One of the biggest problems with administering a major server housing multiple sites is restricting access to the sites to only those people responsible for maintaining
a specific site. The reason for this is that all of the Apache child
processes run with the same user and group Id.
Therefore, all of the files need to be readable, writable, and
executable by the user and group that the server is running as. This
becomes a much bigger issue when you add CGI and PHP scripts to the
site. If those scripts must access private information, then that
information must be stored with relatively insecure user and group
Ids.
New in the Apache space: the Perchild MPM, which specifies User and Group IDs for clusters of child process. Ryan Bloom explains how this will make your life simpler.
Apache 1.3 solved this problem by introducing suexec, which
introduces other problems and PHP and mod_cgi can not take advantage
of it. Apache 2.0 has introduced a new MPM to solve this problem in
a more elegant way that all scripts can take advantage of.
The new
MPM is called Perchild, and it is based on the Dexter MPM. This
means that a set number of child processes are created and each
process has a dynamic number of threads. In this MPM it is possible
to specify User and Group IDs for clusters of child process. Then,
each virtual host is assigned to run in a specific cluster of child
processes. If no cluster of child processes is specified, then the
virtual host is run with the default User and Group Ids.
There
were many designs considered for this MPM, but in the end only one
made sense. The first consideration was which MPM to base off of.
The options were the prefork, mpmt_pthread, and dexter. Prefork and
mpmt_pthread had one major drawback, they create new child processes
which are completely separated from each other whenever the server
gets busy. This means that the parent process would need to
determine what User and Group Ids the new process should have when it
is created. While this seems easy at first glance, it requires load
balancing techniques that begin to get very complicated. If the
prefork or mpmt_pthread MPMs are desired, it makes more sense to put
a load balancer or proxy in front of the web servers, and run
multiple instances of Apache on different ports. To the client, this
would look very similar to the Perchild MPM.
After
eliminating prefork and mpmt_pthread, the only option left was
Dexter. Now, the question was how to associate virtual hosts with
child processes. Do we base the number of child processes on the
number of virtual hosts, or do we allow the web admin to specify how
the setup should look. Assuming that the more flexible we make the
Perchild MPM, the more likely it was to be used, we allow the web
admin to determine how their site looks. This is done through the
combination of two directives:
ChildPerUserID
NumChildren UserID GroupID
AssignUserID
UserID GroupID
The
first directive allow the administrator to assign a number of child
processes to use the same User and Group Ids. This is to provide for
some level of robustness. Because Perchild creates new threads in
the same child process to handle new requests, it is not the most
robust server, although it is very scalable. If one of
the threads seg faults, then that entire process will die, taking
with it all of the requests currently being server by that child
process. By specifying more than one child per user/group pair, we
allow the server to balance the number of requests between multiple
child processes. The second directive is specified inside a
VirtualHost stanza, and assigns that Virtual Host to a specific User
and Group Id. The server is smart enough to combine all of the
VirtualHosts with the same User and Group Ids to the same child
processes.