Setting up multi-user Apache on EC2
Not too long ago, I wrote about how to setup an EC2 instance in five minutes. I’ve grown even more enamored with the how quickly I can create a server, maybe use it for just an hour or two, and then tear it down at a cost of a few cents. In one of my projects, a class needed a public-facing shared web server where people could upload files and access them from mobile devices.
Knowing that Apache supports multi-user environments, I immediately went towards that solution. Unfortunately, and surprisingly due to the massive amounts of Apache documentation, I didn’t find an end-to-end tutorial on how to setup Apache for multiple users. I pieced together the configuration options and steps for creating users from multiple tutorials and pieces of documentation I found scattered around the web.
Enabling user directories
The most useful part of multi-user Apache is the ability for every user to have a directory inside of their home directory where files are served to the public. This is typically done in the public_html directory, allowing you to access files via /~username/ in a web browser. For example, the user foobot has a home directory of /home/foobot and a publicly-accessible web directory in /home/foobot/public_html. So /home/foobot/public_html/index.html is accessible from a web browser as http://www.example.com/~fooboot/index.html.
The default Apache configuration disables user directories by default, but it’s pretty simple to turn it back on. It just takes a few changes to the httpd.conf file, which is located at /etc/httpd/conf/httpd.conf on default EC2 configurations. There’s already a section in the file for setting up user directories, all you need to do is change the default settings so it looks like this:
<IfModule mod_userdir.c>
#
# UserDir is disabled by default since it can confirm the presence
# of a username on the system (depending on home directory
# permissions).
#
UserDir enabled all
#
# To enable requests to /~user/ to serve the user's public_html
# directory, remove the "UserDir disabled" line above, and uncomment
# the following line instead:
#
UserDir public_html
</IfModule>
The section immediately underneath defines any overrides for the user directories. If you want to allow the use of .htaccess in these directories, then make sure to provide the options here. This is the configuration I use to allow .htaccess:
<Directory /home/*/public_html>
AllowOverride All
Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
</Directory>
Once you’ve made these changes, you need to reload the server configuration:
sudo service httpd reload
Now the server is ready to support multiple users. All you need now is a few users.
Creating users
Each user must have a public_html directory in their home directory with appropriate permissions set. The permissions necessary are:
- The user’s home directory must have
711. - The
public_htmldirectory must have755.
For any users you already have, you’ll have to manually create the public_html directory and set permissions appropriately.
In my case, I was creating completely new users, so I found a script for creating users and then modified it to create the public_html directory and set permissions appropriately (as well as fixing a minor bug). You must use sudo to run this script:
#!/bin/bash
# Script to add a user to Linux system
if [ $(id -u) -eq 0 ]; then
read -p "Enter username : " username
read -s -p "Enter password : " password
egrep "^$username:" /etc/passwd >/dev/null
if [ $? -eq 0 ]; then
echo "$username exists!"
exit 1
else
pass=$(perl -e 'print crypt($ARGV[0], "password")' $password)
useradd -m -p $pass $username
if [ $? -eq 0 ]; then
mkdir /home/$username/public_html
chmod 711 /home/$username
chmod 755 /home/$username/public_html
cp /home/temp/.htaccess /home/$username/public_html
chown -R $username /home/$username/public_html
echo "User has been added to system!"
else
echo "Failed to add a user!"
fi
fi
else
echo "Only root may add a user to the system"
exit 2
fi
When run, this script prompts you to enter a username and password for a new user. It then creates the user as well as the public_html directory with the correct permissions.
Once the user is created using this script, they can ssh into the server and use SCP to copy file into their public_html directory.
Enjoy
Setting up a multi-user Apache environment is incredibly useful in situations where each user needs a separate web space. Common situations are professional and academic classes as well as professional organizations where developers need to be able to share things easily. A multi-user Apache environment behind a firewall is a nice alternative for file sharing as well.
Disclaimer: Any viewpoints and opinions expressed in this article are those of Nicholas C. Zakas and do not, in any way, reflect those of my employer, my colleagues, Wrox Publishing, O'Reilly Publishing, or anyone else. I speak only for myself, not for them.
Both comments and pings are currently closed.




6 Comments
Great tutorial!
In the user-creation script, rather than using `egrep` to check if a user exists, you can make the check more robust by using the `getent` command. It accesses ALL of the system’s authentication mechanisms (passwd, ldap, radius, etc) and is more trustworthy to see if a user is defined.
example:
getent passwd $username
it will return 0 if the user exists or non-zero if not.
the `getent` program does not exist in OSX, so it will only work on a linux system.
spike grobstein on November 18th, 2011 at 7:48 am
Also, you might want to use ~$username as the user’s home directory rather than /home/$username since it’s possible that a system may define a different location for user’s home directories.
spike grobstein on November 18th, 2011 at 7:53 am
@spike – Thanks for the tips. I’m not really a sysadmin, I just play one from time to time.
Nicholas C. Zakas on November 18th, 2011 at 8:12 am
Thanks. This is good. One question I had – how do I prevent a script running in one users public_html folder from accessing some other users public_html folder or files?
Yusuf on November 18th, 2011 at 1:12 pm
Ironically, it was much easier to find out how to do these things back in the late ’90s/early 2000s. I can’t remember how many times I’ve been bitten by not having my home directory’s perms set to 0711.
A few bugs to note:
1. file perms are octal, not decimal, so prefix with a 0. Doesn’t matter with the shell or with perl, they will both do the right thing, but if you do it in C or some other language, you might get bitten by this.
2. The script is okay for the purpose of this demo, but it’s not secure for general purpose user creation. It’s best to let the passwd program handle encrypting of passwords. It will take care of setting a different salt for each password. The current script uses the same salt, which makes it very easy to crack.
Instead, I’d run useradd with an empty password, and then immediately run the passwd program with the newly created username. This will prompt the user to enter a password. Alternately, you could call the passwd program with the -e flag, which will require the user to change their password on first login.
Regarding creating the public_html and .htaccess dir/file, it’s better to put them into /etc/skel. The useradd program will copy the contents of this directory into the newly created home directory.
Anyway, good stuff here. It’s well needed.
Lastly, it may be good to just put the apache config in a separate file in the sites_enabled directory (or equivalent for your distro). That way it will survive across apache upgrades.
Philip Tellis on November 19th, 2011 at 7:37 am
@Philip – Thanks, great tips! I’ll try to add those into the scripts I’m using. The reason this wasn’t a big deal for me is that the server was only in use for a few hours before being destroyed (Amazon EC2, FTW!).
Nicholas C. Zakas on November 21st, 2011 at 11:31 am
Comments are automatically closed after 14 days.