Friday, April 20, 2007

Setting Up a Server

This article teaches you, the reader, how to configure a GNU/Linux based server with three of the most important services that must be provided in a company, at home, a lab or anywhere else, both for clients and internal usage: web, database, mail. So it will be assumed that the idea is to host websites that use certain technologies such as a scripting language and a database (for dynamic sites), and also to act as a mailing tool, for sending and receiving email.

Consider that this article only shows some of the basic features for configuring these services, each program has much more in depth options. Entire books have been written just about Apache or MySQL. So, don't just stay with what you learn here, play around, read, learn; system administration is all about security and performance, so there's a lot more to discover.

I have also decided to show some optimization (tuning) techniques for a better performance. We will use only free/open source software in this article, thus,it is not necessary to buy commercial licenses. The software we will use is Debian GNU/Linux, Apache, MySQL, PHP and Postfix. The first three are what is called LAMP, where the P can stand for various server side scripting languages such as PHP, Perl and Python. In general, it represents the open source web platform (both for developing and using it). I have been using LAMP and Postfix for years and must say that, after trying lots of other programs of the same sort, it is the wisest choice if you want a powerful, easy to use/configure/maintain and secure server environment.

Why use Debian? I have always liked this distribution because it's easy to manage packages (programs) and system services. It is also very secure and stable, making it perfect for servers and any system that must run 24/7. It's huge package repository (over 15490) is more than enough to get the best use out of any computer system.

Why use Apache? Simple - it's currently the best, most secure and most used HTTP server. It also supports a huge amount of modules and extensions. Here are some specific benefits of Apache: support, efficiency, portability and customizability.

Why use MySQL? It's logo says it all: The world's most popular open source database. This DBMS is reliable, powerful and easy to manage and use. Also, we will use it with Postfix for better integration and performance.

Why use Postfix? If you ask any systems administrator why he/she uses Postfix as a Mail Transport Agent (MTA) the answer will be it's easy and fast. Another great feature is it's security and the wide amount of operating systems it can run on (BSD, Linux, AIX, Solaris, OSX, etc.)

Installing and Configuring Apache

We will use Apache 2 because it has been rewritten for better performance and security. It brings more out of the box optimizations for scalability and throughput, as opposed to version 1.3 (which is not even being maintained anymore). So let's get to it, we first download and install the essential software:\

apt-get install apache2

This will also install the following packages: apache2, apache2-common,apache2-mpm-worker and apache2-utils. Now, try connecting to localhost:80 and you should see a page saying that Apache as been configured correctly. If not,you might have something wrong with the network settings, but that's a whole different ball game. By default, when installing services in Debian it leaves them configured to start when you boot GNU/Linux so you don't have to worry about further system configuration. For controlling the daemon we have apache2clt or we can use Debian's init utilities:

/etc/init.d/apache2 start|stop|restart|reload|force-reload
apacheclt start|stop|restart|...

Apache2's configuration files, by default, are in /etc/apache2/. Whenever a configuration is modified, the server must be restarted. Here is a description of some of the more important files and directories:

  • apache2.conf is where the main configuration is, it used to be httpd.conf, so don't be fooled.
  • mods-available/ is the directory with all the modules that are available. The .load contain the Apache directives that are needed to load the modules. And the .conf are the configuration directives for each module.
  • mods-enabled/ is the directory that contains the symbolic links to the modules that we want to enable from mod-available/. At least the .load file must be there, so we will have: /etc/apache2/mod-enabled/modulex.load -> /etc/apache2/mod-available/modulex.load

Let's take this to practice, say we want to enable user directories:

(www.myurl.com/~someuser/). First uncomment the following in apache2.conf:

Next, we create the symbolic links for this module and restart the server:

cd /etc/apache2
ln -s mods-available/userdir.* /etc/apache2/mods-enabled/
/etc/init.d/apache restart

This works for all the modules you want to load. Now let's try some optimization methods. Apache uses a great deal of resources, specially RAM, because it accumulates whatever is necessary to accommodate what it's serving and this process never decreases until it is complete. This takes up as much RAM as the largest dynamic script.

To help reduce this problem, edit apache2.conf and enable KeepAlive (increases time) and set a low value for KeepAliveTimout (this will reduce the time the process waits without doing anything). Also, set the value for MaxRequestsPerChild around 20, depending on the amount of dynamic sites the server is hosting. The idea behind this is that when the process ends, it makes it start over again, but with lower RAM usage. However, by doing this, you might have to increase MaxClients around 50%.

Installing and Configuring MySQL

MySQL 5 introduces a number of new features, compared to older versions, such as new data types, precision math, better performance for storage, faster queries and better handling of certain types. The list goes on, so I recommend checking out the official documentation to see how you can take advantage of the latest version. To get it:

apt-get install mysql-server-5.0

libdbd-mysql-perl, libmysqlclient15off, mysql-client-5.0 and mysql-common will also be installed. Debian will also make sure MySQL starts at boot time. To control the daemon, I use the init script and voila!:

/etc/init.d/mysql start|stop|restart|reload|force-reload|status

To first start working with this database, the root password must be set. The word root does not apply to the system's root, but to the database administrator, however, it can be the same person. So let's set it and log in:

mysqladmin -u root password 'thepassword'
mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 10 to server version: 5.0.20a-Debian_1-log

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql>

If you don't like using the command line system (lazy sysadmins), there a couple graphical user interfaces for MySQL, such as MySQLCC (QT), gMySQLCC (GTK+), etc. Since everything is running fine (or should be) it's time to optimize. MySQL uses algorithms that let you run it with little memory, but you can give it options to increase the memory usage if you have more, and therefore increase performance. To lower the amount of time MySQL sits waiting, edit the configuration file: /etc/mysql/my.cnf and add/change the following (values may vary depending on your specific needs):

wait_timeout=60
connect_timeout=10
interactive_timeout=100
join_buffer_size=1M
query_cache_size=128M
query_cache_limit=2M
max_allowed_packet=16M
table_cache=1024

Installing and Configuring PHP

Now that we have our httpd server up and running we can setup PHP. Debian includes PHP5 in the official package repository, not too long ago only up to version 4 was supported. So let's get it:

apt-get install php5

Just like for Apache and MySQL, extra packages will have to be install as well: apache2-mpm-prefork, libapache2-mod-php5 and php5-common.

Now, add support for MySQL:

apt-get install php5-mysql

I also like to add some more packages for PHP, such as CLI, Pear, LDAP, IMAP, GD, mhash, ODBC and PostScript:

apt-get install php5-cli php-pear php5-ldap php5-imap php5-gd  php5-mhash php5-odbc php5-ps

The configuration file for PHP is located in /etc/php5/apache2/php.ini, every time you modify it, Apache must be restarted. So let's see if everything is working. First let's create a simple script, called information.php, in Apache's DocumentRoot, that is /var/www/information.php and inside it should go:

Now, fireup a browser and open www.mycompany.com/information.php. You should see a page with information about the PHP version that is installed. Also it provides some details about Apache, and all the PHP modules. Last, but not least, let's make sure MySQL and PHP are working well together. First, log in to MySQL and create a new database:

mysql> create database test;
Query OK, 1 row affected (0.00 sec)

mysql> exit
Bye


'

Create a new file, db.php, in the same directory and write:

 

Check your browser and you should see: connection success. Now for a little optimization. Usually compiling PHP scripts on the fly uses a lot of memory, so if your hosting several big web sites and have lots of users visiting, you might want to do something about this resource abuse. The solution is to use a program that keeps the scripts precompiled. The most popular include Zend Accelerator, Turck MMCache and PHP Accelerator. Performance can increase up to 200%.

Finally LAMP is up, running and optimized. You can also provide further services, such as more databases (PosgreSQL, Oracle, Informix, etc) and more server side languages (Perl, JSP, Python, etc).

Installing and Configuring Postfix

Postfix was originally written as an alternative to Sendmail, which is used in most mail servers around the world. Unfortunately, Sendmail is hard to use (and manage) and very bug prone, therefore securing it can be quite a task. This is why Postfix is a fantastic option. Just like with the rest of the software, we download and install it, with support with MySQL:

apt-get install postfix postfix-mysql

Leave the values dpkg suggests when configuring. The default configuration files are in /etc/postfix, we will only use main.cf. Once done, we create the postfix user for MySQL and the database for the emails:

  mysql -A -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 4 to server version: 5.0.20a-Debian_2-log

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> use mysql;
Database changed
mysql> insert into user (host, user, password) values ('localhost', 'postfix', password('thepostfixpass'));
Query OK, 1 row affected, 3 warnings (0.00 sec)

mysql> insert into db (host, db, user, select_priv) values ('localhost', 'mail', 'postfix', 'Y');
Query OK, 1 row affected (0.00 sec)

mysql> create database mail;
Query OK, 1 row affected (0.01 sec)

Afterward, MySQL must be restarted to use the new user and database. If everything worked correctly, then there shouldn't be any problem logging in as postfix using the mail database. So now we create our tables, as root:

  mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3 to server version: 5.0.20a-Debian_2-log

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> use mail;
Database changed
mysql> create table transport (
-> domain varchar(255) primary key,
-> transport char(8),
-> access varchar(2)
-> default 'OK');
Query OK, 0 rows affected (0.01 sec)

mysql> create table aliases (
-> id int(6),
-> alias varchar(255) primary key,
-> maildir varchar(255) not null,
-> access varchar(2)
-> default 'OK');
Query OK, 0 rows affected (0.00 sec)

mysql> create table remote_alias (
-> alias varchar(255) primary key,
-> rcpt varchar(255) not null);
Query OK, 0 rows affected (0.01 sec)

mysql> create table domain1 (
-> user varchar(255) primary key,
-> pass varchar(255) not null,
-> maildir varchar(255) not null,
-> active int(8)
-> default 1);
Query OK, 0 rows affected (0.00 sec)

The next step is configuring Postfix to support MySQL, so edit the configuration file and add:

  transport_maps=mysql:/etc/postfix/transport.cf
virtual_mailbox_base=/home/postfix
virtual_uid_maps=mysql:/etc/postfix/ids.cf
virtual_gid_maps=mysql:/etc/postfix/ids.cf
virtual_mailbox_maps=mysql:/etc/postfix/aliases.cf
virtual_maps=mysql:/etc/postfix/remote_aliases.cf

Since we are specifying files that don't exist, we must create them. In transport.cf write:

  user=postfix
password=thepostfixpass # the password used in MySQL
dbname=mail
table=transport
select_field=transport
where_field=domain
hosts=localhost

  user=postfix
password=thepostfixpass # the password used in MySQL
dbname=mail
table=aliases
select_field=maildir
where_field=alias
hosts=localhost

In ids.cf:

  user=postfix
password=thepostfixpass # the password used in MySQL
dbname=mail
table=aliases
select_field=id
where_field=alias
hosts=localhost

And for the final file, remote_aliases.cf:

user=postfix
password=thepostfixpass # the password used in MySQL
dbname=mail
table=remote_aliases
select_field=rcpt
where_field=alias
hosts=localhost

Lets now create the information for the domain1 example in MySQL:

mysql -A -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8 to server version: 5.0.20a-Debian_2-log

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> use mail;
Database changed
mysql> insert into transport(domain, transport) values ('domain1.com', 'virtual:');
Query OK, 1 row affected (0.00 sec)

To add users to that domain, simply insert into the aliases table the data (you can get postfix's userid from /etc/passwd, for example:

mysql>insert into aliases values
(postfix_uid,'
user@domain1.com','domain1/user', 'OK');

Finally everything should be working smoothly. Make sure you constantly check the logs (/var/log/mail.log), even if everything is normal, because the first place you might detect an attack is there.

No comments: