Installing web services on FreeBSD

Use PHP at your own risk. (sorry, just a little joke... no, not really.. be careful)

I know there is already a lot of material about this topic, but... I set up another web server today and this time I took some notes. Maybe somebody will find them useful.

Have your FreeBSD installation securely patched and the ports collection updated. This does NOT cover chrooting or jailing. The installation process takes less than half a day. I am not exactly sure, because I wandered off during port compiles. (which was yet-another-reason to switch to OpenBSD)

My Goal is to set up a web server capable of serving open & encrypted pages (http & https) with popular software. I also want to be able to create dynamic (vs static) web pages and applications, with an option of using a database.

I chose Apache 1.3, you may choose something else. I also chose mod_ssl so I can serve pages securely over SSL (https). As always, read the Makefile before beginning to look for flags. Let's get right to it:

cd /usr/ports/www/apache13-modssl
make

It seems that expat is always out to get me. The make stopped, and I had to deinstall and reinstall expat. I then came back to this directory and did a make again. Finally the screen below appeared:

... answer all the questions. Note, when asked for FQDN, put the Primary DNS web address. The box may be called server123.domain.com, but will answer www.domain.com... so use the latter. Steps 7&8 encrypt your cert and server. They strongly recommend you to encrypt the server.key file with a Triple-DES cipher and a Pass Phrase.

When you have finished answering all the questions you will get:

Congratulations that you establish your server with real certificates.

Now do a make install When it is finished you need to edit
/etc/rc.conf (see other article if needed)
by adding 'apache_enable=YES' so it will start at boot. Now start Apache:

/usr/local/etc/rc.d/apache.sh start

and use a brower to test the http and https.

Hey, it worked!
The SSL/TLS-aware Apache webserver was
successfully installed on this website.

It looks like everything is going well, except one sticky point. Steps 7 & 8 in the cert creation will require you to type the pass-phrase everytime you start the server. While this is secure, it can be a pain. So, use the openssl program to encrypt the key with your pass-phrase. First list the keys to make sure we can proceed.

ls /usr/local/etc/apache/ssl.key/

Then copy the key so the original can be encrypted with the openssl command. You will need the pass-phrase again.. but only this once. When finished; restart Apache and tail the error logs to look for problems.

Depending on the situation, I found Name-based Virtual Hosting sometimes fits my needs.
Read the Apache documentation and decide for yourself what fits yours.

The sample IP address used here (192.168.0.111) does not have to be this machines address. It may be a common pool, or CARP, address.
What is important is that DNS has all the web addresses below and maps them to that IP. DNS is not covered here.

Each virtual host below is different for different reasons. You can test both the DNS and Apache by creating the directories off the web path and putting a
simple index.html file containing the server name, IP, and domain.

I add another directive that is specific to using the PHP web scripting language. Many people tend to save include files with the .inc extension.
If you do not want these pages ever served, just like .ht files, have apache deny them.

<Files ~ "^\.inc">
Order allow,deny
Deny from all
Satisfy All
</Files>

For log analysis and statistics there are several choices; analog, webalizer, and visitors are popular. I have used all of them and they are easy to install and use, even on complex environments.

To illustrate, I have a web installation (not the box I did today) that has multiple domains and subdomains; mirrored on multiple servers tied together with CARP. (jealous?) So, analyzing the logs took a little planning and a little scripting. For most of the domains the logs were collected in different files just in case we wanted to look at them that way. But, it turns out, I could combine some of them for analysis. Others I wanted kept separate all the way through. I cron'd bash scripts to handle combining, taring, and ftp'ing the resulting files to a central server. Once there, I combine and sort them as needed before calling the log analysis applications on the central server each night. Each morning we have a fresh batch of web stats. Note: For that client, everyone; from executives down; claim they REALLY NEEDED web stats; but over time noone actually looks at them. I should know, I log those pages too... and I look at them. [grin]

PHP (recursive acronym for "PHP: Hypertext Preprocessor") is a widely-used
Open Source general-purpose scripting language that is especially suited for Web development and can be embedded into HTML.

cd /usr/ports/www/mod_php5
make
make install
***************************************************************
Make sure index.php is part of your DirectoryIndex.
You should add the following to your Apache configuration file:
AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps
***************************************************************

Edit /usr/local/etc/apache/httpd.conf as recommended above.

Copy the recommended php.ini and make any edits you see fit.

cp /usr/local/etc/php.ini-recommended /usr/local/etc/php.ini

On FreeBSD, PHP installs pretty safely. But don't take my work for it. You should really check the whole php.ini file and read their superior online documentation for yourself. You should have an understanding of why switches are present and what the settings mean. As is true for almost ALL CONFIG files, leave yourself comments in the file when you make changes. This will help you track them down later -and- when upgrading the server.

This is a new setup so I can follow strict coding standards. I have a few pet peeves, so, I make sure the following are set. You may have to audit any old php scripts to meet these new standards.

short_open_tag = Off

error_reporting = E_ALL

register_globals = Off

allow_url_fopen = Off

safe_mode = On

PHP can report errors quietly to a log file or very loudly right to the browser. PHP catches all errors but only reports what you want it to report. You may want PHP to show [E_ALL] the errors of your ways, and want them in the browser; during development. This forces one to code more cleanly - to get rid of all the errors in your face. Alternately, you could just have PHP put errors to a log file and tail -f the log at a different prompt. Regardless, in production, I change the ini file to put E_ALL errors in log files only.

Next, I uncomment and set an include directory in the 'Paths and Directories' section. I can put sensative files, like db passwords, there and they will not be served because

.inc files are not served [see Apache section] and

I set the include directory to be outside the document path.

While you are in the ini file you may decide to change the directory settings that default to "/tmp", which is world readable.
Have a look at session.save_path and mysql.default_socket. The later would require changes in its config file: my.conf.
I have heard good arguments to change mssql.allow_persistent to Off. You may want to consider that.
allow_url_fopen defaults to On, but I believe it poses a security risk. Better to have it Off globally then switched On as needed in a script.

Restart Apache and create a test file to serve up.

echo "<?php phpinfo() ?>" > /usr/local/www/data-dist/testfile.php

Then call that file from the browser to test PHP.

lynx https://www.domain.com/testfile.php

This should bring back gobs of data about your installation.

Important

After everything is working for you, you should delete that file before you go into production... well... because it delivers gobs of data about your installation, and that may be insecure.

I chose MySQL. You may choose something else. Again, I wanted to try the lastest, so I chose version 5. But, any version should work. Please, read the Makefile in the port directory, and choose your own build flags.

Note if you are upgrading, you should read the MySQL Upgrade documentation.

I can not stress enough how important "WITH_LINUXTHREADS=yes" is to a smoothly running MySQL database on FreeBSD.

When the port finishes it gives several good hints. Read them! Here is a quick start:

Have a look at the different config options that come included and choose the one that fits your needs:

/usr/local/share/mysql/my-[small|medium|large|huge].cnf. As it states in the header of the file, you
can copy one of them to my.cnf and make changes to it. The server will run with defaults if you do nothing.
As mentioned in the PHP section, you may want to change the default socket in the [client] and [server] sections.
The default location for databases on FreeBSD is /var/db/mysql. You are free to put the db's anywhere you want, as long as you mention it in the cnf.

# You can copy this file to
# /etc/my.cnf to set global options,
# mysql-data-dir/my.cnf to set server-specific options (in this
# installation this directory is /var/db/mysql) or
# ~/.my.cnf to set user-specific options.

Edit /etc/rc.conf again by adding mysql_enable=YES, so the db starts at boot. Then start the database for the first time.

We are not finished yet. If you go back to your browser and reload testfile.php script you will notice that mysql is still not listed. You need the php-mysql module to do that.

cd /usr/ports/databases/php5-mysql
make
make install

When I ran this on my box, it spit out what looked like an error "This port is deprecated; you may wish to reconsider installing it: Please use devel/automake19 instead.", but it was talking about the automake script not the php-mysql port. When it is finished, restart apache and check your testfile.php in a browser. You should see a mysql section.

OK, BAMP!! (a play on words from the linux community [LAMP])-- you have the basics out of the way. Now you just have to write a dynamic, data-driven, standards based, browser agnostic website with distinct separation of data, content, and markup!!