How to 'chroot' an Apache tree with Linux and Solaris

Table of Contents


Introduction

I have set up and used chroot-ed web trees in the past with the CERN httpd. There are various advantages and disadvantages to chroot-ing a web tree. In the early days of the 'web' this technique provided some valuable extra security. In this Apache-dominated era there seems to be less need. However the techique is still interesting and relevant.

I provide example chroot-ed Linux and Solaris setups, with options to do a standard compilation (which is marked non-DSO where necessary), or a Dynamic Shared Object (DSO) compilation (which is marked DSO where necessary). The solaris example with DSO options is not yet documented, since I haven't tested it (and want to play with Solaris 8 as well when I do it :-)

It is relatively simple to set up a chroot-ed apache tree on Linux. This example uses Red Hat 6.* and Apache 1.3.12. This example also includes PHP 4 (as an apache module), and an installation of perl 5 in the chrooted tree. Additionally mod_ssl and mod_perl are installed.

This example assumes that Red Hat was installed with a decent development environment (ie: sufficient include files, libraries and development tools). Note that you will typically have a complete development environment if you installed the Red Hat custom (preferred!) configuration and selected the 'development' option; or the server configuration.

MySQL 3.22.27 is not installed in the chroot-ed tree, but is added here for completeness.

* Standard Disclaimer

I am not an expert (IANAE ? :-), especially for issues related to encryption (openssl, mod_ssl and company). I am human and I make mistakes. Please let me know if you find any, or if you have any other constructive suggestions.

This how-to is provided in the hope that it will help you, and that you may learn something from it. I could always just provide an RPM, but it is far more interesting (I think) to know that you can construct a modern web server from scratch, yourself. But it is up to you to learn and understand the issues, the problems and the risks of running a web server in today's internet!

* The Solaris Example

The Solaris example for chroot-ing a web tree is very similar to the Linux case. Of course, if you don't have a current GNU development environment installed then it will be not be as easy as the Linux case.

The Solaris example is documented here, in a separate web document (but note that DSO options, mod_perl and mod_ssl are not yet documented).


Additional Notes


Getting the Source

You will need to pick up the source files for any packages you intend to integrate into your chroot-ed tree. Many of these source files can be extracted from the corresponding linux distribution SOURCE cdroms as SRPMs (RPM source packages) or tarball (.tar.gz) files. (This is very handy if you have limited bandwidth).

For a Red Hat system you install the source (as root):
  ROOT# rpm -i /path/to/SRPMfile.src.rpm
and pick the source out of the /usr/src/redhat/SOURCES/ directory.

But for these examples I indicate where to go to get the sources on the internet (and the versions that were used for these examples):

Package Version Source Documentation
Apache 1.3.12 www.apache.org/dist/
www.apache.org/mirrors/
www.apache.org/docs/
MySQL 3.22.27 www.mysql.com/downloads/
www.mysql.com/downloads/mirrors.html
www.mysql.com/documentation/
PHP 4.0.2 www.php.net/downloads.php www.php.net/docs.php
Perl 5.00503 www.cpan.org/src/
www.cpan.org/modules/00modlist.long.html
www.cpan.org/doc/manual/html/
mod_perl 1.24 perl.apache.org/dist/ perl.apache.org/#docs
Hello.pm   perl.apache.org/dist/contrib/  
mod_ssl 2.6.6-1.3.12 ftp.modssl.org www.modssl.org/docs/2.6/
OpenSSL 0.9.5a ftp.openssl.org www.openssl.org/support/faq.html
RSAref 2.0 google search
altavista search
google search
altavista search

Detailed Steps

* Prepare a Chroot-ed File System

  1. Set up the tree anywhere (preferably another disk or a non-system partition to discourage others from making hard links to files outside your web tree), but use a symlink (eg /www) to reference it.
    ROOT# mkdir /export/misc/www
    ROOT# ln -s /export/misc/www /www

  2. Create the basic directories; bin will be a link to usr/bin
    !! NOTE the lack of leading slashes in this example, except where I copy files from the regular file system. Do NOT mix up your chroot-ed tree with your real '/'!
    You have been warned!
    I have indicated the chroot-ed files in magenta
    ROOT# cd /www
    ROOT# mkdir -p usr/bin usr/lib lib etc tmp dev webhome
    ROOT# ln -s usr/bin bin

  3. /tmp is given special perms.
    ROOT# chmod 777 tmp
    ROOT# chmod +t tmp

  4. Make the special device /dev/null
    ROOT# mknod -m 666 dev/null c 1 3

  5. Set up the timezone info for YOUR timezone (this example uses MET):
    ROOT# mkdir -p usr/share/zoneinfo
    ROOT# cp -pi /usr/share/zoneinfo/MET usr/share/zoneinfo/
    ROOT# cd etc
    ROOT# ln -s ../usr/share/zoneinfo/MET localtime
    ROOT# cd ..

  6. You will find that perl and/or mod_perl will complain about the lack of locale settings. To fix this install your locale files in the chroot-ed tree:
    ROOT# set |grep LANG
    LANG=en_US

    ROOT# mkdir /www/usr/share/locale
    ROOT# cp -a /usr/share/locale/en_US /www/usr/share/locale/

  7. Now copy in the shared libraries that provide a very basic chroot-ed file system
    ROOT# cp -pi /lib/libtermcap.so.2 /lib/ld-linux.so.2 /lib/libc.so.6 lib/

  8. Test your tree ('cat' will be needed by 'apachectl' later, but is not strictly necessary):
    ROOT# cp -pi /bin/ls /bin/sh /bin/cat bin/
    ROOT# chroot /www /bin/ls -l /
    lrwxrwxrwx   1 0        0               7 Jan 29 09:24 bin -> usr/bin
    drwxr-xr-x   2 0        0            1024 Jan 29 09:28 dev
    drwxr-xr-x   2 0        0            3072 Jan 29 13:17 etc
    drwxr-xr-x   2 0        0            1024 Jan 29 13:12 lib
    drwxrwxrwt   2 0        0            1024 Jan 29 09:23 tmp
    drwxr-xr-x   5 0        0            1024 Jan 29 09:23 usr
    drwxr-xr-x   2 0        0            1024 Jan 29 10:41 webhome
    
  9. You can remove 'ls'; it was only used for testing:
    ROOT# rm bin/ls

* Prepare a User and the Naming Service

Here we create the user whom apache will run as, and the necessary naming services for this configuration.
  1. Create a new user that doesn't exist on the system, and give the user a unique name (eg: www) and user id (eg:888). Note that it isn't actually necessary for the user:group to exist in the real authentication (/etc/passwd /etc/group) files. It's up to you..
    ROOT# cd /www
    ROOT# touch etc/passwd etc/group etc/shadow
    ROOT# chmod 400 etc/shadow

  2. Edit these three files. For the sake of this example I am just echoing the data into the files:
    ROOT# echo 'www:x:888:888:Web Account:/webhome:/usr/bin/False' > etc/passwd
    ROOT# echo 'www:x:888:' > etc/group
    ROOT# echo 'www:*:10882:-1:99999:-1:-1:-1:134537804' > etc/shadow

  3. I have given this user no login, and no shell. Just to be complete, compile a 'no-go' shell called False:
    ROOT# echo 'int main(int argc, char *argv[]) { return(1); }' > /tmp/False.c
    ROOT# cc -o /www/usr/bin/False /tmp/False.c

  4. While we are at it, lets mark the binaries as execute-only:
    ROOT# chmod 111 usr/bin/*

  5. Some naming services will be required. With glibc and the Name Service Switch libraries the necessary libraries are not immediately obvious. See 'man nsswitch' for details.
    I chose to rely on files and DNS, even though I also run NIS on my home machines.

    Note: The libresolv library will be needed as well (This will become evident when PHP is installed).
    ROOT# cp -pi /lib/libnss_files.so.2 lib/
    ROOT# cp -pi /lib/libnss_dns.so.2 lib/

  6. We will need 3 files to complete the configuration for Naming Service. The contents of these files will depend on your IP and DNS setup. Here we assume that the web server is named ns.mynet.home with IP address 192.168.196.2 (it is actually also my naming server):
    # ---- Contents of    etc/nsswitch.conf ----#
    passwd: files
    shadow: files
    group: files
    hosts: files dns

    # ---- Contents of    etc/resolv.conf ----#
    domain mynet.home
    ## use the IP address of your naming server
    ## if bind is not installed on your web server
    #nameserver 192.168.196.xxx
    ## use this if your web server is a (caching) name server
    nameserver 127.0.0.1

    # ---- Contents of    etc/hosts ----#
    127.0.0.1 localhost loopback
    192.168.196.2 ns.mynet.home ns www

* Compile and Install Apache

  1. Make the top-level directory for the apache install (in this example: /apache); and create a symlink to it in the real tree:
    ROOT# mkdir /www/apache
    ROOT# ln -s /www/apache /apache

  2. I normally compile and install as an ordinary user (in this example: softs), rather than as 'root'. Note, however, that the installation of apache should be done as root. (See the 'security tips' in the online apache documentation)
    In this case I compile sources in /usr/local/src/chr, which is owned by softs:softs
    $ cd /usr/local/src/chr
    $ tar zxf /path/to/apache_1.3.12.tar.gz
    $ cd apache_1.3.12

  3. Edit config.layout so that it includes a special layout called chroot
    #   chroot layout.
    <Layout chroot>
       prefix:        /apache
       exec_prefix:   $prefix
       bindir:        $exec_prefix/bin
       sbindir:       $exec_prefix/bin
       libexecdir:    $exec_prefix/libexec
       mandir:        $prefix/man
       sysconfdir:    $prefix/conf
       datadir:       $prefix
       iconsdir:      $datadir/icons
       htdocsdir:     $datadir/htdocs
       cgidir:        $datadir/cgi-bin
       includedir:    $prefix/include
       localstatedir: $prefix/var
       runtimedir:    $localstatedir/logs
       logfiledir:    $localstatedir/logs
       proxycachedir: $localstatedir/proxy
    </Layout>
    
  4. Now configure and make:
    $ make
    ROOT# make install ## I am root!

  5. Copy the other shared libraries that will be needed by Apache as configured in this example. NOTE that other configurations may require other libraries (use ldd to find out).
    ROOT# cd /www
    ROOT# cp -pi /lib/libm.so.6 /lib/libcrypt.so.1 /lib/libdb.so.3 lib/
    ROOT# cp -pi /lib/libdl.so.2 lib/

  6. Do a quick test to see that it worked. The main fields to edit in the configuration file /www//apache/conf/httpd.conf for a quick test are:
    User www
    Group www
    ServerName yourserver.yourdomain.here
    Port 8088   ## pick your favourite test port
    Here are sample configuration files:
    non-DSO: httpd.conf (colorized) httpd.conf (plain text)
    DSO: httpd.conf (colorized) httpd.conf (plain text)

  7. Start the daemon (you need to be root):
    ROOT# chroot /www /apache/bin/apachectl start

  8. Test the URL:
    $ lynx -dump http://yourserver/
    Test the URL if on another port, eg: 8088:
    $ lynx -dump http://yourserver:8088/

  9. Here is a small perl script that removes most of the comments from the generated config files, for those who want to simplify the file.

  10. This would be a good time to give ownership of the htdocs tree to the web tree 'owner':
    ROOT# chown -R 888:888 /www/apache/htdocs

* Compile and Install MySQL

MySQL is not installed in the chroot-ed tree; indeed, it should probably be installed on another system. But on my home system it is installed on the same server as apache.

This example includes creating the user and the place where the database will reside, and the creation of the initial database.

  1. Create the user who will own the mysql database -- for example, 777:777 in /home/mysql:
    ROOT# groupadd -g 777 mysqldba
    ROOT# useradd -c "mysql DBA" -d /home/mysql -u 777 -g 777 -m -n mysql

  2. unpack the source and give ownership of the mysql source tree to the mysql user:
    ROOT# mkdir /usr/local/mysql
    ROOT# chown mysql:mysqldba /usr/local/mysql
    ROOT# cd /usr/local/src
    ROOT# tar zxf /path/to/mysql-3.22.27.tar.gz
    ROOT# chown -R mysql:mysqldba /usr/local/src/mysql-3.22.27

  3. Now as the mysql user, make a directory for the database, and compile and install mysql:
    $ mkdir ~/db ## where the DB will reside
    $ cd /usr/local/src/mysql-3.22.27
    $ ./configure --localstatedir=/home/mysql/db --prefix=/usr/local/mysql
    $ make
    $ make install

  4. Create the *MySQL* grant tables (necessary only if you haven't installed *MySQL* before):
    $ ./scripts/mysql_install_db

  5. Install and modify the database startup script, changing the database owner from root to 'mysql':
    ROOT# cd /usr/local/src/mysql-3.22.27/
    ROOT# cp support-files/mysql.server /etc/rc.d/init.d/
    ROOT# chmod 755 /etc/rc.d/init.d/mysql.server
    ROOT# [ edit /etc/rc.d/init.d/mysql.server: ]
    mysql_daemon_user=mysql ## so we can run mysqld as this user.
    
    ROOT# chkconfig --add mysql.server ## permanently add server to rc scripts

  6. It may be necessary to refresh the shared library cache after installing mysql:
    ROOT# /sbin/ldconfig -nv /usr/local/lib

  7. Edit the PATH variable for the mysql owner, and set up the 'root' password for the database (read the documentation!) (and you will probably want to delete the test database and associated entries):
    $ [ Edit shell login script .bash_profile: ]
         PATH=$PATH:$HOME/bin:/usr/local/mysql/bin
    
    $ . ~/.bash_profile ## source it!
    $ mysqladmin -u root password '2mUch!data' ## pick your own password!

* Compile and Install PHP

  1. Stop the apache daemon, if it is running:
    ROOT# chroot /www /apache/bin/apachectl stop

  2. You must first compile PHP, then for non-DSO installs only you must recompile Apache. (You will need to do this each time you upgrade either software package for non-DSO installs.)
    $ cd /usr/local/src/chr ## I am NOT root!
    $ tar zxf /path/to/php-4.02.tar.gz
    $ cd php-4.02
    $ make

  3. Now for the non-DSO installation only, recompile Apache, activating the PHP module:
    $ cd ../apache_1.3.12/
    $ ./configure --with-layout=chroot \
    --enable-module=most --enable-module=so \
    --activate-module=src/modules/php4/libphp4.a

    $ make
    ROOT# make install ## I am root!

  4. More shared libraries (for PHP) are needed in the chrooted tree; check with 'ldd': A little for-loop can be used to copy the needed files from /lib and from /usr/lib:
    ROOT# cd /www
    ROOT# for i in libresolv.so.2 libnsl.so.1 libpam.so.0 ; do
    > cp -pi /lib/$i /www/lib/ ; done

    ROOT# for i in libgd.so.1 libgdbm.so.2 libz.so.1; do
    > cp -pi /usr/lib/$i /www/usr/lib/ ; done


  5. If you will be needing mysql, you must install that library as well from the place it was compiled into:
    ROOT# cp -pi /usr/local/mysql/lib/mysql/libmysqlclient.so.6 /www/usr/lib/

  6. You must edit httpd.conf so that it recognizes .php files, if you have not already done so:
    ROOT# cd /apache/conf
    ROOT# [ edit /apache/conf/httpd.conf ]
      AddType application/x-httpd-php .php
      AddType application/x-httpd-php-source .phps


  7. Restart the daemon:
    ROOT# chroot /www /apache/bin/apachectl start

  8. For non-DSO installs you can check for compiled-in PHP:
    ROOT# chroot /www /apache/bin/httpd -l | grep php
    mod_php4.c

  9. Here is a 'hello world' script to test PHP. It should be installed as 'hello.php' (save as type 'text' from netscape), with a copy or a symlink as 'hello.phps' for source-code viewing if you wish. Do not leave it lying around for the public after you have finished testing!

* Compile and Install Perl

You can get away with simply copying /usr/lib/perl5 into /www/usr/lib/ ; and copying /usr/bin/perl5.00503 (assuming Red Hat 6.0) into /www/usr/bin/. You would need to check for, and install any missing shared libraries. You should also make a hard link from usr/bin/perl5.00503 to usr/bin/perl in /www as well.

The easy way:

ROOT# cp -a /usr/lib/perl5 /www/usr/lib/perl
ROOT# cp -p /usr/bin/perl5.00503 /www/usr/bin/
ROOT# cd /www/usr/bin
ROOT# ln perl5.00503 perl

Nonetheless (the slightly less easy way :o), I show how to compile and install perl. If you are going to install mod_perl then you really must compile perl here:

  1. Make the nessary links to install into the chroot-ed tree. This example uses /usr/Local inside the tree. The choice of /usr/Local is deliberate -- do not confuse it with /usr/local.
    Ever fearful :-O, I installed as 'softs':

    ROOT# mkdir /www/usr/Local
    ROOT# ln -s /www/usr/Local /usr/Local
    ROOT# chown softs:softs /www/usr/Local

  2. Get the source RPM from the redhat sources:
    ROOT# rpm -i /path/to/perl-5.00503-2.src.rpm

  3. As the owner (softs) of the source tree, unpack perl.
    $ cd /usr/local/src/chr
    $ tar zxf /usr/src/redhat/SOURCES/perl5.005_03.tar.gz

  4. Red Hat supplies some patches in the SRPM. You can apply these patches for this distribution as well. This exemple illustrates patching perl from a Red Hat 6.0 distribution.
    $ cp /usr/src/redhat/SOURCES/perl*.patch .
    $ cd perl5.005_03
    $ patch -p1 <../perl5-installman.patch
    $ patch -p1 <../perl5.005_02-buildsys.patch
    $ patch -p1 <../perl5.005_03-db1.patch

  5. You need to run Configure, accepting most of the defaults from the script. You will also probably want to specify 'none' for the man pages. A few of the defaults to change in my example are listed below:
    $ ./Configure

  6. Compile and install it.
    $ make
    $ make test
    $ make install

  7. Create symlink to perl in the usr/bin tree. If you are not installing mod_perl (see ahead), then you could change ownership of the perl tree to root (but not necessary as long as the permissions on the perl tree are read-only for the web-tree owner: uid '888' in this example):
    ROOT# cd /www/usr/bin
    ROOT# ln -s ../Local/bin/perl perl

  8. Check the shared libraries and install any missing libraries (depends on your configuration options). No extra libraries are needed in this example:
    ROOT# ldd /www/usr/bin/perl
      libnsl.so.1 => /lib/libnsl.so.1 (0x4001b000)
      libdl.so.2 => /lib/libdl.so.2 (0x40031000)
      libm.so.6 => /lib/libm.so.6 (0x40035000)
      libc.so.6 => /lib/libc.so.6 (0x40052000)
      libcrypt.so.1 => /lib/libcrypt.so.1 (0x40147000)
      /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
    
  9. Test your installation:
    ROOT# chroot /www /usr/bin/perl -v

    This is perl, version 5.005_03 built for i386-linux
    ...
    
  10. Set up the example perl cgi bin script installed with the apache server:
    ROOT# cd /www/apache/cgi-bin
    ROOT# chmod ugo+x *

  11. Start your apache server, and test the example perl cgi bin script installed with the server:
    ROOT# chroot /www /apache/bin/apachectl start
    $ lynx -dump http://yourserver/cgi-bin/printenv
    While you are at it, check test-cgi for shell CGI access as well:
    $ lynx -dump http://yourserver/cgi-bin/test-cgi

  12. Finally, REMOVE the execute bit from the example cgi-scripts, or remove them entirely. Don't let the general public have access to these scripts:
    ROOT# chmod ugo-x /www/apache/cgi-bin/*

* Compile and Install mod_perl

  1. This process assumes that your chroot-ed perl tree is owned by your source-code owner. It this is not the case then change ownership:
    ROOT# chown -R softs:softs /www/usr/Local

  2. Extract the source code for mod_perl:
    $ cd /usr/local/src/chr
    $ tar zxf /path/to/mod_perl-1.24.tar.gz
    $ cd mod_perl-1.24

  3. IMPORTANT: Put /usr/Local/bin first in the path before starting configuration. This helps to avoid problems with the configuration finding /usr/bin/perl or /usr/local/bin/perl first in your environment:
    $ which perl
    /usr/bin/perl

    $ export PATH=/usr/Local/bin:$PATH ## assuming a bourne shell
    $ which perl
    /usr/Local/bin/perl


  4. Now configure mod_perl; configure the Perl-side of mod_perl, and prepare the mod_perl subdirectory inside apache:
  5. Now make and install mod_perl into the chroot-ed tree:
    $ pwd
    /usr/local/src/chr/mod_perl-1.24

    $ make

  6. For the non-DSO installs only you must recompile apache and reinstall it:
    $ cd /usr/local/src/chr/apache_1.3.12/
    $ ./configure --with-layout=chroot \
    --enable-module=most --enable-module=so \
    --activate-module=src/modules/php4/libphp4.a \
    --activate-module=src/modules/perl/libperl.a

    $ make
    Stop apache if it was previously running, and install it:
    ROOT# chroot /www /apache/bin/apachectl stop
    ROOT# make install ## I am root!

  7. For non-DSO installs you can check for compiled-in PHP and mod_perl:
    ROOT# chroot /www /apache/bin/httpd -l | grep -E '(php|perl)'
    mod_php4.c
    mod_perl.c


  8. Test your mod_perl setup with the Hello.pm. perl module written by Doug MacEachern. You need to install it, edit httpd.conf and restart apache:
    $ cp -i Hello.pm \
    /www/usr/Local/lib/perl5/site_perl/5.005/i386-linux/Apache/


    Insert the mod_perl configuration necessary for Hello.pm into httpd.conf -- example:
    <Location /hello>
      SetHandler perl-script
     
      PerlHandler Apache::Hello
    </Location>
     
    ### Section 3: Virtual Hosts
    
    ROOT# chroot /www /apache/bin/apachectl restart
    $ lynx -dump http://yourserver:yourPort/hello
       Hello, I see you see me with Lynx/2.8.3dev.18 libwww-FM/2.14.
  9. If you are finished testing then comment out this entry in httpd.conf. Don't leave unnecessary functionality enabled in your apache configuration.

  10. NOTE: If you need to install other perl modules, you must put /usr/Local/bin first in your path before running perl Makefile.PL:
    $ export PATH=/usr/Local/bin:$PATH ## assuming a bourne shell

* Compile and Install mod_ssl

I hope you have read the additional notes section if you are planning a DSO install of mod_ssl.

You must compile both openSSL and mod_ssl. I have also elected to compile rsaref version 2.0. You should read the documentation for mod_ssl in the source code table to understand the issues and the options for mod_ssl.

Note that openssl and rsaref provide the include files, libraries and tools to allow you to compile mod_ssl and generate keys, and therefore they are not part of, nor installed into, the chroot-ed tree.

  1. Extract the source code for mod_ssl, openssl and rsaref20:
    $ cd /usr/local/src/chr
    $ tar zxf /path/to/mod_ssl-2.6.6-1.3.12.tar.gz
    $ tar zxf /path/to/openssl-0.9.5a.tar.gz
    $ mkdir rsaref-2.0
    $ cd rsaref-2.0
    $ tar Zxf /path/to/rsaref20.1996.tar.Z

  2. Configure and build the RSA Reference library. Note that on 64-bit architectures you MUST read the documentation in the INSTALL file in the mod_ssl package about portability problems/solutions with rsaref.
    $ cd /usr/local/src/chr/rsaref-2.0
    $ cp -rpi install/unix local
    $ cd local
    $ make
    $ mv rsaref.a librsaref.a

  3. Configure and build the OpenSSL library.
    $ cd /usr/local/src/chr/openssl-0.9.5a
    $ ./config -L/usr/local/src/chr/rsaref-2.0/local -fPIC
    $ make
    $ make test    # inspect output for anomolies

  4. You may want to install the package. Of course, it is not installed in the chroot-ed tree. Here I assume that softs:softs owns the /usr/local/ tree, because the default install prefix for openssl is /usr/local/ssl. However, it is not necessary to install this package; you can operate out of the src tree for building mod_ssl (but do NOT run make clean!)
    $ make install

  5. Configure mod_ssl:
    $ cd /usr/local/src/chr/mod_ssl-2.6.6-1.3.12
    $ ./configure --with-apache=../apache_1.3.12

  6. Go into the apache tree to complete the build. Run configure and then make:
    $ cd /usr/local/src/chr/apache_1.3.12
    $ make

  7. Install apache again. Stop apache if it was previously running, and then install it:
    ROOT# chroot /www /apache/bin/apachectl stop
    ROOT# make install ## I am root!

  8. For non-DSO installs you can check for the compiled-in modules:
    ROOT# chroot /www /apache/bin/httpd -l | grep -E '(php|perl|ssl)'
    mod_ssl.c
    mod_php4.c
    mod_perl.c


  9. Create the random devices in the chroot-ed tree:
    ROOT# cd /www/dev
    ROOT# mknod random c 1 8
    ROOT# mknod urandom c 1 9

  10. Merge the default configuration file into your current httpd.conf file. I test on a different port from the standard port 80 because I usually already have a web server running on port 80. But for the secure port (port 443) I have no web server running, so I use it immediately.

    For the default configuration file the main fields to change for this example follow (and here is an example httpd.conf file):

  11. If you do not already have a server key and certificate then create them. In this example I assume that openssl is in your path because you have installed it. If not, then you should add it to your path (according to this example it is in /usr/local/src/chr/openssl-0.9.5a/apps).

    Note also that I am certifying my own key. Presumably you will get a Certifying Authority to sign your key if you are doing any serious work with your web tree (eg: commericial work):


  12. Start apache first without ssl to make sure it still works:
    ROOT# chroot /www /apache/bin/apachectl start
    $ lynx -dump http://yourserver:8088/

  13. Re-start apache with ssl and test it with netscape (note that the URL is specified as https):
    ROOT# chroot /www /apache/bin/apachectl stop
    ROOT# chroot /www /apache/bin/apachectl startssl
    $ netscape https://yourserver/

  14. At this point you probably want to edit your web server configuration and set the server on the standard ports 80 and 443 if your test configuration did not use these ports.

* Some Security Considerations

  1. See the 'security tips' in the online apache documentation for some help in this area. One extra precaution to take is to change the permissions on the httpd scripts and binaries:
    ROOT# chmod ugo-rw /www/apache/bin/*

* Escaping Your Chroot-ed Environment

  1. You should be very careful when you set about deliberately escaping from your chroot-ed environment -- you need to assess the risks and benefits. In the UNIX world there is always more than one way to accomplish a task, and you should think about other ways of solving your problem.

    Never the less, I provide an example C-utility that implements a customised remote-shell command to email a file generated by forms output to someone. It might be invoked via a cgi-bin script, or via PHP. Example:
          <?php
          ...
          /** construct the file name as $f  **/
          $cmd = "/bin/mail \"-s Some-subject-line -t webmaster@localhost -f $f\"";
          $op = exec( $cmd, $arr, $retval );
          ...
          ?>
       
    The file is called wwwmail.c and it is linked here.

    Almost anything can be done this way if you code-up your own small utility. I have written a similar utility to exec sqlplus macros for example. But these sorts of utilities are risky, and need to be carefully evaluated.

    For this particular problem (emailing forms-output to someone) you might be better off putting files to be mailed in a directory and having a cron job pass through every few minutes and process them...

* Cleanup, etc. After Installation

  1. Remove temporary links needed for installation of apache and perl ( remember to put them back if you need to rebuild or upgrade any package ):
    ROOT# rm /apache /usr/Local

  2. Automate the startup of Apache by installing a startup script called httpd in /etc/rc.d/init.d/ Here are two examples:
    Then run chkconfig on it to set the runlevel symbolic links (and verify it with '--list'):
    ROOT# chkconfig --add httpd
    ROOT# chkconfig --list httpd
    httpd       0:off   1:off   2:on    3:on    4:on    5:on    6:off
  3. Automate log file trimming. On a Red Hat system you can specify which log files and which parameters to use in /etc/logrotate.conf. Here is an example file

* New: Harvesting files based on RPMs

    I haven't had time to totally document this, but you can use the RPM contents from RPMs and create a chroot-ed web tree without compiling the sources. To this end, I have these scripts. I will document this technique more completely later...
  1. Script file based on Red Hat 7.0 that will harvest the RPMs (RPMs must be installed on system)
  2. Script file for creating temporary SSL key and certificate (testing purposes only!!!)
  3. Script file based on Fedora Core 2 that will harvest the RPMs (RPMs are NOT installed on system with this version!)
  4. Example httpd startup file for FC 2 to be placed in /etc/init.d/ and enabled with
      ROOT# chkconfig --add httpd
  5. Script file 'apachectl' for FC 2 called from /etc/init.d/httpd that does the actual chroot - modified slightly by adding path to chroot tree. It also adds the mysql libraries to the library path.

Denice Deatrich
Last modified: Wed Jan 5 11:59:32 PST 2005