We run web servers where we have the following situation:
- The www-data user runs the web server and must have read+write access to the files
- The deploy user deploys all the code
- The bob and alice users might login via ssh and change configurations locally
All users must have read+write access on /var/www/mysite. We currently accomplish this by owning the group of /var/www/site to www-data. Then we set the write + setgid bit on the group to make sure all subdirectories are having the same rights.
Now, this is all running fine for some time, but we have issues with the following scenarios:
- We use bower to install packages with
bower install
. The user who ranbower install
the first time owns thepublic/bower_components
directory and no setgid bit is set - We use gulp to minify javascripts from
public/scripts/src
topublic/scripts/dist
and the first user who rangulp build
owns the files
In both situations, a find path/to/dir -type d -exec chmod g+ws {} \;
does mitigate the problem, but is it possible to fix this issue in the first place? We have set the setgid bit on the /var/www/mysite
directory, so why does bower install
not follow this permission set?
If not, is there a better way to fix this problem? We have thought to set the bits in the deployment automation process, but if a user forgets the setgid bit we think the automated deployment could get stuck as well.
Posix ACLs are the only clear-cut elegant way to do this, this is how I deal with shared read/write resource conflicts particularly on web-based systems. Here is a running example.
In my example I have a directory called
/var/www/html/share
. In addition I have the usersalice
,bob
,deploy
andbower
First, I have created a group called
html
and then added the users to this group.Now, I have then added a file ACL against this
html
group onto that folder.The second command is important, it causes inheritance to occur.
Now, we can test out the behaviour of this.
At first glance, it looks as though the file ownerships are all just simple, and will not allow one user to interact with anothers. However, we can inspect the ACL using
getfacl
which shows more infomation.You can see that the
html
group has control over these files.Note: the standard unix GROUP permission denotes the mask against the permissions. As it is
rw
for files it is also effectivelyrw
for the ACL, despite the actual permission granted beingrwx
.Lets test other users can modify/delete these files.
Finally, the tricky bit. What happens when alice makes a directory?
Because we passed
-d
tosetfacl
it instructs new directories to also inherit (and apply that inheritance to further subdirectories). So, now as userdeploy
we can add and edit existing files inside of that new subdirectory.You have mixed up semantics of sticky and setgid.
The sticky bit on a directory is used when multiple users are allowed to create files and directories in that directory, but they are only allowed to change those, which they created themselves, they are not allowed to mess with those contents created by other users. The
/tmp
directory is the typical use case for this.The sticky bit is not inherited by subdirectories. There is no need for it to be inherited in order to satisfy its intended purpose. The subdirectories created in a sticky directory are supposed to be off-limits by default for everybody except the creator.
The setgid bit on a directory indicates that files and directories created inside that directory inherit group from the directory, instead of getting the current group of the user creating it. The setgid bit is inherited by new directories created inside the setgid directory.
The setgid bit could achieve part of the goal you are trying to achieve. It would achieve the part where the entire hierarchy of directories and files will have the same group (unless explicitly overridden).
It does however not guarantee that everything in there will be writable by the group. That can be achieved through umask setting.
The umask indicates a set of bits, which are not to be set on newly created files and directories. Typical values for umask are
0002
,0007
,0022
,0027
,0077
. In your case you want those directories to be writable for the group, which means you want either0002
which means what is created will be readable to everybody outside the group or0007
which means what is created is inaccessible to everybody outside the group.You need to ensure the umask is set at some point before creating new files or directories. The umask is inherited by child processes. Beware of files created outside that specific directory, since the umask is applied elsewhere as well, so anything created elsewhere will still be writable by the group, even if that is a different group from what is used on the
/var/www
hierarchy.You could try making it harder to reset the permissions of the root directory by making it append only with chattr: