User management for web applications with multiple developers

Probably lots of you have experienced one or another variant of the problem already: you're administrating a webserver with serveral web applications and either the person in charge or her developers or all of them need write access to the code (application directory). Additionally, the web application itself requires write access to particular areas of the application folder. And to make it even more complicated, none (or at least not all) of them know about version control systems, so using Git with post-hooks for continuous delivery is not an option. Instead, they need simple remote access to the DocumentRoot using SCP/SFTP/FTPS.

There's several solutions to these requirements involving system user groups and webservers suexec solutions. Usually you also want ...oO#####0o...

While I read several blog posts and tutorials about this topic over the years, every single time I stumble across the topic, it again takes some time to find and implement a proper solution for the concrete solution.

This post tries to summarize options and solutions that I know about.

Description of the setup

Let's assume the following:

  • We have a web application app1 living in /var/www/app1
  • The webserver runs as www-data:www-data (default for Apache on Debian)
  • The webserver needs write access to the whole application (for updates)
  • Two separate users need write access to the application over SCP

Dedicated user group per web application

One approach is to add a dedicated system user group for the web application, make everything group writable and ensure that each user writing to the directory sets the system group and permissions accordingly.

  1. First, we add the dedicated system group web-app1 and two users for scp:
addgroup web-app1
adduser --home /var/www/app1 --no-create-home --ingroup web-app1 user1
adduser --home /var/www/app1 --no-create-home --ingroup web-app1 user2
  1. Now, we adjust ownership and permissions:
chgrp -R web-app1 /var/www/app1
chmod -R g+w /var/www/app1
  1. Now we configure the webserver Apache2 to run the VirtualHost for app1 as www-data:web-app1:

    • Add user www-data to group web-app1:

      adduser www-data web-app1
      
    • Enable suexec module in Apache2:

      a2enmod suexec
      
    • Configure the VirtualHost at /etc/apache2/sites-available/app1:

      <VirtualHost ...>
      [...]
      SuexecUserGroup www-data web-app1
      </VirtualHost>
      
    • Finally, we activate the new configuration:

      service apache2 restart
      
  2. Finally, we have to set the umask to 0002 for each system user and/or applicatation that writes to /var/www/app1 in order to ensure that new files are created with group write permissions.

    • For bash logins, this can be accomplished by setting the umask in the users' ~/.bashrc:

      cp /etc/skel/.bashrc /var/www/app1
      echo "umask 002" >>/var/www/app1/.bashrc
      chgrp web-app1 /var/www/app1/.bashrc
      
    • For SCP, another solution is needed as SCP doesn't start a shell. The following settings in /etc/ssh/sshd_config cause SSH to set the umask for each login of users in group web-app1:

      Match Group web-app1:
      ForceCommand /bin/sh -c 'umask 0002; ${SSH_ORIGINAL_COMMAND:-$SHELL}'
      

Known issues

  • Umask for Apache suexec:

    Files created by Apache (even through suexec) will use the default umask for the Apache Process, which is 0022 per default. On systemd systems you can change the default umask for Apache by adding a unit drop in at /etc/systemd/system/apache2.service.d/umask.conf:

[Service]
UMask=0007

Beware that this sets the umask globally for Apache2, not only for the app1 VirtualHost.