Note: This documentation is mainly for Drupal 6/7. For drupal 10, see
Securing file permissions and ownership.
Table of Content #
- Introduction
- Caution: Individual Results will Vary
- Automated Tools to Set Permissions
- Automated Tools to Verify Permissions
- Configuration examples
- Quick lesson in permission's numeric equivalents
- How insecure permissions are a problem
- If you are a sysadmin
- Special considerations for settings.php
- Summarizing the permissions
- Script based on guidelines given above
Introduction #
The server file system should be configured so that the web server (e.g. Apache) does not have permission to edit or write the files which it then executes. That is, all of your files should be 'read only' for the Apache process, and owned with write permissions by a separate user.
Note that this whole article is about "defense in depth." Drupal can run quite safely with permissions a little "looser" than they should be. But if an administrator account is compromised by an attacker or an attacker gains the ability to execute arbitrary code then the configuration below will limit their ability to further exploit your site.
Caution: Individual Results will Vary #
Bear in mind that the process of securing files varies depending on individual server configuration. Always consult your server's documentation for further guidance. The methods for securing file permissions described in this guide assume you are a server administrator with root access to the server.
Site administrators using a Shared Hosting provider commonly lack this level of access and will find many of the methods that follow to be inaccessible due to insufficient privileges. Users of Shared hosting providers should consult that provider's documentation or seek professional assistance.
Automated Tools to Set Permissions #
The File permissions module allows you to automatically set up correct file permissions in your Drupal instance. It uses Drush commands. Most importantly it maintains correct permissions on those directories. That module requires a full Root access to your server. Because this is all about permissions. This module will likely work with most hosting suppliers such as dedicated or vps. It would not work on shared hosting without full Root access.
Automated Tools to Verify Permissions #
As a quick test to confirm whether your site is secure or not you can run the Security Review module. However, this module may from time to time report false positives. To avoid being confused by these you need to check the module's issue queue to see if there any open issues that is about false positives.
Configuration examples #
For example, on many systems the Apache process runs as a user called "www-data" that is in a group called "www-data". This user should be able to read all of the files in your Drupal directory either by group permissions or by "other" permissions. It should not have write permissions to the code in your Drupal directory. If you use features of Drupal which require the "files" directory, then give the www-data user the permission to write files only in that directory.
The following is an example file listing of a safe configuration showing two files in a site where uploaded files are stored in the "files" directory. In order to see the file permissions set for your setup, go to the command line and type: ls -al
.
drwxrwx--- 7 www-data greg-group 4096 2008-01-18 11:02 files/
drwxr-x--- 32 greg-user www-data 4096 2008-01-18 11:48 modules/
-rw-r----- 1 greg-user www-data 873 2007-11-13 15:35 index.php
In the above example, the web server user has the ability to write in the files directory, any users in the group "greg" can read and write the data as well, but other users are not allowed to interact with that data. The "index.php" file (representative of all code files) can be edited by "greg" and can be read by the www-data group (we assume the www-data user is in the www-data group). No other users can read that file. This is a fairly secure method of configuring your site. You generally don't want random users who have the ability to read files on your server to see inside those files, hence the last three permissions are --- instead of r-x.
Below is an insecure setup:
NOTE: THIS IS AN INSECURE CONFIGURATION
drwxrwx--- 7 www-data www-data 4096 2008-01-18 11:02 files/
drwxrwx--- 32 greg-user www-data 4096 2008-05-16 11:48 modules/
-rw-rw-rw- 1 www-data www-data 873 2007-11-13 15:35 index.php
This configuration allows the www-data user to edit the index.php file (and since it is representative of other files, we assume every file that makes up the Drupal site). This configuration is dangerous for the reasons outlined below. If you are using a configuration like this, please change it immediately to be more like the first version. Instructions for making the necessary changes are given below for Linux Servers.
Quick lesson in permission's numeric equivalents #
On Unix-like servers (including Linux), permissions for files and directories can be specified using letters (e.g., "r" for read, "w" for write, and "x" for execute bits) or numbers. The numbers 4, 2, and 1 are conversions of these bits from binary, and correspond directly to read, write, and execute. The instructions below use the alphabetic notation because it is easier to read, but you often will see permissions given in numeric notation in the Drupal Handbook and many other How-Tos. Below are examples of the alphabetic notation and the numeric equivalent:
rwx == 111 binary == 7
r-- == 100 binary == 4
--- == 000 binary == 0
Unix filesystems assign permissions to three different categories of possible users -- owners, members of a security group defined on the server (e.g., using the groupadd
command in Linux, the pw
command in FreeBSD or the dseditgroup
command in OSX), and everyone else. Each of these categories is assigned permissions using the alphabetic or numeric notation explained above via the chmod
command.
The permissions for a file or directory can be displayed using the ls -l
command. The display shows file or directory permissions in the first column in alphabetic notation. The first character indicates the type of directory item, with a "d" whether the file system entity is a directory; a "-" is shown if the entity is a file. The next three letters show the permissions for the user-owner of the file or directory. The next three letters show permissions for the group-owner of the file or directory. The last three letters show the permissions for everyone who is not the user-owner or a member of the group that owns the file or directory. For example:
drwxr-x--- 10 joe www-data 4096 Oct 15 14:15 ./
drwxr-xr-x 13 root root 4096 Oct 11 14:50 ../
-rw-r----- 1 joe www-data 6553 Aug 1 12:27 authorize.php
-rw-r----- 1 joe www-data 70700 Aug 1 12:27 CHANGELOG.txt
-rw-r----- 1 joe www-data 5267 Oct 12 22:47 .htaccess
drwxr-x--- 4 joe www-data 4096 Oct 15 14:23 includes/
-rw-r----- 1 joe www-data 529 Aug 1 12:27 index.php
So, in the listing above, the index.php
file is owned by the user joe
and the group www-data
(usually the name of the Apache user and group on Debian-based systems). The permissions allow joe
to read and write the file but allow users in the www-data
group only to read the file (except joe, of course, who has owner permissions).
Addendum on chmod Non-Numeric Permission Notation #
When used in the chmod
command, the symbols below have the meanings given:
"+" = add a permission to the ones already assigned
"-" = revoke a given permission maintaining the others already assigned
"=" = ignores the already assigned permissions and assigns the permissions specified
"u" = user
"g" = group
"o" = others
"a" = everybody / all (user, group, others)
For files:
r = read
w = write
x = execute
For directories:
r = list (read directory contents)
w = write
x = can access the directory (i.e., cd
to the directory)
Using chmod
without numeric values makes it more human-readable. These are some examples of how to use it:
chmod commands and results for a file with permissions rwxrwx--- (770) |
||
---|---|---|
chmod human | chmod numeric | resulting permission |
ugo=rwx | 777 | rwxrwxrwx |
u-wx | 470 | r--rwx--- |
o+r | 774 | rwxrwxr-- |
g-wx,o+r | 744 | rwxr--r-- |
u-w,g-wx,o+r | 544 | r-xr--r-- |
g=,o=r | 704 | rwx---r-- |
a-wx | 440 | r--r----- |
Note: Because of the way Unix filesystems work, all files and directories created by the Apache server will be created with an owner that is the same user as is running httpd
. In Linux, you can handle this with a useful tool called fsniper. It uses iNotify to check for newly created/modified directories and files and you can apply whatever action you want through customized scripts on them in real time. So you can create scripts to change ownership of files and directories automatically. This solution doesn't work (and isn't required) in Microsoft Windows because of NTFS "permission inheritance".
TIP: The following command may also deal with different 'x' for files and dirs:
[root@localhost]chmod go+rX
The uppercase X will add the execute permission only to directories leaving regular files untouched. Both files and dirs would get read permission added.
How insecure permissions are a problem #
If you allow your site to modify the files which form the code running your site, you make it much easier for someone to take over your server.
Worst case scenario: a file upload tool in Drupal allows users to upload a file with any name and any contents. This allows a user to upload a mail relay PHP script to your site, which they can place wherever they want to turn your server into a machine to forward unsolicited commercial email. This script could also be used to read every email address out of your database, or other personal information.
Undesirable scenario: if the malicious user can upload a file with any name but not control the contents, then they could easily upload a file which overwrites your index.php (or another critical file) and breaks your site.
Undesirable scenario: if the code allows users to see the contents of files, attackers could see information which might reveal potential attack vectors.
If you are a sysadmin #
Disclaimer: Don't risk following these instructions blindly; each system has its own peculiarities and, because of that, the instructions here MUST be altered to suit your needs. All of the instructions here are aimed at people who are familiar with filesystem permissions and know exactly what all the commands written here mean. If you try to follow these instructions without paying full attention to what you are doing, you are very likely to get into trouble. These instructions are designed to alter filesystem permissions as a root-level user, so tread carefully!
Note for hosted Drupal installations #
This installation method presumes one shared drupal core and many subdomains installed under it. So suppose you are the owner of a hosting service that has a Drupal installation already pre-configured and you want to sell a hosted Drupal site with pre-configured Drupal core to your clients. So when you sell it, you create their user on the server and let them configure their own Drupal site just entering their site's address to open the install page. The way this document suggests the configuration, it will prevent customers from modifying and accessing the Drupal core files and other customer's sites files and directories.
It is important to notice that the user ownership of Drupal's core directories/subdirectories and files is given to the user who administers Drupal (usually root) and group ownership is given to the group your apache is running on. For files and directories inside the "sites" directory the user who is hosting the site on your server is their owner. One way to do this is to delete the "sites" directory under Drupal's root directory and make it a symbolic link to /home or another path you use to store user's home directories. That way, if you create user names that matches the customer's site URL, no permission will need to be changed. The only thing to be done is to change the directory group ownership to the group your apache is running on.
cd /path_to_drupal_installation
mv sites/* /home
rmdir sites
ln -s /home sites
useradd www.example.com
chown -R www.example.com:www-data /home/www.example.com
The permission required by Apache is given through group permission and others have no access at all to any files and directories on a Drupal installation. Don't give any permissions to "others", otherwise if your system is hacked through a user's weak password, the hacker will be able to access all files and directories of all installed sites on your server, not only the one invaded. Even a read-only permission must be avoided. Remember that the user name and password to connect to the database for each site are stored in settings.php. Worse still, if you give write permission to others, the hacker will be able to alter files to damage your site or upload malicious scripts to your server.
The instructions in this guide assume a non-hosted installation, so modify the ownership to match your situation as necessary, e.g. where you see "greg" in these instructions, replace "greg" with the name of the user (often root, but not necessarily) who administers your installation of Drupal.
Linux servers #
Permissions for files and directories on a Linux system are adjusted using the chmod
command. User-owner and group-owner identity for files and directories are adjusted using the chown
command.
The code below demonstrates one method for changing the ownership and permissions of files and directories in the Drupal Root directory to confirm ownership and permissions to the recommendations above. We assume in the example below that the user greg
is part of the greg
group and that user greg
is the site owner. We also assume that you are running Drupal on a server that is not in a hosting environment which provides website hosting services to multiple customers.
Make sure you run the following commands from inside Drupal's root directory! If you run these commands from any other directory, you either will not make changes to all of the Drupal installation's files and directories or you will make changes to files and directories other than those in the Drupal installation. Neither alternative is your goal.
[root@localhost]cd /path_to_drupal_installation
[root@localhost]chown -R greg:www-data .
[root@localhost]find . -type d -exec chmod u=rwx,g=rx,o= '{}' \;
[root@localhost]find . -type f -exec chmod u=rw,g=r,o= '{}' \;
Note: Within a CentOS environment, you may need to use the apache
group instead of the www-data
group, which will change your second line to:
[root@localhost]chown -R greg:apache .
The second command makes user greg
the user-owner and group www-data
the group-owner of all files and directories in Drupal's root directory and all subdirectories and files in those subdirectories (the -R switch means recursive). Note that in a multiple-customer hosting environment, the user-owner of the Drupal files and directories should be root
.
The third command in the example finds all directories and subdirectories in Drupal's root directory and executes the chmod
command on all of those directories and subdirectories (-type d means filesystem entities that are directories). The command changes the permissions to read, write and access for user greg
and read and access for users in the www-data
group. Users who are not greg
and not in the www-data
group cannot read, write, or access the directories or subdirectories in the Drupal root directory. In numeric notation, the permission assigned to these directories and subdirectories is 750.
The fourth command finds all files in the Drupal root directory and its subdirectories and changes the permissions on those files to read and write for the user greg
and read only for the www-data
group. Other users have no access to these files. The numeric notation for this set of permissions is 640.
For the "files" directory in the sites/default directory and any other site directories in a multi-site installation, the permissions are slightly different because the www-data
user must have write permission to the directory:
[root@localhost]cd /path_to_drupal_installation/sites
[root@localhost]find . -type d -name files -exec chmod ug=rwx,o= '{}' \;
[root@localhost]for d in ./*/files
do
find $d -type d -exec chmod ug=rwx,o= '{}' \;
find $d -type f -exec chmod ug=rw,o= '{}' \;
done
The second command above finds all subdirectories named files
below the sites
directory and changes the permissions for the user-owner and the group-owner to read, write, and access. All other users cannot read, write to, or access these files
subdirectories.
The "for" loop above is written for an sh-style shell (sh, bash,ksh). If you use csh or tcsh, type bash
before executing the command. These commands in the loop give read, write, and access permissions to user greg
and group www-data
to all subdirectories and files within the files
but not access to other users. The numeric permissions code is 770.
Remember that any newly installed module/theme or whatever add-on must have its permissions changed too. It's better to do this BEFORE installing the module, theme, or add-on in its appropriate Drupal directory.
Windows servers #
By default, Apache runs in the built in SYSTEM account. So all you have to do is change the permission in a way that only the SYSTEM account, the administrators group and the user greg have access to the Drupal root directory, subdirectories and files (assuming greg is the site owner).
You should exclude all other users and groups from the ACL. For the SYSTEM account give read only access to all Drupal directories, subdirectories and files except for the "files" directories which require write permission. For the user greg give read, modify and write permissions. And for the administrators group give complete access. Go to the Drupal root directory, right click on it, go to properties and then security.
Make use of permission inheritance to make things easier for yourself. And remember that any newly installed module/theme or add on must have its permissions changed too. It's better to do this BEFORE installing it in its appropriate Drupal directory. Permission inheritance is done automatically by Windows.
Special considerations for settings.php #
The settings.php file contains the database password and username in plain text and, once created, must be set so that only appropriate users can read it. That usually means removing read permissions for the "other" user.
Summarizing the permissions #
- drupal_admin: the user on the server that administrates Drupal, not necessarily is the root.
- site_admin: the owner of the hosted site (a customer)
Ownership #
Core modules/themes files and directories: drupal_admin:www-data
Hosted sites modules/themes/files files and directories: site_admin:www-data
Permissions #
Core modules/themes directories: rwxr-x---
Core modules/themes files: rw-r-----
Hosted sites modules/themes directories: rwxr-x---
Hosted sites modules/themes files: rw-r-----
Hosted sites "files" directory: rwxrwx---
Hosted sites files under "files" directories: rw-rw----
Hosted sites subdirectories under "files" directories: rwxrwx---
Follow this guide exactly as it is to make your Drupal installation as secure as possible. This guide was tested and works. If something goes wrong with your installation, review the steps — possibly you missed something. If it really doesn't work, post a comment with your issue, and someone will fix this guide.
Script based on guidelines given above #
If you need to fix permissions repeatedly then the following script will help you, it is based on the guidelines given above and performs some checks before any modification to ensure it is not applied on files/directories outside your Drupal installation.
#!/bin/bash
# Help menu
print_help() {
cat <<-HELP
This script is used to fix permissions of a Drupal installation
you need to provide the following arguments:
1) Path to your Drupal installation.
2) Username of the user that you want to give files/directories ownership.
3) HTTPD group name (defaults to www-data for Apache).
Usage: (sudo) bash ${0##*/} --drupal_path=PATH --drupal_user=USER --httpd_group=GROUP
Example: (sudo) bash ${0##*/} --drupal_path=/usr/local/apache2/htdocs --drupal_user=john --httpd_group=www-data
HELP
exit 0
}
if [ $(id -u) != 0 ]; then
printf "*************************************************\n"
printf "* Error: You must run this with sudo or root *\n"
printf "*************************************************\n"
print_help
exit 1
fi
drupal_path=${1%/}
drupal_user=${2}
httpd_group="${3:-www-data}"
# Parse Command Line Arguments
while [ "$#" -gt 0 ]; do
case "$1" in
--drupal_path=*)
drupal_path="${1#*=}"
;;
--drupal_user=*)
drupal_user="${1#*=}"
;;
--httpd_group=*)
httpd_group="${1#*=}"
;;
--help) print_help;;
*)
printf "************************************************************\n"
printf "* Error: Invalid argument, run --help for valid arguments. *\n"
printf "************************************************************\n"
exit 1
esac
shift
done
if [ -z "${drupal_path}" ] || [ ! -d "${drupal_path}/sites" ] || [ ! -f "${drupal_path}/core/modules/system/system.module" ] && [ ! -f "${drupal_path}/modules/system/system.module" ]; then
printf "**********************************************\n"
printf "* Error: Please provide a valid Drupal path. *\n"
printf "**********************************************\n"
print_help
exit 1
fi
if [ -z "${drupal_user}" ] || [[ $(id -un "${drupal_user}" 2> /dev/null) != "${drupal_user}" ]]; then
printf "***************************************\n"
printf "* Error: Please provide a valid user. *\n"
printf "***************************************\n"
print_help
exit 1
fi
cd $drupal_path
printf "Changing ownership of all contents of \"${drupal_path}\":\n user => \"${drupal_user}\" \t group => \"${httpd_group}\"\n"
chown -R ${drupal_user}:${httpd_group} .
printf "Changing permissions of all directories inside \"${drupal_path}\" to \"rwxr-x---\"...\n"
find . -type d -exec chmod u=rwx,g=rx,o= '{}' \;
printf "Changing permissions of all files inside \"${drupal_path}\" to \"rw-r-----\"...\n"
find . -type f -exec chmod u=rw,g=r,o= '{}' \;
printf "Changing permissions of \"files\" directories in \"${drupal_path}/sites\" to \"rwxrwx---\"...\n"
cd sites
find . -type d -name files -exec chmod ug=rwx,o= '{}' \;
printf "Changing permissions of all files inside all \"files\" directories in \"${drupal_path}/sites\" to \"rw-rw----\"...\n"
printf "Changing permissions of all directories inside all \"files\" directories in \"${drupal_path}/sites\" to \"rwxrwx---\"...\n"
for x in ./*/files; do
find ${x} -type d -exec chmod ug=rwx,o= '{}' \;
find ${x} -type f -exec chmod ug=rw,o= '{}' \;
done
echo "Done setting proper permissions on files and directories"
Copy the code above to a file, name it "fix-permissions.sh" and run it as follows:
sudo bash fix-permissions.sh --drupal_path=your/drupal/path --drupal_user=your_user_name
Note: The server group name is assumed "www-data", if it differs use the --httpd_group=GROUP argument.
If you have sufficient privileges on your server
- Place the file in
/usr/local/bin
sudo chown root:root /usr/local/bin/fix-permissions.sh
sudo vi /etc/sudoers.d/fix-permissions
and enter the following line in the fileuser1, user2 ALL = (root) NOPASSWD: /usr/local/bin/fix-permissions.sh
- Save the file and then
sudo chmod 0440 /etc/sudoers.d/fix-permissions
Note: Substitute your desired comma separated list of users where you see user1, user2
above. Alternatively, you could enter an ALIAS for a user list. Run man sudoers
for more information on formatting the line.
What the /etc/sudoers.d/fix-permissions
accomplishes is making the script available to a set of users via the sudo command without having to enter a password.
Assuming that /usr/local/bin
is in the user's path (and it should be), then the script can be run from anywhere using
sudo fix-permissions.sh \ --drupal_path=/path/to/the/drupal/install \ --drupal_user=your_desired_user
.
Note: The "\" is being used here to help avoid bad line breaks in the display of the page.
See also:
- What are the recommended directory permissions in Drupal 7?
Comments
re: find . -type d -name
re: find . -type d -name files -exec chmod ug+rwx,o-rwx {} \;
This only works for a new site (e.g. one that doesn't already have files in the /sites/[site]/files directory).
For the hardening of an existing site,`find . -type f -exec chmod u+r-wx,g+rw-x,o-rwx {} \;` sets all of the files inside sites/[site]/files to be read-only, and `find . -type d -name files -exec chmod ug+rwx,o-rwx {} \;` will only affect new files; anything currently existing in the /files folder will still be read-only. A `chmod -R ug+rwx,o-rwx /[path to site]/files/*` should fix this.
Thanks for the howto.
I think there may be a problem with your recommended fix
chmod -R ug+rwx,o-rwx /[path to site]/files/*
This command gives execute permissions for both the owner and group to all regular files residing within the /[path to site]/files/* tree? Isn't this a bad thing?
I believe Drupal itself
I believe Drupal itself prevents files in the /files/ directory from being executable.
The 'execute' (x) permission
The 'execute' (x) permission flag at the filesystem level is for allowing scripts and binaries to be processes that run on the server shell etc.
While the Apache rule in the .htaccess in /files/ (provided by Drupal) only tells the webserver not to evaluate PHP files in that directory as PHP.
These are different rules with different meanings. And yeah, you really do not want 'x' permissions on (any) web files, as it's just a mistake.
.dan. is the New Zealand Drupal Developer working on Government Web Standards
Permisson Configuration
Well, if you want to restrict the permissions to directory only please use capital x i.e 'X',
recommended permissions created more errors for me
I went into my ftp and changed permission as your recommendation and it created more problems. Please advise.
Warning: filemtime(): stat failed for themes/stark/stark.info in _system_rebuild_theme_data() (line 2551 of /var/www/html/prod/modules/system/system.module).
Warning: filemtime(): stat failed for themes/garland/garland.info in _system_rebuild_theme_data() (line 2551 of /var/www/html/prod/modules/system/system.module).
Warning: filemtime(): stat failed for themes/bartik/bartik.info in _system_rebuild_theme_data() (line 2551 of /var/www/html/prod/modules/system/system.module).
Warning: filemtime(): stat failed for themes/seven/seven.info in _system_rebuild_theme_data() (line 2551 of /var/www/html/prod/modules/system/system.module).
Notice: Undefined property: stdClass::$owner in _drupal_theme_initialize() (line 209 of /var/www/html/prod/includes/theme.inc).
Warning: include_once(/var/www/html/prod): failed to open stream: Permission denied in _drupal_theme_initialize() (line 209 of /var/www/html/prod/includes/theme.inc).
Warning: include_once(): Failed opening '/var/www/html/prod/' for inclusion (include_path='.:/usr/share/pear:/usr/share/php') in _drupal_theme_initialize() (line 209 of /var/www/html/prod/includes/theme.inc).
No
It's nuts that web server should own the site. In all normal cases your regular user (that you do your regular ssh, scp or ftp access with) should should own the installation files.
Anyway, this regular user should normally own an html area exclusively, from which the web server serves the pages of the host/virtualhost, that is only readable and searchable to others (i.e. the web server). After ensuring that this is the case the user then normally copies or uploads the contents of the distribution into the html area, thus maintaining ownership and sane permissions. The user then grant the web server read, write and search permission to the files directory of the site by changing the group access. Optionally, the user also gives up his own write permissions for the files directory (in order not to tamper recklessly with this area as it should be managed exclusively by the web server).
There's really no need for recipes, if the user doesn't grasp this he simply needs to do UNIX permission homework or else he'll never be secure. If that is the case, enter the following into shell or Google:
man chown
man chgrp
man chmod
Thanks for the advice. After
Thanks for the advice. After reading your post, I found the following relevant information:
http://www.onlamp.com/pub/a/apache/2004/05/28/apacheckbk.html
"Apache runs as the user specified in the User directive. Files need to be readable by that user. Directories need to be +x (searchable) by that user. CGI programs need to be runnable (+x) by that user."
A question
User apache is completely unpriviledged and has no login shell. A question, supposing that the file index.php in drupal's root have these file permissions: -r--r----- 1 apache apache 980 Mai 18 15:25 index.php. Would it be possible to an attacker explore an Apache vunerability to take advantage of the ownership by apache to execute a chmod on it and alter the permission in a way that it becomes writeable and then modify or overwrite it uploading a hacked one?
Shell or no shell
Shell or no shell, as long as the user the server and the php scripts runs as owns files and directories, it can also alter them. Owning files is a privilege. So if your server, or php, or Drupal has a hole, or most likely, if you accidentally allow someone to plant some php code, you're in trouble.
Understood
Thank you for your clarification, when you told about this on the comment I became worried because I didn't think of this possibility. Now that you explained how it can be achieved I saw the problem and modified all my permissions in the server to u=rwx,g=rx,o= for directories and u=rw,g=r,o= for files and the ownership is site_owner:apache. This way only site_owner can chmod the files and directories.
doesn't work
Hi, permissions above look pretty tight. However it doesn't work ... at least for me (Ubuntu 8.04 x64 serv), I don't know which files have to be writable, executable etc ... but with these permissions I am getting only "Forbidden - u don't have permissions ....." to whole drupal subdirectory, when I set drupal directories to "chmod 1755" and files "chmod 1644" it's much better (perhaps sticky bit is not necessary), i can work in any case at it's very important for me (newbie in drupal). I would like to have secure site at the same time, therefore I tried permissions here from "wiki", i have experimented with them about 2 hours and ended up with working ones as I mentioned above. I haven't tried to edit .htaccess, perhaps there is also some possiblility to achieve usefull behavior.
----edit-----
as mike_waters points out directories need to be executable (x) so one has to # find . -type d -exec chmod u=rwx,g=rx,o=x {} \; this fix the problem, I should have read carefully his post. It could save me 3 hours of trying and googling ...
Everything is right on this post
If you have read those 3 commands on the beginning of this howto carefuly you should have seen that for directories it has an x to permit access.
[root@localhost]cd /path_to_drupal_installation
[root@localhost]chown -R greg:www-data .
[root@localhost]find . -type d -exec chmod u=rwx,g=rx,o= {} \;
[root@localhost]find . -type f -exec chmod u=rw,g=r,o= {} \;
I needed to modify thos
I needed to modify thos commands to
find . -type d -exec chmod u=rwx,g=rx,o=rx {} \; - that's 755
find . -type f -exec chmod u=rw,g=r,o=r {} \; - that's 644
Otherwise my Bluehost hosted Drupal site shows Forbidden when I try to access it.
I also had to modify the permissions
I am using Hostgator and the documented code broke my site. Being a newbie I panicked because I didn't know what files and folders I just changed. Luckily, I found this post and was back up and running.
It is important to note that I could not execute the first line:
chown -R greg:www-data .
I omitted it when after realizing that chown was not permitted and gave me an invalid user error. Perhaps this is part of my problem.
Small side note, I experimented with:
find . -type d -exec chmod u=rwx,g=rx,o=r {} \;
and my site still worked but had no styling. I suppose there is a use for that down the road.
Hey, it's wrong giving to
Hey, it's wrong giving to others any kind of permission and the user greg, if you read carefully, was used as an example and you MUST change it for the proper user that administrates Drupal(usually root or your user). Look at this: "To set the permissions all at once you can issue these commands from the Drupal root directory. I'm assuming that greg user is part of greg group and that greg is the site owner." It´s just an assumption just to explain a situation not an obligation. READ CAREFULLY AND REPEAT THE STEPS, YOU SURELY MISSED SOME STEP!
This documentation is for site administrators, newbies must know deeply about Linux permissions scheme before using this guide.
Yay!
Awesome, these two lines are just what I needed to get my site running up at GoDaddy. Sheesh, what a frustrating week it's been. Thanks!
ACL Support
ACLs are an under-used feature of Linux. It's great for web development, as the server can have one set of permissions while the developers have their own. However, I don't think Drupal supports this, because it thinks that the server has write permissions to a directory that it doesn't have write permissions to.
Being brand new to Drupal, I could be wrong, but I believe I'm interpreting the example below correctly.
Securing the files directory permissions properly
This command is not so secure because some contrib modules contain 'files' directories such as feedapi, and in core we now have ./modules/simpletest/files
Also, it does not cover the case where you have existing files in it the 'files' directory. I can't find a better way other than running the following commands from each sites/SITENAME/files directory:
I'm happy to update the documentation with this, but maybe someone has a better way of doing this?
Uppercase x permission
I've added an uppercase x execute permission tip that applies only to directories.
HTH.
numeric values
Many of us work through FTP programs, and not the command line.
Could you please post info on the numeric values corresponding to the CHMOD equivalents you listed here?
Thanks!
Summary of permissions and numeric values
Like two_wheeler, I need to use the numeric values.
As I read (and re-read) the instructions in this document under Linux servers, and combine that with the information from Mike_Waters, I think this is what they mean.
If someone in-the-know could confirm or correct this it would be a big help.
Thanks!
why cannot have this permission
with folder files/images;
If I set rwxrwxr-x and owner root I cannot upload images
# Directory "iimages" is not accessible under file system!
# Unable to get a working directory for the file browser
If I set rwxrwxrwx and owner root I can upload images
but the module alert that
Some files and directories in your install are writable by the server
If I set rwx------ and owner apache I can upload Image but always same alert's message
why cannot use this
rwxrwxr-x owner root ?
os centos and imce with fckeditor
other:
Security Review also alert regard html full, which html tags is preferable to remove from html full?
server does not run as root
Usually, server run as user www-data or nobody. So if you have your files owned by root, only if "others" with the relevant permissions will be accessing them. Check owner and groups in the "Configuration examples" at the beginning of this post.
files directory permissions for CentOS
on CentOS (which many cPanel servers use), cd to the public_html directory if necessary, then:
chown -R nobody:nobody /sites/default/files
This will make the apache web server able to upload images including with ckeditor/imce
Just figured this out after a day of struggles hope it helps someone.
CPanel, WHM, VPN
I've decided to update this post. The following leaves me problem free using Drush, CentOS, WHM and CPanel.
First, the basic ownership and permissions followed by a cut and paste list of commands.
*Note: update the paths in the commands to match your setup.
Example Setup
CPanel User: username
Site Root: /home/username/public_html
Ownership
Files and folders username:nobody
Temporary Folder username:nobody
Permissions
Update ownership for entire site and tmp folder
chown -R username:nobody /home/username/public_html
chown username:nobody /home/username/tmp
Permissions
find /home/username/public_html/modules -type d -exec chmod 750 {} +
find /home/username/public_html/modules -type f -exec chmod 640 {} +
find /home/username/public_html/themes -type d -exec chmod 750 {} +
find /home/username/public_html/themes -type f -exec chmod 640 {} +
find /home/username/public_html/sites/all/modules -type d -exec chmod 750 {} +
find /home/username/public_html/sites/all/modules -type f -exec chmod 640 {} +
find /home/username/public_html/sites/all/themes -type d -exec chmod 750 {} +
find /home/username/public_html/sites/all/themes -type f -exec chmod 640 {} +
find /home/username/public_html/sites/default/files -type d -exec chmod 770 {} +
find /home/username/public_html/sites/default/files -type f -exec chmod 660 {} +
find /home/username/tmp -type d -exec chmod 770 {} +
chmod 440 /home/username/public_html/sites/default/settings.php
chmod 750 /home/username/public_html/sites/default
-- If no-one asked Drupal questions there would be no Drupal answers --
Good
This is really helpful.
My website was set up via the
My website was set up via the WHM panel that is installed on my GoDaddy VPS server. The server username is "myserver" and the cpanel username for my website is "mywebsite".
When I run these commands via command line, the website shows a "500 Internal Server Error". The commands I used are below:
chown -R mywebsite:nobody /home/mywebsite/public_html
chown mywebsite:nobody /home/mywebsite/tmp
What would cause this?
Also, when I revert back to a clean copy of the site and skip those two commands, and then I run these two commands...
...it causes my admin toolbar to disappear and the Security Review module will no longer run. The rest of the website is displayed correctly. Again, what would cause this issue, and how can I fix it?
Thanks for writing this and
Thanks for writing this and everything, but all that I and 99% of people reading this page really want is a list of numbers next to a list of folders. This just confuses me and makes something really simple into a frustrating and confusing waste of time. Here is the permissions you should set for folders in Drupal 6.x, for those who don't feel like learning apache command line scripting just to set some permissions:
/default on 755
/default/files including all subfolders and files on 744 (or 755)
/default/themes including all subfolders and files on 755
/default/modules including all subfolders and files on 755
/default/settings.php and /default/default.settings.php on 444
Works, tnx
By the way Jason, I followed your indications (thank you!) and it worked :)
I started with Drupal in 2007 and then my life got stuck...
Yes I would put this info at
Yes I would put this info at the top, rather than buried in the comments. This is the heart of what most people want to check, a very quick reference sheet, rather than a wall of text.
:-)
I agree, thanks.
This page is classic Drupal.org. The people who probably most need a tutorial are the people doing their first Drupal site. And these are the people (like me) who probably know how to use a ftp program to change settings and everything else on this page is Greek to them. Thanks Arman for some clear, concise, usable information.
A Big Thank You!
I can't begin to tell you how quickly you resolved my can't write to files directory problem after migration with these simple cut and paste instructions:
Since our community has thousands and thousands of image files, what a time saver! This information helped me understand how to more tightly reign in permissions on files and saved the day for me.
A big thank you.
protoplasm
little bit safer
First of all: thanks for this doc, it's an important part of drupal's usage.
The 1st sentence is the heart of the matter: "system should be configured so that the webserver does not have permission to edit or write the files which it then executes".
'files' directory is an exception, that's why it is a security risk.
If someone can upload script (php) into that folder, your server is broken.
Let's minimize this case:
1.
files/.htaccess should not be writeable by webserver
2.
disable php in that folder, add this line to your files/.htaccess:
(Your server will be safer, if a security hole or a weak admin password allows to upload php files.)
A great idea, but if you
A great idea, but if you grant write permission to the "files" directory itself, that permission could be used to overwrite any .htaccess file within, regardless of the permissions on that file (at least on some OSes). So to really accomplish this, you'll need to put the directives into your main Apache site config. Something like this:
Still Confused
I have some of my sites that have user and group set to apache for everything / all files and dirs. Is this bad? Under the impression that user apache is a special user with very limited permissions.
Also I run my own server so don't need a user for each site I host so I assume if I need to have the user not be apache I can just create a user eg webdude and use them for all my sites or is this less secure?
You must create it and you
You must create it and you must use this user. If a user is the file and directory onwer all limitations go to the ground. You simply can put an script to change permissions and ownerships as you want, hackers will do it undoubtedly
Audit what is currently writable
From a serverfault thread
To see if your webserver can write to anything that it's not supposed to, if you have sudo, you can run
- this will list anything writable by the apache user - it should be empty after your site
files
dir is excluded.It will just list, not fix it for you (the commands in the OP will do that for you).
.dan. is the New Zealand Drupal Developer working on Government Web Standards
centos find command
on centos would that be: sudo -u apache find . -type d -perm /u=w | grep -v sites/default/files ?
In summary...using FTP for file permissioning
Hi lsrzj, would you please confirm my translation of your documentation and your script per below:
I need to use the numeric values to apply permissions via FTP for a site hosted on Bluehost.
I reviewed the security script suggested in the document, under the heading: "Script based on guidelines given above". I am yet to test this but I believe it means:
1. [@ ROOT] DRUPAL CORE PLUS OUR ADDED MODULES & THEMES
2. [@ /SITES] DRUPAL SETTINGS
3. [@ /SITES/.../FILES] WRITEABLE FILES in /sites/all/default/files folders : (like images, file attachments etc)
these folders/files are the exception so that Drupal can delete the files attached to posts when they are deleted etc.
4. REDUCING WRITABLE FILES VULNERABILITY
Addtitional recommendation by: herend on February 24, 2011 at 11:57am
"...system should be configured so that the webserver does not have permission to edit or write the files which it then executes". So the server will be safer, if a security hole or a weak admin password allows to upload php files.
1. files/.htaccess should not be writeable by webserver
2. disable php in that folder, add this line to your files/.htaccess:
AddHandler default-handler php
I hope this is a correct translation and likely to work! I will investigate and attempt. Any confirmation from lsrzj or others, that this looks sensible, would be appreciated.
On my site www-data has no premissions and the site works. Why?
I have a test site setup automatically with user=me group=me. How is www-data not even factored into this and the site works just fine. According to this tutorial. apache needs to have at least read access to the files but the www-data group/user has no permissions. Only my user/owner has permissions.
All I did was download drupal and extract it and the site works fine. Working with all the permission setting above gives me all types of problems. Such as the login page not being responsive.
On a traditional system...
There are at least *three* pseudo-groups that have their own permission set. 'owner', 'group', and 'other'
It would be normal for a host that set your user up with a web directory to assume that you wanted stuff you put there to be world-readable, so the 'other' permissions probably include the normal 'read-only' permissions, and www-data can read and serve your files.
There are now a number of extended file system properties that allow even more control than that, but in this case, they are probably not an issue.
.dan. is the New Zealand Drupal Developer working on Government Web Standards
And the right way for the Linux?
I wonder why there were no a single word about Linux ACLs while they do really good job.
Recently I was trying to setup permissions/owns for a website to provide access to another developer and faced the fact that technically it is impossible to achieve the result that would secure enought and flexible using old-style linux fs security. I will demonstrate what I mean.
Suppose we have next setup:
Users:
customer - site's owner
dev1, dev2 - two developers
apache - apache user
Reqs:
1) customer, dev1, dev2 - should have r/w access to the site
2) apache - should have r/w access to the site's /sites/all/files dir only
3) any changes to site's files shouldn't break the requirement 1-2. For example, files created by apche should be r/w accessible to customer, dev1 and dev2 and vice versa.
4) nobody else should have access to the site
I'm gonna skip considering different "tranidional" approaches to achieve above, including running patched apache which can set specific owner/owning group (vie AssignUserID for example), for only reason - it would be either impossible or ugly to the extreme.
Now I'll show how to do this with simple native Linux ACLs. Let us assume the site root is under 'www' dir of the current directory and all the files are owned by the `customer` user and the `customer` group.
1) adding customer user and group to the "write list" for all the files:
2) adding dev1 and dev2 to the "write list" for all the files:
3) adding apache user to the "write list" for sites/default/files:
That's all. Note - not a single chmod/chown issued. Let us see file permissions now with example output from real setup (customer = mosaicum, dev1 = fantomas, dev2 = doka, apache as is):
Advantages:
1) You don't need chmod/chown. You don't even need chmod g+s'ing
2) You don't need to reissue commands (if only some outdated software which doesn't respect ACLs will break them) - acls are inherited (thanks to "-d")
3) You ain't depending on who creates files no more - you just don't care about owners - and they now go like the should - preserving names. So for example if it was you, who last uploaded a new version of a file - then it will be owned by you and your group, but the staff don't lose control over it.
UPDATE:
*
drush dl
breaks ACLs since it moves (renames) downloaded and extracted files from /tmp to the site's dir (and while moving ACLs/owners/permissions never copied - this is "by design").But thanks to drush developers, shell's rename is inside
drush_move_dir()
which has a workaround in case when system rename "doesn't work": files from /tmp are first copied to the site's dir and then unlinked from /tmp. When acting like this, ACLs are applied/preserved. To make system rename doesn't work you just add one line to either /etc/drush/php.ini or ~/.drush/php.ini:*
tar zxf module.tar.gz
would likely extract module which will become r/o for all the groups and named users. I think this is because tar preserves r/o for groups permission when creating archive and when extracting, this changes "mask" attribute of extended ACL to become "r-x" and not "rwx".Well, I didn't find how to make tar to extract ignoring mode (or rather with mode changed to 666). But to change the mask back you can either use setfacl again, or just issue this right after tar zxf:
Group memberships..
Great page but perhaps needs to make mention of the fact that any files uploaded will be owned by www-data:www-data..
Only ways I know of to get around this are..
1. Add the user to the www-data group - Problem here is that the user then has access to everything that www-data has access to potentially including other users files (if you have more than one user/site on the server.. If its a single site server this isn't such an issue)..
2. Set the UID on the writeable directories so that newly created files inherit the user..
3. Create a separate group and make www-data and the user members of the group.. Use this new group when setting permissions and set the GID of the writeable directories to the new common group..
Not sure which way is best or most secure but think that whichever is felt to be best is detailed on the page..
It works only for dedicated
It works only for dedicated servers or VPS.
It is not useful at all for shared hosting solutions.
Apache should work with client username or user will not be able to even change or delete uploaded via apache files!
Plus many other problems, specially when user try to move from one web hosting company to other.
And I don't even talk about newbies! They will go nuts.
It works for hosted
It works for hosted installation. Note that the OWNER of each site's subdirectories and files will be each client's system logins so if you have a site www.example.com and the hosting service create a user www.example.com, the owner of all files and directories inside it will be your user. The OWNER can do whatever he wants to do with the directory, move files, delete files.... the Apache permission is given through GROUP permissions, Apache MUST NEVER be the owner of the files. The problem is that apache will try to create the files and directories with it's user. So I'm open to suggestions to solve this issue, there must be a way to do it. Is there a point to install one apache for a single user and run multiple instances of it, each apache running under the costumer's user name?
If apache works from NOBODY
If apache works from NOBODY (for example) - all created files and directories via drupal will be own by nobody.
User will not be able to chown it, because CHOWN restricted to root user only.
Also user will not be able to chmod it, because he is not own it.
When regular (no shell experience at all, no unix permissions knowledge ) user see this situation, he just put 777 on all dirs and files in sites/default/files.
And it is a big security hole.
For shared hosting there is no simple way to have php files owned by user, web host by apache and don't have any file permissions issues.
And don't forget. Shared hosting is mass hosting. Users pay only ~$5/month and they just need to see they own website online.
They don't want to play with permissions, owners and etc. Any limitations will push them away.
UPD: there is only way to process each request via user's id for apache. But it is mean, that user will be able to change any file.
I checked that there is a way
I checked that there is a way to inherent parent directories permissions using POSIX ACLs, so using this, apache will create, automatically, files and directories owned by the users.
Sounds good. But if php under
Sounds good.
But if php under apache works with apache user and I have admin role with a right to write node with php code - I can read any settings.php on all websites and hack few more websites then.
Safe mode will save from it, but it will make problems - http://drupal.org/node/324295.
Slight correction to your
Slight correction to your thinking..
Apache doesn't create or delete files.. PHP does..
Apache only needs read permission to files/directories..
Running PHP as the owner of the scripts can be accomplished in a number of ways.. Typically with apache modules like SuEXEC or SuPHP.. It can also be done with MPM-ITK or running PHP-FPM with individual pool configurations..
There are pro's and cons to all these options and some will need specific permissions and/or group memberships..
You will just have to research what is going to work for your particular setup..
I read the previous comments,
I read the previous comments, but I'm still confused... Is there a suggested configuration for files/folders permissions on a shared hosting?
Right now my files are on myusername:myusername ownership.
I don't have permissions to chown to myusername:nobody (nobody:nobody = apache), and I have set o+r (o+rw to 'files' directory), which doesn't make me feel comfortable.
Yes, there are. Look at If
Yes, there are. Look at If you are a sysadmin section.
Hello delxpez sysadmin - mean
Hello delxpez
sysadmin - mean you have a right to be root and you don't.
Basically there is no way to follow this recommendation on any shared hosting! It is my personal opinion.
All this words just for Guys who has root access!
I understood you, but this
I understood you, but this install method presumes one shared drupal core and many subdomains installed under it. So suppose you are the owner of a hosting service that has a Drupal already pre-configured and you want to sell a hosted Drupal site with pre-configured Drupal core to your clients. So when you sell it, you create their user on the server and let them configure their own Drupal site just entering their site's address to open the install page. The way we suggested the configuration, you will prevent costumers from modifying and accessing the Drupal core files and other costumer's sites files and directories.
Find Syntaxt
Just curious on this part but shouldn't all of the find commands, for consistency purposes, have their {} wrapped in single quotes? So instead of:
It would look like:
And then in the "for" loop the same thing would apply:
According to the find manual, "[...] the braces are enclosed in single quote marks to protect them from interpretation as shell script punctuation."
Yes, it should be quoted with
Yes, it should be quoted with single quotes. Thank you, the commands were corrected
Apache user
Hi guys,
if ever there is a way to recover the apache user automatically:
apache_group=$(ps axho user,comm|grep -E "httpd|apache"|uniq|grep -v "root"|awk 'END {if ($1) print $1}')
I have tested this in Ubuntu 11.04 and CentOS 6 and it works perfectly.
is there anywhere a comprehensive guide?
I've gone through this entire thread and am still lost. Is there a comprehensive guide to file / directory permissions? I work almost exclusively on shared hosting packages, and just need a guide to tell me:
Drupal core directories and files: I have everything set to 755. Good? Bad?
everything in sites/* is set to 755 except default.settings.php and settings.php. I tried to set them to 444 but they revert to 644 every time.
Using FileZilla to set the permissions, btw.
I have checked index.php and it is at 644, as is .htaccess.
The site is currently in a subdomain named 'beta' which points to a folder also called 'beta' inside the root. Both the beta directory and the root directory (public_html) are set to 750.
This is for a Drupal 7 site. Did anything change from 6 to 7?
I am using Drupal Security Review and it is telling me that every single directory and file is writable, including the settings.php file.
I would greatly appreciate it if someone could point me to a handbook, a page, something that explains it step by step, because it is not clear for me.
Thank you in advance!
PS QUICK UPDATE I tried to set the file permissions for the files directory and all subdirectories and files as proposed in the original post (rwxrws--- for directories and rw-rw---- for files within those directories, and none of my images displayed, except for a views slideshow on the front page which still seemed to be displaying. -- rek
Resources for those not born with inherent linux knowledge
I found that people's Linux knowledge has passed from person to person all the way back to the bearded folk who built Unix. When Unix came out they wrote simple explanations that has become such 'common knowledge' that no one seems to justify re-writing it for Linux.
So. To really get to know Linux, pipes file permissions etc, I would hold back from reading reams and reams of 'Chinese Whispers' and recommend the following, choice, info 'From the Horse's Mouth':
* "The UNIX Time-Sharing System (1974) by Dennis M. Ritchie and Ken Thompson" - The paper (by its inventors) that introduce Unix to the world. Explains files, pipes and shell etc.
* "The Art of Unix Programming by Eric Steven Raymond" - The background to Unix and why everything is as it, crazy, is.
* "Filesystem Hierarchy Standard" - A standard to define and explain the directory layout of in Unix/Linux distributions.
Then, this book is a great, modern practical guide:
* "Beginning Ubuntu LTS Server Administration 2nd Edition (2008), by Sander van Vugt" - A modern book that explains (amongst other things) file systems, basic commands, permissions and ssh
Chapter 5 of that last book will explain a lot.
Breaks D7 "Install new module" feature (admin GUI)
When I implement these permissions on a VPS running a single site, it causes the GUI-based "install new module" capability of D7 to fail. Now, I understand that installing modules with drush may be "better", but I don't think my users will agree. I can restore that functionality by making www-data own everything, but seems to defeat the purpose of all of this. Is there a solution that enables gui-based module installation that leaves as much of the security intact as possible? Changing just permissions or ownership in sites/all doesn't do the trick. If I'm just running a single site with few users (all admin), do I need these permission changes at all?
Yes, you need write
Yes, you need write permission to the .../sites/all/modules directory to use the GUI based install. Then the module will be owned by your web server. You can either give write access to the group (and place the web server in the group owning the directory) or change the owner to the web server's id.
Both ways have security implications as noted above; On my servers I change the directory owner temporarily to the web server id (via SSH), load the modules then change the ownership of the directory and uploaded files/directories to the ftp upload id.
... and also
It seems that as well as write permission to .... sites/all/modules, you also need the .../sites/default directory to be owned by the web server's id for the GUI installer to work. Write permission to .../sites/default is not sufficient. (7.15)
A quick, comprehensive script (maybe?)
Taking the handbook script as a base, I cooked the following script a couple of weeks ago for a friend of mine, been using it myself with much bliss :)
Mind you, I've not tested this extensively, but haven't run into any problems so far... I find it's pretty useful as a "one shot" solution.
I sort of added to the directory structure by creating a "bin" directory under
sites/<whatever>/bin
, and giving execute permissions to that directory alone (an example of a module needing executables is Printer, email and PDF versions, with thewkhtmltopdf
backend), if the executable files are needed somewhere else (as is the case for the above module, which needs them atsites/<whatever>/libraries
) you can always soft-link (ln -s
) them.What do you think of it? Am I missing something? Could something be improved?
PS: my bash coding could use some (constructive) criticism :)
fix-permissions.sh but ignore sites/default/files?
I'd like to run this script, but have a ton of files in my sites/default/files folder with proper permissions, on s3fs, so I'd rather not touch those (I've tried running the script as is, and it just seems to take forever... eventually killed it).
Anyone with more knowledge know how to modify fix-permissions.sh so that it leaves the sites/default/files directory alone?
Thanks in advance!
A script to fix your permissions!
Below is a bash script, name it whatever you want and make it executable, this seems easier than the proposal above....KISS!
I am open to any suggestions or changes because I use this script for every site I create.
Other owner
David, your script worked! Thanks!
As beginner, I have read comments and shouldn't the owner be other user than apache?
Something like:
$CHOWN -R greg:apache sites
shouldn't the owner be other
Actually, almost everything from above is about insecure/vulnerable setups and as you just noticed - the owner should never ever be an apache process since the foremost rule of web server security is to forbid the web server to write where it shouldn't write. This is the basics of web server configuration which doesn't depend on used CMS and I wonder how so many people advice all these flawed techniques.
If you are a beginner, then I encourage you to stand on the right path when securing filesystem of your web applications.
My first comment here was about exactly this - about using Linux ACLs: http://drupal.org/node/244924#comment-5179950
It is a bit outdated and currently I'm using a set of scripts, but the idea is the same.
P.S. /me is thinking about providing his scripts to the community.
So this is done. I created a
So this is done. I created a child page where I documented my script: http://drupal.org/node/1825824
Drush command to fix permissions
Just wanted to let people know that there's discussion on a drush command to fix permissions at http://drupal.org/node/990812
There's also information on fixing permissions/owner after drush dl at http://drupal.org/node/841310
where did i go wrong
i followed these instructions to a t (at least I think I did) but now the themes for the sites that are under the sites folder (i.e., the ones that got moved to home and a symlink) wont work -- the error log shows that it can't find various css files, even though they do exist at the path they are supposed to be in. I tried removing the theme, and reinstalling it, but same problem .
Index.php group owner on CentOS
I just had an issue with the index.php settings on a CentOS Server when doing a drupal 7 upgrade through drush, so hoping that this might help others. I was following the instructions above which said the index.php file should be:
-rw-r----- 1 greg-user www-data 873 2007-11-13 15:35 index.php
I replaced "www-data" with "nobody" since I thought that is the CentOS equivalent to Ubuntu's "www-data" which gives permission to the web server (apache). But I was unable to access the site after this. Turns out I had to set do the following:
chgrp greg-user index.php
and that did the trick. Replace "greg-user" with whatever the Linux username is on your server for that particular site.
Anyway, hope that helps someone who has a similar problem.
completely lost
CentOs doesn't have www-data and I am using root as my user while testing.
Cannot follow above directions, they are way too confusing.
I want to know what my drupal folder should be set to for ownership and permissions and down the line.
I have a subdomain where drupal resides.
At the moment I can't update modules not to mention other problems because nothing is set correctly.
Everything seems to be 6226 and then I read how that happened. Is everything 6226 supposed to be "apache"?
I am NOT on UBUNTU but CentOs vps so it is different and I'm completely lost on this most important set up.
I have read all of the above and it is not clear to me and I don't want to run a bash script.
Hope someone can help.
Centos is a distro of Red Hat
Centos is a distro of Red Hat
You are correct in that there is no group 'www-data' on Centos.
As Far as I know the Centos equivalent of 'www-data' is 'apache' so for example the shell line to change ownership of all files in and below a directory would be chown -R user:apache .
(replacing user with your dev or sysadmin username.)
I hope that helps
Tim
Add in git hooks
A reasonably effective method of ensuring file ownership after git pulls is to use git hooks.
If the following script is run on checkout and merge the entire drupal installation should use the correct ownership. This script will need to be extended for multisite installs to cover sites/*/files etc
Permission set script on Github
I took the script above and put it up on Github (and enhanced a bit and fixed some minor issues). Pull requests welcome.
https://github.com/MinnPost/drupal-permissions
--
zzolo
can't pass args directly as the beginning of the script suggests
The beginning of the script contains the unused and highly misleading section
You cannot, in fact, pass arguments that way. You need to use --drupal-user etc. I initially thought this was a problem with @zzolo's version of the script, when in fact the problem exists in the original (sorry, zzolo!)
For people running their own
For people running their own servers, I find setting a system wide UMASK of 027 simplies a lot of this. You could then chgrp your docroot (ie: public_html) to the shared group (www-data) and then setgid on it with
chmod g+s
. This would insure any new folders or files created would have 750 and 740 permissions respectively, and allow the web server access to the files. Then you just manually create your public files folder (and settings.php) and give the server permission to write to it withchmod g+w
.The only thing left to deal with is managing permissions on newly created folders and files WITHIN the files folder. In my testing, everything created within the files folder is owned by the server, and has 775 and 664 respectively, of course being a public space this shouldn't be too much of an issue.
Of course doing this on a brand new system may be easier than implementing on an existing system.
How to presave SGID (setgid) for folders/files created by Drupal
Drupal calls drupal_chmod() after new directory is created. There is
'file_chmod_directory'
setting which can be set in settings.php or withvariable_set()
.To make Drupal set 2775 permissions for new folders you can add this line to settings.php:
By default it is set to 0775. There is similar
file_chmod_file
for files (0644).Of course you should additionaly configure your OS:
This works great!
After QUITE a bit of trial and error (I have 13 unused 'test' image styles in my drupal install now) I finally found instructions that WORK! Kalabro, thanks for setting us all straight here. Setting umask to 002 is a critical component here, and my site didn't created directories with 775 until I set that.
I too was having the issue where an image style would be created, with apache:apache ownership and 755 permissions. This worked fine until I did 'chown web:apache -R' to the file directory (to allow 'web' to edit files via sftp) and suddenly the owner was 'web' and not 'apache' ... Now I can re-apply the 'correct' ownership (web:apache) WITHOUT breaking image styles, since perms are set to 775, and both user 'web' and group 'apache' have write permissions.
Thanks @kalabro!! I only wish your comments weren't hidden at the bottom of a thread, but somehow front/center in drupal's documentation on file permissions and/or setting up image styles.
Better performance
I got significantly better performance by changing all:
find [...] -exec chmod [...] \;
to:
find [...] -exec chmod [...] \+
(~3 secs compared to ~2 mins)
Changing the
;
(at the end of theexec
action) to a+
means matched files are appended onto the end of the onechmod
command (as opposed to runningchmod
on each file individually).Example: (
echo
simply displays the command, rather than actually running it)See man find for more details.
If someone else can confirm this works and doesn't have any adverse side-effects, can we edit the script above?
Script will change status of files in version control
This script is great but any files in version control will be marked as changed if their permissions change. As a result, I prefer to separate out my scripts for handling tmp, public & private files (none of which I keep in version control) so that I can run them on a remote site without having to worry about what's happening to Git status etc. I've shared my work so far on GitHub (along with some other scripts): https://github.com/danbohea/drupal_remote_scripts
My script
Hello,
as I am currently building a site with Drupal 7.26 and had issues with permissions on Apache 2 on Ubuntu 12.04, I tried to get all the info from this thread and make a solution for my sites. I ended up with a script, which I want to share now.
Note (Warning/Disclaimer):
I am a Linux and Ubuntu beginner and this is my first edit of a bash script, so I can't guarantee it is correct. Please comment, if something didn't work for you or could be done better.
1) I started here:
https://drupal.org/node/244924
And among all other things, I have found this summary usefull:
https://drupal.org/comment/4519336#comment-4519336
2) As a base, I have taken a script from:
https://github.com/MinnPost/drupal-permissions/blob/master/drupal-permis...
I call it "original script"
I didn't commit my script back to github. When the script proves to be correct, somebody experienced is welcome to update it.
3) Performance fix according to:
https://drupal.org/comment/8429975#comment-8429975
http://ss64.com/bash/find.html
a) Changing find chmods like:
find ${x} -type d -exec chmod ug=rwx,o= '{}' \;
to:
find ${x} -type d -exec chmod ug=rwx,o= '{}' \+
original "find ${x} -type d -exec chmod ug=rwx,o= '{}' \;" will call separate chmod for each found item (directory, ev. file), this could make performance issues.
Proposed "find ${x} -type d -exec chmod ug=rwx,o= '{}' \+" will first build a list of all found items (directories, ev. folders) '{}' and then perform chmod just once, this is faster.
b) Combining multiple files to one chmod like:
chmod u=rwx,go= CHANGELOG.txt
chmod u=rwx,go= COPYRIGHT.txt
to:
chmod u=rwx,go= CHANGELOG.txt COPYRIGHT.txt
These performance fixes, when run on your (busy) live site, will minimize possible errors to your online users. During running the script (original or proposed), first all directories are set non writable (by server) u=rwx,g=rx,o= and all files are set non writable (by server) u=rw,g=r,o=. Then script (original or proposed) continues and makes sites/*/files writable. If there are performance issues (original script), i.e. making files writable takes too long or is performed too late, your online users could get errors e.g. when uploading images to your site. With proposed performance fix, this risk is reduced.
4) Added chmod for sites/*/settings.php and sites/*/default.settings.php:
See: https://drupal.org/comment/4519336#comment-4519336
5) Added chmod for sites/*/files/.htaccess
It was recommended to have .htaccess in sites/*/files directories without server write access, see:
https://drupal.org/comment/4519336#comment-4519336
To disable executing php scripts from files directory:
https://drupal.org/comment/4133742#comment-4133742 - Suggestion adding: AddHandler default-handler php
https://drupal.org/comment/4572986#comment-4572986 - Apache config suggestion
But in Drupal 7.26 I have found section starting with:
# Set the catch-all handler to prevent scripts from being executed.
so I think, this is already handled with default Drupal installation?
And I do not need to edit .htaccess, just to chmod it?
Let us know, if you think otherwise.
6) Script could be safely used on the live site,
it doesn't revoke permission of all files and directories in the beginning.
Original script sets permission on ALL directories an on ALL files.
Then it sets permission of some "sub files" and some "sub directories".
This could cause problems to your web visitors, because some file/directory permissions could be temporarily restricted before they are set later to correct values. Your visitors or Drupal could get permission denied errors in this moment.
So in the newest version of the script I have excluded setting permissions of "sub files" and "sub directories" from ALL or their parent files/directories. "sub files" and "sub directories" are only set once.
NOTE 1:
Every server, especially shared hosting can be different, so if some set of permissions work on one hosting, it might not work on another. I have experienced this problem some time ago, because some hidden load balancer was used by my shared hosting provider. See e.g.:
https://drupal.org/comment/3026118#comment-3026118
https://drupal.org/comment/4080864#comment-4080864
https://drupal.org/comment/4519336#comment-4519336 - general permissions overview with proposed alternatives
(Adjust the permissions in the script accordingly, if the script permissions do not work for your server.)
NOTE 2:
I would rather prefer solution based on Linux ACL proposed at:
https://drupal.org/comment/5179950#comment-5179950
but it didn't fit my needs "out-of-the-box" and it is currently beyond my abilities and time restrictions to learn and adapt the ACL solution.
NOTE 3:
Personally I enjoyed the motto from user "suffering drupal" (https://drupal.org/user/215292):
"I started with Drupal in 2007 and then my life got stuck..."
:)
from: https://drupal.org/comment/4714254#comment-4714254
The newest version of the script is uploaded here:
(contains a fix for error reported by dhayalan_ms and doesn't support hardcoded arguments):
http://pastebin.com/KRt7uMqD
Hey filipes
Hey filipes
Thanks, that's a pretty decent and useful script. I had one issue where a library contained a "files" directory of its own, and ended up getting set with g=rwx permissions, when it should just be g=rx. That's due to the
-not -path "./sites/*/files"
matching./sites/all/libraries/elfinder/files
when you don't want that.One fix is just add a second chmod, which worked for my case. Another might be to fix the
-not
regex, but I didn't try that route.Script breaks Boost
Hi
Thanks for this script - very helpful. Just one issue I found - it breaks Boost by making the Boost cache folder unreadable. This issue becomes apparent if you visit the Status report for the site after running this script.
I resolved it by tweaking the method for securing permissions in the files directory on a Linux server, as described above, to look like this:
I provide Drupal, Drupal Commerce and CiviCRM development services for customers in New Zealand and beyond
.htaccess
this script changes the .htaccess file in the */files directory to writable by Apache (http_user--)
The very end of the script...
this line
find ${x} -type f -exec chmod ug=rw,o= '{}' \;
is making the .htaccess file in the files directory writable by apache
this should be added
the .htaccess can be used to alter the configuration of the Apache Web Server this could be a potential security risk
Can 2 different users have full read, write, and execute perms?
Hello Drupal Community.
We'd like to follow these instructions as closely as possible, but we have 2 different user accounts on the server that need full read, write, and execute permissions. (We administer a client's website on their behalf, so we want a user at the client to have full permissions also.) How best to handle that?
A coworker's idea is to reverse the user and group and the associated permissions - grant the Apache user only read and write, and grant the users' group, which does not include the Apache user, read, write, and execute. AKA 570 and 460 permissions. (He also mentions 'The ONLY reason this works is because apache and php both run under the Apache user. If they were separate then either our client or we would not be able to have write permissions.')
Is there another solution that is preferred? Are there any security concerns with the proposed idea?
Thank you,
Adam
When sites/default/files should have a different group owner
On a site we maintain, there are a number of users with FTP access to sites/default/files *only*, which they use to upload large files for download. This is a less-than-ideal set-up, but moving to tracking all files from w/in Drupal and handling file uploads solely through the admin UI is more work than we're ready to take on at this point. Because of this the sites/default/files directory needs to have different group-level ownership from the rest of the drupalroot. I modified the above script to take an additional --sites_default_files_group argument and to set that group ownership specifically:
https://gist.github.com/timstallmann/86e0b782e98fa7f5e1fd
SELinux
I suggest this script also deal with SELinux labels.
In Fedora 23 installation, Drupal code files (inside /usr/share/drupal7/ ) have labels:
system_u:object_r:httpd_sys_content_t:s0
while sites files (inside /etc/drupal7/sites ) have labels:
system_u:object_r:httpd_sys_rw_content_t:s0
http://Fiable.biz Web site creation.
I've spent some time reading
I've spent some time reading this extensive thread, and thought I would share my script as well, but as a Drupal Module, that I've created some time ago.
You can place it in
~/.drush
subdirectory and simply executedrush file-permissions
while being in any working Drupal site subdirectory.It bootstraps your Drupal site, checks for
file_private_path
,file_public_path
and sets them to correct Apache user and group. Apache user / group is being determined automatically, so it's not relying on the user specifying them manually or having them hard-coded in a script file.Module page: https://www.drupal.org/project/file_permissions