Alrighty, Here's my rough draft of a howto for Chrooting Apache. I was able to do it Slackware 10.2, and really can't say if it will work for everyone yet.
That's why I'm posting it here. Everyone's feedback is welcomed, good or bad. Let me know what you guys think.
### Background information ###
I was able to perform this chroot on my Slack server using
some of the available Slackware packages. Below I will list
everything that was used in the creation of the chroot:
Linux Distro used:
Each one of these packages comes with the Install CD or can
be downloaded from any slackware mirror server out there.
### Setting up Chroot environment ###
Basically, This is the exact setup I'm using currently. A lot
of this may require extra libraries or depenecies if you decide
to try this anything other than Slackware. I plan on doing more
research and determining what exactly is needed.
# Making directories
I started by creating a new directory, as root, specifically for
# mkdir -p /chroot/apache
Then, I moved into the new dir and began laying the framework for
my new chroot environment:
# cd /chroot/apache
# mkdir bin dev etc lib usr var
Next, I created a new dev/null for the chroot:
# mknod dev/null c 1 3
# Package information:
It's an absolute must to have dev/null present, since most programs
will use this throughout their usage.
Now we grab those pachages I listed at the beginning and move them
into the /chroot/apache directory. Since these are slackware packages
there are a few things to take note of about them.
1. The are basically nothing more than gloried tarballs. You can
unpack them by simply using the following command:
# tar -zxvf slackware-package.tgz
2. There is an extra folder called install/ included in each package.
This will need to be removed during the "installation" part of this
3. The most important thing to remember is, each one of these packages
are designed to install everything, in a binary format, from the
root directory. For example if you untarred apache-1.3.34-i486-1.tgz
in any random directory, you will see etc/ usr/ and var/ directories
appear. This is very important and helpful when attempting to build
one of these chroot environments. Each package comes with everything
that would be installed if you were compile the program by source and
install it. You'll understand better as we go through the motions.
Alright, so at this point we have our skeletal filesystem and the packages
to fill that filesystem. Now we need to include a few extras to ensure that
everything will run properly.
# Dependencies and Libraries:
****** WARNING: The following libraries and information are very specific
****** to Slackware 10.2 and Apache 1.3.34. I cannot confirm this
****** will work with anything else at this point.
In my case, I had Apache already installed on my system and from what I had
read, I needed to know to which libraries I needed to copy into lib/. So
There are two sets of command that will help any and all users to locate all
the necessary files for their chroot environments.
The first command is 'ldd'. This produces a list of dependencies that you'll
need to have for the program to run, as well as where to find them. The first
program I used tested this with was /bin/sh, since I *THINK* it is needed to
run Apache in chroot environment. Here's how it should look and work:
$ ldd /bin/sh
libtermcap.so.2 => /lib/libtermcap.so.2 (0x4001d000)
libdl.so.2 => /lib/libdl.so.6 (0x40022000)
libc.so.6 => /lib/libc.so.6 (0x40026000)
The dependencies listed above are symlinks located in /lib/. The symlinks point
at actual lib files in the /lib directory. A perfect exampe is libc.so.6:
$ ls -l /lib/libc.so.6
lrwxrwxrwx 1 root root 13 2005-11-17 17:16 /lib/libc.so.6 -> libc-2.3.5.so
So in actuality, libc-2.3.5.so is the lib you need to copy into
/chroot/apache/lib but you also need to create the symlink libc.so.6 as well.
The reason is if you were just copy libc*, I don't think the symlink's properties
transfer over as well. Not too sure though, this is another area I need to work
on more. So, to help out, below is a list of all files that need to be copied over
from /lib to /chroot/apache/lib/ as well as what symlinks should be created. These
are all the dependencies that I have in my /chroot/apache/lib/:
# cd /chroot/apache/lib/
# cp /lib/ld-2.3.5.so .
# ln -s ld-2.3.5.so ld-linux.so.2
# cp /lib/libc-2.3.5.so .
# ln -s libc-2.3.5.so libc.so.6
# cp /lib/libcrypt-2.3.5.so .
# ln -s libcrypt-2.3.5.so libcrypt.so.1
# cp /lib/libdb-3.3.so . # This one does not need a symlink created for it.
# cp /lib/libdl-2.3.5.so .
# ln -s libdl-2.3.5.so libdl.so.2
# cp /lib/libm-2.3.5.so .
# ln -s libm-2.3.5.so libm.so.6
# cp /lib/libnsl-2.3.5.so .
# ln -s libnsl-2.3.5.so libnsl.so.1
# cp /lib/libnss_compat-2.3.5.so .
# ln -s libnss_compat-2.3.5.so libnss_compat.so.2
# cp /lib/libnss_files-2.3.5.so .
# ln -s libnss_files-2.3.5.so libnss_files.so.2
# cp /lib/libnss_nis-2.3.5.so .
# ln -s libnss_nis-2.3.5.so libnss_nis.so.2
# cp /lib/libpthread-0.10.so .
# ln -s libpthread-0.10.so libpthread.so.0
# cp /lib/librt-2.3.5.so .
# ln -s librt-2.3.5.so librt.so.1
# cp /lib/libtermcap.so.2.0.8
# ln -s libtermcap.so.2.0.8 libtermcap.so.2
# cp /usr/lib/libexpat.so.0.5.0 ../usr/lib/
# cd ../usr/lib/
# ln -s libexpat.so.0.5.0 libexpat.so.0
And we need to add one more thing that ties in with the libraries:
# cp /etc/ld.so.cache /chroot/apache/etc/
These should be all the necessary dependencies for /bin/sh and /usr/sbin/httpd.
Below is the ldd output for /usr/sbin/httpd:
$ ldd /usr/sbin/httpd
libm.so.6 => /lib/libm.so.6 (0x4001d000)
libcrypt.so.1 => /lib/libcrypt.so.1 (0x40041000)
libdb-3.3.so => /lib/lidb-3.3.so (0x4006f000)
libexpat.so.0 => /usr/lib/libexpat.so.0 (0x40103000)
libdl.so.2 => /lib/libdl.so.2 (0x40123000)
libc.so.6 => /lib/libc.so.6 (0x40127000)
With the ldd command, we can figure out what libraries are needed for httpd
to run. There's still to be discovered though. See, during my first attempts,
I was under the impression that those libraries were all the dependencies
needed for httpd to run. I was horribly wrong. There are quite a few other
files that need to be in their respective places before you attempt to launch
Apache in a chroot.
An easy way to discover what files will be needed is to use 'strace' and track
down what files will be opened and used by httpd as well. strace is typically
used to track down problems with programs that are being developed or that randomly
stop working. If you use the command:
# strace /usr/sbin/httpd
You will receive more output about the program than you will need (at least to this
point). Adding in the switch '-eopen' will allow you to see what files httpd attempts
to open and collect information from. Example below:
# strace -eopen /usr/sbin/httpd
open("/etc/ld.so.cache", O_RDONLY) = 3
open("/lib/libm.so.6", O_RDONLY) = 3
open("/lib/libcrypt.so.1", O_RDONLY) = 3
open("/lib/libdb-3.3.so", O_RDONLY) = 3
open("/usr/lib/libexpat.so.0", O_RDONLY) = 3
open("/lib/libdl.so.2", O_RDONLY) = 3
open("/lib/libc.so.6", O_RDONLY) = 3
open("/etc/apache/httpd.conf", O_RDONLY) = 3
open("/usr/libexec/apache/mod_vhost_alias.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_env.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_define.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_log_config.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_mime_magic.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_mime.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_negotiation.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_status.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_info.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_include.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_autoindex.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_dir.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_cgi.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_asis.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_imap.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_actions.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_speling.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_userdir.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_alias.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_rewrite.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_access.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_auth.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_auth_anon.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_auth_dbm.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_digest.so", O_RDONLY) = 4
open("/usr/libexec/apache/libproxy.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_cern_meta.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_expires.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_headers.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_usertrack.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_log_forensic.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_unique_id.so", O_RDONLY) = 4
open("/usr/libexec/apache/mod_setenvif.so", O_RDONLY) = 4
open("/etc/nsswitch.conf", O_RDONLY) = 4
open("/etc/ld.so.cache", O_RDONLY) = 4
open("/lib/libnss_compat.so.2", O_RDONLY) = 4
open("/lib/libnsl.so.1", O_RDONLY) = 4
open("/etc/ld.so.cache", O_RDONLY) = 4
open("/lib/libnss_nis.so.2", O_RDONLY) = 4
open("/lib/libnss_files.so.2", O_RDONLY) = 4
open("/etc/passwd", O_RDONLY) = 4
open("/etc/group", O_RDONLY) = 4
open("/etc/apache/srm.conf", O_RDONLY) = 3
open("/etc/apache/access.conf", O_RDONLY) = 3
open("/var/log/apache/error_log", O_WRONLY|O_APPEND|O_CREAT, 0666) = 3
open("/etc/resolv.conf", O_RDONLY) = 3
open("/etc/host.conf", O_RDONLY) = 3
open("/etc/hosts", O_RDONLY) = 3
open("/etc/apache/mime.types", O_RDONLY) = 3
open("/etc/apache/magic", O_RDONLY) = 3
open("/var/log/apache/access_log", O_WRONLY|O_APPEND|O_CREAT, 0644) = 3
As you can see, there are quite a few things that are opened during the start of
httpd. All the /usr/libexec/apache/* files will be included in the
apache-1.3.34-i486-1.tgz package, so no worries there. We have copied all the lib
files over too, so no problems there either. Now we just have to get the rest of
the files into their places and we'll be ready to start unpacking.
# /etc configuration and setup:
Now we need to do some more work. First we need to create the user that httpd will
run as. The default convention for the user and group is apache.www.
For the purposes
of this howto, that's the user we will. You can be created and use different names
but the rest of this should be performed pretty much the way it's written:
# groupadd -g 5000 www
# useradd -u 5000 -g www -d /dev/null -s /bin/false -c Apache WWW Server apache
This user needs to be created in /etc/passwd and /etc/group since this will be the
user running httpd. Once you have created the user and group, we will need to copy
that information into the chroot environment. Some people say to copy to passwd and
group over to the chroot directory and then edit it in the chroot environment. That
is not how I did it. I used the following commands to create the new Apache user and
# cat /etc/passwd | grep 'apache' > /chroot/apache/etc/passwd
# cat /etc/group | grep 'www' > /chroot/apache/etc/group
This will create our chroot passwd and group file. Now I'm not sure if the shadow
and gshadow are absolutely required to have, but it worked for me with them, so
for the time being, also perform these commands as well:
# cat /etc/shadow | grep 'apache' > /chroot/apache/etc/shadow
# cat /etc/gshadow | grep 'www' > /chroot/apache/etc/gshadow
You need to have the same user listed in both your root environment and your chroot
environment. I do not believe it will recognize the user if it's only listed in the
chroot dir, but I could be wrong.
And finally to wrap up all the stuff you need to copy into /etc, just copy the
following files over into the chroot environment:
# cp /etc/host.conf /chroot/apache/etc/
# cp /etc/hosts /chroot/apache/etc/
# cp /etc/nsswitch.conf /chroot/apache/etc/
# cp /etc/resolv.conf /chroot/apache/etc/
# Package installation:
Now that we've prepared the chroot environment, we need to "install" Apache. First
you want to make sure you have the apache, perl and php packages in the
/chroot/apache/ directory. The packages are expected to installed with a prefix of
/. In other words, it would be the same thing to cp them to / and simply untar them.
So, now you want to do the following:
Move or download the packages into /chroot/apache/
# cd /chroot/apache
# tar -zxvf apache-1.3.34-i486-1.tgz
# tar -zxvf php-4.4.1-i486-1.tgz
# tar -zxvf perl-5.8.7-i486-1.tgz
Remove the directory install/
# rm -rf install/
Since the Slackware Apache build had PHP and Perl built into it, you must
install/untar those packages as well. As it stands now, this is going to be
a 100MB build I believe. I plan to work on trimming that down as well.
### Final steps and testing the setup: ###
Now, go into /chroot/apache/etc/httpd.conf and change the user and group from
nobody to apache and www, respectively. That way, we'll have some minor increased
security and the ability to run httpd.
Now to test out httpd in the chroot environment. Run the following command as root:
# chroot /chroot/apache/ /usr/sbin/httpd
If you don't receive any error messages, do a 'ps aux' and check to see if it's
running. If it is, Congrats!
### Errors and Troubleshooting ###
Now, if you got to 'chroot /chroot/apache/ /usr/sbin/httpd' and received the error
message "/usr/sbin/httpd: File or Folder not found", then there are some things to
check and try.
Most howtos will tell you use to use strace on the chroot command you issue to start
httpd. This can be confusing and mislead, as it traces the chroot command and httpd.
I'm not saying it's not helpful, just confusing. Here are some tips from my
experiences and adventures in chroot Apache:
- Go back and make sure you have all the correct file names, files and above mentioned
packaces and programs. One of the reasons I had problems was an extra 's' in one of
the library symlinks. Simple mistakes are the hardest to find.
- Make sure you've configured httpd.conf properly. If this is your first time running
Apache, you might want to install it on the system, before chrooting. This will
provide you with some experience and knowledge of Apache and setting up httpd.conf.
- Make sure you have completed all of this as root. Some may say it's a security risk
and you should only run as root when you absolutely must. The only thing you can
really mess up as root with this setup is your lib files. You must be careful to
copy them instead of moving. You can still delete them as a user I think, but don't
really want to try.
- Make one change at time and try starting httpd each time. Tedious as it is, slow and
steady is the way all people should pursue learning. Sometimes you need to review
everything a hundred times to see the one error you made.
- Email me, I work at a large corporate helpdesk supporting multiple clients and hang
out in the #linuxhelp and #Slackware channels on irc.freenode.net. I'm accustom to
trying to help and getting asking really odd questions. Email is firstname.lastname@example.org
And whatever you do, just keep plugging away. I was almost convenienced that I could
not chroot this, and I did. Believe me when I say, I'm not a guru of any kind. I'm a
regular Slackware Linux user and someone who's thristy for knowledge, learning and
hacking. I live to do stuff like this, then show other people how they can do it too.
The chance to share with everyone in the community is a good feeling.
Hope this helps you guys. I'm always looking for feedback and assistance. Currently
I plan on packing this up and creating a small offshoot of Apache called Mjolnir Apache.
It's going to be a security focused type deal.