CentOS
From LinodeWiki
Contents
|
[edit] CentOS 5.2 Virtual Hosting
This tutorial will guide you in setting up your Linode for virtual hosting using the CentOS 5.2 64bit distro. At the end of this tutorial you will have a Linode that can host websites and email for multiple domains.
[edit] Introduction
CentOS is a Linux distribution based upon Red Hat Enterprise Linux.[1]
CentOS is an Enterprise-class Linux Distribution derived from sources freely provided to the public by a prominent North American Enterprise Linux vendor. CentOS conforms fully with the upstream vendors redistribution policy and aims to be 100% binary compatible.[2]
This tutorial is written for an experienced PC user. Steps in this tutorial involve editing scripts, setting up MySQL databases, and compiling form source. Most steps will be covered briefly and the reader is expected to research them further.
It is important to not blindly follow any tutorial on the internet. Time is well spent researching each command and option as they are discussed. The research will pay off as your Linode progresses.
[edit] Tutorial Requirements
You will need a Linode account and a domain name for this tutorial. You will also need some way of connection to your Linode, preferably an SSH client.
The two other requirements are a willingness to read and plenty of time. This tutorial will take most of a day to complete. So get your favorite beverage ready, shut yourself in, and get ready for some hacking.
[edit] Tutorial Goals
There are an infinite number of ways to configure your new Linode. As such, no one tutorial will cover all possible situations. The goal of this tutorial is to setup a web and email server without a control panel. This Linode setup will be used to host websites and email for multiple domains.
Each domain will get the following:
- Shell access
- Ability to add and remove email addresses
- Direct access to domain email directories
- Per email sieve scripts
[edit] Tutorial Components
A list of the major components of this guide follows.
| Component | Version | Install Method | Short Description |
|---|---|---|---|
| Lighttpd | 1.4.22 | source | Serves each website. |
| ClamAV | 0.95.1 | source | An email virus scanner |
| Dovecot | 1.1.16 | source | Accepts email from Postfix and delivers it to a local users account. |
| Dovecot Sieve Plugin | 1.1.6 | source | Gives Dovecot the ability to manipulate emails after they are accepted for delivery. |
| MailScanner | 4.76.25-1 | source | Passes incoming email to Spamassassin and ClamAV for scanning. |
| MySQL | 5.0.45 | binary | Database server. |
| PHP | 5.2.10 | source | A server-side scripting language. |
| Postfix | 2.6.2 | source | Accepts email from other servers on the Internet. |
| Postfix Admin | 2.2.1.1 | source | An easy email account administration tool. |
| SquirrelMail | 1.4.19 | source | Webmail access. |
| SpamAssassin | 3.2.5 | source | Scans email and identifies spam messages. |
[edit] Tutorial Conventions
Commands that should be executed on the Linode appear as follows. It is important to note that the '$' beginning the line should not be typed.
$ls -al
Input that must be specified by the reader is wrapped in brackets "[" and "]". Both the brackets and the text contained by them must be replaced by the reader.
For example:
$ls -al [DIRECTORY]
Could become:
$ls -al /etc
Commands that are being explained and need not be executed will appear inline with the text as: ls.
Text that is either in a file or should be placed in a file appears as follows.
FILE: /etc/sudoers
## Allows people in group wheel to run all commands # %wheel ALL=(ALL) ALL
[edit] Linode Setup
Before the configuration can begin your Linode must be partitioned and the operating system (OS) must be installed. Fortunately, the Linode Manager makes this a simple process.
The goal of this step is to partition your Linode into four sections. The first section will be the primary boot device. The second and largest section will hold the /home directory. The third section is an unused copy of the primary boot device and the final section is for swap.
| Size | Use |
|---|---|
| 3072 MB | Primary boot device |
| 9984 MB | /home |
| 3072 MB | Unused boot device backup |
| 256 MB | Swap Image |
Please note that using this partitioning scheme is not entirely necessary. By setting up your Linode like this you will lose a portion of your usable harddisk space to the boot device backup. However, the benefits of having a bootable copy around may outweigh your need for extra space. The backup copy is very useful for getting your Linode running again should something go wrong.
[edit] Deploy a Linux Distribution
Login to the Linode Manager at https://www.linode.com/members/. Once logged in access the Linode that you would like to setup by clicking on the Linode's name. If this is your first time logging into the Linode Manger you may be greeted with a welcome message.
In the Linode Dashboard click on Deploy a Linux Distribution. You will then be taken to the Linode Distribution Wizard where you can select your flavor of Linux and other settings. Please note that you may setup and delete Distributions at will, doing so takes a matter of minutes.
At the Linode Distribution Wizard choose the following settings:
| Description | Setting |
|---|---|
| Select your Distribution | Centos 5.2 64bit |
| Select Disk Image Size | 3072 |
| Select Swap | 256 |
| Root Password | [Your root password] |
An image size of 3072 MB is necessary for CentOS if it will be updated to 5.3. Feel free to adjust this to suit your particular needs. Click on Create Profile to begin the OS install process. This will bring you back to the Linode Dashboard.
[edit] Create a Backup Disk Image
If you have elected to use some extra space for a backup of your boot disk image continue with this step. If you would rather make use of all of the space on your Linode you may skip this step.
In the Linode Dashboard click on Create a new Disk Image. You will be taken to the Create an empty Disk Image where you should use the settings that follow.
| Description | Setting |
|---|---|
| Label | boot disk backup |
| Size | [The same setting you used for "Select Disk Image Size" above] |
| Filesystem Type: | ext3 (Default) |
Click on Create Disk and go back to the Linode Dashboard.
[edit] Create a /home Disk Image
In this tutorial the home directory is separated so that a backup of the boot device can be easily made. If you would rather not split the home directory off from the main Image then skip this step. If you are skipping this step you will want to increase the size of your primary boot image.
All of the user directories, email, and websites will live in the home directory. This data is not needed by the OS and can be easily separated from it. To do so another disk image will be created and the OS will be configured.
In the Linode Dashboard click on Create a new Disk Image. You will be taken to the Create an empty Disk Image where you should use the settings that follow.
| Description | Setting |
|---|---|
| Label | /home |
| Size | [Your remaining disk space] |
| Filesystem Type: | ext3 (Default) |
Click on Create Disk and go back to the Linode Dashboard.
[edit] Add the New Drive
Now that a new drive is setup it must be added to the configuration profile for use. Go to the Dashboard for your Linode and click on your configuration profile under Configuration Profiles. Under Drive Setup select the "/home" Image for Device "/dev/xvdc".
Leave the rest of the settings at their defaults and click on Save Profile.
[edit] Final Configuration Settings
Now is the time to setup the rest of your needed settings. You may want to use the DNS Manager to add a domain to your Linode. You may also wish to write down your Network Settings under the Network tab.
[edit] Initial Boot
Once you are ready to begin the main configuration go to your Linode's Dashboard and click on Boot.
However, note that booting into multi-user mode with networking enabled (i.e., using the default Linode runlevel) is a security risk. If a cracker sees your VPS, he could run scans against it and then run a targeted exploit on a vulnerable service, possibly giving him root access. This can literally be accomplished within seconds, or even less than a second if the cracker is on the same Linode subnet (see "Real World Linux Security, 2nd Edition" p. 66). For additional security, most steps below (except for updating the software) should be performed by booting the Linode with the runlevel set to 'single user mode' or 'init=/bin/bash' (this boots without networking enabled), and using lish to access the VPS. A very restrictive firewall should be configured before networking is first enabled, in order to update OS/packages. Virtually all services should be disabled until after the OS/packages are updated. Then, only enable the services you need.
[edit] Hardening
During this first part of the setup the newly setup Linode will be locked down a little. The entry point for you will be configured, then a firewall will be setup, and finally the OS will be updated.
[edit] Locking Down SSH
The Linode Manager has a console based terminal that can be used to send commands to the Linode. You can get by using this as your primary means of accessing the server, however it is a little limited.
Another way of communicating with your Linode is through SSH. SSH is a Secure Shell and will be the primary means of communicating with the Linode in this tutorial. Finding an SSH client is left as an exercise for the reader. (Windows users can use PuTTY)
The Linode CentOS distribution comes preconfigured with the OpenSSH sshd server installed. However, the initial configuration is not secure enough for the needs of this tutorial. Begin by logging onto your Linode with your SSH client.
[edit] Disable Root Access
In Linux the primary administrative account is called root. This account has full control over the entire system. As such it should be both respected and protected. Rarely login directly as root and always have a purpose in mind while doing so. Only users that are critical to operating the Linode should have root access.
With that in mind, the first step to securing SSH is to disable root access. To do so a new user will be added and given administrative rights. Then the root login will be disabled. Disabling root access is an important step because it makes it harder for an attacker to gain root on your VPS.
All commands in this tutorial must be run as the root user unless otherwise noted. So how do you issue root commands after locking the root account out? You have two simple options su and sudo.
$su
The command su switches you to the root user, making you root until you type exit. After issuing the command you will be asked for the root password.
$sudo ls /root/
sudo runs the given command as the root user. It is handy for one time commands that need root privileges. You will need to enter your password, not the root password, when prompted (assuming you stick with the default configuration). We will configure sudo such that only users in the wheel group can issue this command.
[edit] DETOUR: Splitting off /home
Now is a good time to finalize the /home disk image created above. With a newly installed OS there should be no data in the /home directory to worry about. You only need to do this step if you decided to Create a /home Disk Image above.
To begin mount the new drive as /home. Your new home disk image should have been added to your Linode configuration in the Add the New Drive as drive "/dev/xvdc".
$mount /dev/xvdc /home
That will attach the /home directory to drive /dev/xvdc until a reboot. To automatically mount the directory add the following line to the end of the /etc/fstab file.
FILE: /etc/fstab
/dev/xvdc /home ext3 defaults 1 2
[edit] Add a New User
Adding a new user is straight forward and will be done several times in this tutorial. In this case this new user will be the primary means of logging onto the Linode. You must add a new user before disabling root or else you will not be able to ssh into the VPS (but lish will still work).
Simply run the following commands, where [USERNAME] is the same in both:
$adduser [USERNAME] $passwd [USERNAME]
The adduser command will create the user and the appropriate directories needed. The passwd command will set the password for that user.
Now that the user has been added it must be given administrative access. To do this run:
$usermod -a -G wheel [USERNAME]
The usermod changes attributes for the given username. The option "-a" tells usermod to append and the "-G" option selects a group. Using these two options together we have, "append the given username to the wheel group".
Next we must modify the /etc/sudoers file to make the wheel group work as administrators. The only safe way to modify this file is to use the visudo command. That command will open up the sudoers file and will make sure that nothing else gets at it while you are messing with it.
Run the command:
$visudo
The command will open up the sudoers file with the vi editor. The vi editor has two modes, command mode and insert mode. Command mode allows vi to accept input commands while insert mode actually modifies the file. The important vi commands that we will use are ":q" (quit) and ":w" (save). To move into insert mode press the 'i' key a single time. To move back into command mode press the Esc key. Use the 'j', 'k', or arrow keys to scroll up or down in the file. See Mastering the VI editor or Google for more information.
Find the following:
## Allows people in group wheel to run all commands # %wheel ALL=(ALL) ALL
Delete the pound sign (#) on the second line so that it matches the following:
## Allows people in group wheel to run all commands %wheel ALL=(ALL) ALL
Removing the pound sign uncomments the line. This is pretty standard for most config files. Generally config files contain three types of lines; white space, commented lines, and configuration specifics.
Press the following keys:
Esc :w :q
[edit] Configuring sshd
See also CentOS - Securing OpenSSH.
Now that a new user is added, root can be locked out of ssh. Open up the sshd configuration file located at /etc/ssh/sshd_config with your favorite text editor. Make sure the following lines exist and are either uncommented or changed in the config file. Note that two lines must be commented out.
FILE: /etc/ssh/sshd_config
Port [somewhat random number below 1024] ListenAddress [your Linode IP address] PermitRootLogin no MaxAuthTries 3 IgnoreUserKnownHosts yes UsePAM no # UsePAM yes X11Forwarding no # X11Forwarding yes UseDNS no # uncomment the following line if you want to restrict who can use ssh # AllowUsers mark73j alice88p
The given configuration will set the ssh server to use listen to a random port number for ssh traffic. This security through obscurity moves the ssh server to a different port number, hiding it (somewhat) from an attacker. For security reasons the port should be below 1024. The other settings tighten down ssh a little more than the default settings. For further explanation of each option see [3].
Once the configuration changes have been made ssh must be reloaded. The following command will cause ssh to read the configuration file again.
$service sshd reload
Note: If you to use a Port number besides 22 the iptables rules may be blocking it. To fix this issue the following commands.
$iptables -F $service iptables save
[edit] Test SSH
Now test SSH by opening a new connection to your Linode. Do not log out as root yet! You will reach your server by opening a connection to your Linode address. However, the port number will be whatever number you selected above. Once you have logged in you can make sure the administrative account has root access by issuing the following command.
$sudo ls /root/
The test is successful if you see a list of all files in the root directory. The test fails you will see Permission denied. If the test fails go back to the open root session and make sure your settings match the above settings. If the test passes you may log out of the root session.
[edit] New User Setup
The new user created above is missing some directories from its path. You may notice that some commands were working for the root login but not for the new account. To fix this edit the hidden file .bash_profile with your favorite text editor. This file lives under your home directory and can be reached using ~/.bash_profile
Change the following line from:
PATH=$PATH:$HOME/bin
to:
PATH=$PATH:$HOME/bin:/sbin:/usr/sbin
Whenever you log in the file .bash_profile is read and executed setting the PATH variable. Once the file has been changed it needs to be reloaded. To reload the file issue:
$source ~/.bash_profile
[edit] TIP: SSH & Weird Characters
Sometimes you may run across some man pages that do not look correct. You may notice weird characters or other formatting issues. To fix this issue edit /etc/man.config file.
Find and change this:
NROFF /usr/bin/nroff -c --legacy NROFF_OLD_CHARSET -mandoc 2>/dev/null
To this:
NROFF /usr/bin/groff -Tlatin1 -mandoc
More can be found at How To Fix Weird Characters In Linux Man Page.
[edit] Update CentOS
In CentOS packages (binary software) are installed with the yum package manager. With yum you can install, update, or remove software that yum knows about.
Now that root has been locked out you can take time out to update all of the software installed on the Linode. Before this happens however yum must be informed of the mirrors that it can use when searching for software.
Open up the file /etc/yum.repos.d/CentOS-Base.repo in a text editor and modify the following. This will enable the plus repository, giving you access to a little more software.
FILE: /etc/yum.repos.d/CentOS-Base.repo
[centosplus] name=CentOS-$releasever - Plus mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=centosplus #baseurl=http://mirror.centos.org/centos/$releasever/centosplus/$basearch/ gpgcheck=1 enabled=0
to
[centosplus] name=CentOS-$releasever - Plus mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=centosplus #baseurl=http://mirror.centos.org/centos/$releasever/centosplus/$basearch/ gpgcheck=1 enabled=1
With the yum repositories setup start the update with the yum update command. This will cause yum to look for the latest versions of software installed on the machine. It is important to note that yum update will only update software that has been installed through yum. Any software that is compiled from source will not be updated.
$yum update
The update process will take several minutes. At some point after yum downloads packages you will be prompted to continue. Answer 'y' when prompted to complete the update.
[edit] Firewall Setup
The firewall of choice for this tutorial is called iptables, see Netfilter IPTables Mini Howto for further study. This tutorial uses the following shell script to setup rules. IPTables setup script. Save the shell script to your server as iptablessetup.sh. Then edit the following lines.
iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT iptables -A OUTPUT -p tcp -m tcp --dport 22 -j ACCEPT
to
iptables -A INPUT -p tcp -m tcp --dport [Your sshd port number] -j ACCEPT iptables -A OUTPUT -p tcp -m tcp --dport [Your sshd port number] -j ACCEPT
With the setup script saved and modified switch to the root user and then run it. The sh command tells the bash shell to execute the file called iptablessetup.sh. Shell scripting is very powerful and is worth further study.
$sh iptablessetup.sh
Now that iptables has been setup you must save the changes that you made with the service command.
$service iptables save
[edit] TIP: Loading additional iptables modules [FAILED]
If you see a message similar to Loading additional iptables modules: ip_conntrack_netbios_n[FAILED] edit the /etc/sysconfig/iptables-config file. Find and change the following lines. When you have finished making the edits restart iptables with the command service iptables restart. [4]
IPTABLES_MODULES="ip_conntrack_netbios_ns" IPTABLES_MODULES_UNLOAD="yes"
to
IPTABLES_MODULES="" IPTABLES_MODULES_UNLOAD="no"
Restart iptables:
$service iptables restart
[edit] Disable Unused Services
There are several services running by default that will not be used by the server setup in this configuration. They are essentially taking up space and cpu cycles so it is usually best to disable them.
To get a list of services which run on startup use the chkconfig command.
$chkconfig --list
The chkconfig command is also used to disable a service.
$chkconfig --level 0123456 [SERVICE NAME] off
The following services are installed by default for the CentOS 5.2 64bit distro and will be disabled. This information has been gathered from several sources. [5] [6] [7]
Later on in this tutorial Postfix will be installed and used as the default mail transport agent. This means that there is no reason to even keep sendmail around anymore. Remove it with the following:
$yum remove sendmail
| Service Name | Description |
|---|---|
| anacron | Runs cron jobs that were supposed to run when the system was shut down. |
| autofs | Auto-mount file systems, CD's, DVD's, etc |
| bluetooth | Provides support for bluetooth devices |
| cpuspeed | Throttles the CPU speed dynamically |
| cups | Printing |
| firstboot | Configures various things on first boot |
| gpm | Mouse support for X windows |
| hidd | Bluetooth HID server |
| isdn | For ISDN connections |
| netfs | Mount/Unmount network file systems |
| nfslock | Network file sharing |
| pcscd | Support for smart cards and smart card readers |
| portmap | Used by the network file service |
| rpcgssd | Used by the network file service |
| rpcidmapd | Used by the network file service |
| sendmail | Mail transport |
| yum-updatesd | Provides notification of updates |
Disable the rest of the services by issuing the command:
$chkconfig --level 0123456 [Service Name] off
For example:
$chkconfig --level 0123456 [anacron] off
[edit] Misc Setup
[edit] Timezone Change
Now is a good time to change the timezone of your Linode. This is an optional step but it can help when you are reviewing log files later.
A timezone change is done by linking the appropriate file with /etc/localtime. To find the appropriate file simply browse the /usr/share/zoneinfo directory. The following will configure your Linode to use the PST timezone.
$rm /etc/localtime $ln -s /usr/share/zoneinfo/US/Pacific /etc/localtime
To ensure that your changes were made correctly, issue the following command:
$date
[edit] Hostname Change
Now is also the time to make another quick and easy change. Modify your Linode's hostname with the hostname command.
$hostname [New Hostname]
Make the new hostname permanent by modifying HOSTNAME in /etc/sysconfig/network.
[edit] Software Installation
Your Linode should be happily humming along now. You have updated and secured it from outside threats. In the following sections software will be added to make it useful.
[edit] MySQL
MySQL is a very popular open source database system. In this tutorial it will be hooked into Postfix and PHP. It will house the email account data for all of the domains hosted by this Linode. Install MySQL using yum.
$yum install mysql-server
During the install of mysql an account called mysql is created. You can confirm this by running cat on the /etc/passwd file. In that file you will find something similar to the following.
mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/bash
Since no user will actually log in with the mysql account the shell login can be disabled.
$usermod -s /sbin/nologin mysql
Now configure mysql to start on boot and then start it manually with the following.
$chkconfig --level 3 mysqld on $service mysqld start
When mysql starts you may be greeted with the following:
Initializing MySQL database: Installing MySQL system tables...
OK
Filling help tables...
OK
To start mysqld at boot time you have to copy
support-files/mysql.server to the right place for your system
PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER !
To do so, start the server, then issue the following commands:
/usr/bin/mysqladmin -u root password 'new-password'
/usr/bin/mysqladmin -u root -h [Your Linode Hostname] password 'new-password'
See the manual for more instructions.
You can start the MySQL daemon with:
cd /usr ; /usr/bin/mysqld_safe &
You can test the MySQL daemon with mysql-test-run.pl
cd mysql-test ; perl mysql-test-run.pl
Please report any problems with the /usr/bin/mysqlbug script!
The latest information about MySQL is available on the web at
http://www.mysql.com
Support MySQL by buying support/licenses at http://shop.mysql.com
[ OK ]
Starting MySQL: [ OK ]
Do what it says and issue the first command. Doing so will give a new password for the root MySQL user. The other command that they have listed will fail because of the iptable rules that were setup eariler.
$mysqladmin -u root password '[New Password]'
[edit] Low Memory Optimization
The following configuration changes will help conserve memory on lower end Linodes.
Please note that "skip-innodb" will disable the InnoDB storage engine. Below you will be installing Postfix Admin which uses InnoDB for the vacation tables. The installation may fail with InnoDB disabled. Simply enable InnoDB do the installation and then disable it again.
FILE: /etc/my.cnf
[mysqld] datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock user=mysql # Default to using old password format for compatibility with mysql 3.x # clients (those using the mysqlclient10 compatibility package). old_passwords=1 # Low memory optimizations skip-bdb skip-innodb skip-networking server-id = 1 key_buffer = 256K max_allowed_packet=1M thread_stack = 64K table_cache = 4 sort_buffer_size = 64K read_buffer_size = 256K read_rnd_buffer_size = 256K net_buffer_length = 2K thread_stack = 64K query_cache_limit=256K query_cache_size = 2M [mysqld_safe] log-error=/var/log/mysqld.log pid-file=/var/run/mysqld/mysqld.pid
[edit] Lighttpd
The server of choice for this tutorial is LightTPD. It uses less memory and is generally faster than Apache. If you would like to install Apache instead please see the guide at the end of this tutorial.
[edit] HTTPS: Preliminary work
For security reasons the webmail and administration access points should be accessed through an encrypted connection. To do this you will need a certificate that is either self-signed or signed by a certificate authority (CA).
This tutorial will use a self-signed certificate. The down side of a self-signed certificate is that your users will be prompted with a message asking whether or not to trust your certificate. For any sort of professional business you will want to buy a certificate signed by a CA.
For more reading about certificates see:
- Creating Certificate Authorities and self-signed SSL certificates
- How to Create A Self Signed Certificate
- Be your own Certificate Authority (CA)
First create a directory to hold your certificates:
$mkdir /etc/pki/[YourDomain]CA $chmod 600 /etc/pki/[YourDomain]CA $cd /etc/pki/[YourDomain]CA
Now create a private CA key:
$openssl genrsa -des3 -out ca.key 4096
Give a very strong password when asked:
Enter pass phrase for ca.key: Verifying - Enter pass phrase for ca.key:
Now create a CA certificate using your new CA key:
$openssl req -new -x509 -days 365 -key ca.key -out ca.crt
Fill in the questions you are asked:
Country Name (2 letter code) [GB]: State or Province Name (full name) [Berkshire]: Locality Name (eg, city) [Newbury]: Organization Name (eg, company) [My Company Ltd]: Organizational Unit Name (eg, section) []:Certificate Authority Common Name (eg, your name or your server's hostname) []:[Linode host name] CA Email Address []:
Now create a private server key:
$openssl genrsa -des3 -out server.key 4096
Give a very strong password when asked:
Enter pass phrase for server.key: Verifying - Enter pass phrase for server.key:
Now create a server certificate using your new server key:
$openssl req -new -key server.key -out server.csr
Fill in the questions you are asked:
Country Name (2 letter code) [GB]: State or Province Name (full name) [Berkshire]: Locality Name (eg, city) [Newbury]: Organization Name (eg, company) [My Company Ltd]: Organizational Unit Name (eg, section) []:Host Common Name (eg, your name or your server's hostname) []:*.[Your domain name] Email Address []:
Now sign your server certificate:
$openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt
Finally make an insecure server.key for Apache:
$openssl rsa -in server.key -out server.key.insecure $mv server.key server.key.secure $mv server.key.insecure server.key $chmod 600 server.key server.key.secure $cat server.key server.crt > server.pem
Please note that only one certificate can be associated with one IP address. If your clients need a separate certificate for their domain they will need a separate IP address. See the FAQ: Purchase additional IP addresses.
[edit] Installation
Get the Lighttpd archive file from the Lighttpd download page at http://www.lighttpd.net/download.
The easiest way to get Lighttpd is with the wget command. This command will download whatever URL you give it to your Linode. Download the archive file with the following.
$wget [URL]
Extract the archive file using the tar command. As of this writing the latest version of Lighttpd is 1.4.20 and the archive file is named lighttpd-1.4.20.tar.gz. Extract the files from the archive with the following.
$tar -zxvf lighttpd-1.4.20.tar.gz $cd [unpacked archive]
To install things from source gcc must be installed first. The header files for mysql and the Berkeley DB files will be needed later so get them now.
$yum install gcc pcre-devel.x86_64 bzip2-devel.x86_64 mysql-devel.x86_64 db4-devel
Once gcc is installed the Lighttpd source code can be compiled and installed.
To compile and install Lighttpd issue the following
$./configure --prefix=/usr --with-openssl --with-openssl-libs=/usr/bin --with-mysql $make $make install
Now add a user that will own the lighttpd process with the following.
$groupadd -r lighttpd $useradd -r -g lighttpd -s /sbin/nologin lighttpd
Finally copy over the init script that comes with Lighttpd.
$sed -e 's/FOO/lighttpd/g' doc/rc.lighttpd.redhat > /etc/init.d/lighttpd $chmod 755 /etc/init.d/lighttpd $cp -p doc/sysconfig.lighttpd /etc/sysconfig/lighttpd $install -Dp ./doc/lighttpd.conf /etc/lighttpd/lighttpd.conf
[edit] Setup Your first domain
Now is the time to setup your first domain. Add a new domain user with the addDomain.sh script. Also, add the domain to the /etc/lighttpd/lighttpd_vhosts.conf file described above. Now is also a good time to test your webserver configuration.
You should add the main domain that you will be using for this Linode. Also, at this time also add two subdomains that will be used, one for webmail and the other for Postfix administration.
To start you will need to create two directories for these subdomains. Create a mailadmin and webmail folder under your main usernames web folder.
$mkdir /home/[Your Domain Username]/public_html/mailadmin $mkdir /home/[Your Domain Username]/public_html/webmail
The following domains will be added:
- mailadmin.[Your Domain].com
- webmail.[Your Domain].com
- [Your Domain].com
CREATE FILE: /etc/lighttpd/lighttpd_vhosts.conf
$SERVER["socket"] == "[Your Linode IP]:80" {
$HTTP["host"] == "mailadmin.[Your Domain].com" {
server.document-root = "/home/[Your Domain Username]/public_html/mailadmin/"
accesslog.filename = "/home/[Your Domain Username]/logs/mailadmin_access.log"
}
else $HTTP["host"] == "webmail.[Your Domain].com" {
server.document-root = "/home/[Your Domain Username]/public_html/webmail/"
accesslog.filename = "/home/[Your Domain Username]/logs/webmail_access.log"
}
else $HTTP["host"] =~ "(^|\.)[Your Domain].com$" {
server.document-root = "/home/[Your Domain Username]/public_html/"
accesslog.filename = "/home/[Your Domain Username]/logs/access.log"
}
}
$SERVER["socket"] == "[Your Linode IP]:443" {
ssl.engine = "enable"
ssl.pemfile = "/etc/pki/[Your Domain Username]CA/server.pem"
ssl.ca-file = "/etc/pki/[Your Domain Username]CA/ca.crt"
$HTTP["host"] == "mailadmin.[Your Domain].com" {
server.document-root = "/home/[Your Domain Username]/public_html/mailadmin/"
accesslog.filename = "/home/[Your Domain Username]/logs/mailadmin_access.log"
}
else $HTTP["host"] == "webmail.[Your Domain].com" {
server.document-root = "/home/[Your Domain Username]/public_html/webmail/"
accesslog.filename = "/home/[Your Domain Username]/logs/webmail_access.log"
}
else $HTTP["host"] =~ "(^|\.)[Your Domain].com$" {
server.document-root = "/home/[Your Domain Username]/public_html/"
accesslog.filename = "/home/[Your Domain Username]/logs/access.log"
}
}
[edit] Config Changes
Now edit the /etc/lighttpd/lighttpd.conf file and make the following changes.
FILE: /etc/lighttpd/lighttpd.conf
server.modules = ( "mod_rewrite", "mod_access", "mod_fastcgi", "mod_userdir", "mod_accesslog" ) server.document-root = "/home/[Your Domain Username]/public_html" server.port = 80 server.bind = "[Your linode IP address]" server.username = "lighttpd" server.groupname = "lighttpd" userdir.path = "public_html" include "/etc/lighttpd/lighttpd_vhost.conf"
Now Create the log directory for Lighttpd.
$mkdir /var/log/lighttpd $chown -R lighttpd.lighttpd /var/log/lighttpd
You should startup Lighttpd and make sure everything is working correctly. In the next section PHP will be installed and linked up with Lighttpd
$service lighttpd start
[edit] PHP
PHP will be installed from source to make it easier to change the settings in the future. Also, doing so ensures that fastcgi is enabled which is used by Lighttpd.
Download the PHP source code http://www.php.net/downloads.php. You can use the same wget command used earlier.
$wget [PHP Source Archive] $tar -zxvf [PHP Source Archive] $cd [Extracted Directory]
Before PHP can be compiled some extra libraries have to be installed. Use yum to install these libraries.
$yum install libxml2-devel.x86_64 libpng-devel.x86_64 libjpeg-devel.x86_64 curl-devel.x86_64 libmcrypt-devel.x86_64 libc-client-devel.x86_64 libtool-ltdl-devel.x86_64
Compile PHP with the following.
$./configure --prefix=/usr --enable-fastcgi --enable-force-cgi-redirect --enable-bcmath --enable-calendar --enable-mbstring --enable-zip --with-openssl --with-gd --with-mysql --with-bz2 --with-curl --with-mcrypt --with-libdir=lib64 --with-jpeg-dir=/usr/lib64 --with-ttf --with-mysqli --with-imap --with-imap-ssl --with-kerberos --with-pear --with-zlib $make $make test
It is normal to see a few tests that fail during make test. Just check over them and make sure nothing critically fails. Should the tests fail you will be asked if you would like to send a report. Answer "Y" and enter your email address. This will inform the makers of PHP about the error.
Baring no critical errors install PHP with the following.
$make install
Now, copy over the recommended php.ini file with the following.
$cp php.ini-recommended /usr/lib/php.ini
[edit] Config Changes
To hook Lighttpd up to PHP the /etc/lighttpd/lighttpd.conf file needs to be modified again.
FILE: /etc/lighttpd/lighttpd.conf
"mod_fastcgi"
fastcgi.server = ( ".php" =>
( "localhost" =>
(
"socket" => "/var/run/lighttpd/php-fastcgi.socket",
"bin-path" => "/usr/bin/php-cgi",
"bin-environment" => (
"PHP_FCGI_CHILDREN" => "16",
"PHP_FCGI_MAX_REQUESTS" => "10000"
),
"idle-timeout" => 20
)
)
)
Please note that if you are on a Linode with lower memory you should use the following to conserve resources. FILE: /etc/lighttpd/lighttpd.conf
"mod_fastcgi"
fastcgi.server = ( ".php" =>
( "localhost" =>
(
"socket" => "/var/run/lighttpd/php-fastcgi.socket",
"bin-path" => "/usr/bin/php-cgi",
"idle-timeout" => 20
)
)
)
With the configuration changes made a spot for the socket that connects Lighttpd and PHP needs to be created. Make the following directories.
$mkdir /var/run/lighttpd $chown lighttpd.lighttpd /var/run/lighttpd $chmod 750 /var/run/lighttpd
PHP will be enabled after you restart Lighttpd.
$service lighttpd restart
[edit] postfix.admin
Creating and configuring email mailboxes is much easier with the help of a PHP utility called Postfix Admin. Postfix Admin can be downloaded from http://postfixadmin.sourceforge.net/.
You should have setup your main domain in the Setup Your first domain section above. You should download the Postfix Admin files to the web folder for your main domain.
$cd /home/[Main domain user]/public_html
Extract the files from the archive with the following.
$tar -zxvf postfixadmin-2.2.1.1.tar.gz
To make life easier down the road rename the extracted folder to something more reasonable.
$mv postfixadmin-2.2.1.1 mailadmin
Postfix Admin requires a MySQL database as well as a MySQL user account. To set both of those up use the mysql client. Log into the client with the mysql command. The password for the root user is the password you set above using the mysqladmin command.
$mysql -u root -p [MySQL root password]
At the mysql command prompt enter the following.
CREATE DATABASE postfixmail; CREATE USER 'postfixmailuser'@'localhost' IDENTIFIED BY '[New Password]'; GRANT ALL PRIVILEGES ON `postfixmail` . * TO 'postfixmailuser'@'localhost';
To leave the mysql command prompt enter:
quit;
With the database setup Postfix Admin can be configured. Edit the configuration file config.inc.php as follows.
$CONF['configured'] = true; $CONF['postfix_admin_url'] = 'https://mailadmin.[Your Domain]'; $CONF['database_user'] = 'postfixmailuser'; $CONF['database_password'] = '[Password assigned to postfixmailuser above]'; $CONF['database_name'] = 'postfixmail'; $CONF['admin_email'] = '[Your admin email address]'; $CONF['user_footer_link'] = "https://mailadmin.[Your Domain].com/main"; $CONF['footer_text'] = 'Return to mailadmin.[Your Domain].com'; $CONF['footer_link'] = 'https://mailadmin.[Your Domain].com';
Next run the setup script by opening the following in your browser: https://mailadmin.[Your Domain]/setup.php
Follow the script instructions and once finish delete the setup.php file.
$rm setup.php
[edit] Postfix Admin Modifications
In order to get the mail delivered to the home folder of the user associated with a given domain some modifications need to me made to Postfix Admin. Some fields need to be added to the database and then the script needs to be modified a little.
Please note that this is a quick and dirty script modification. You will have to set up the domain's username before adding email addresses in Postfix Admin. Also, you will not be able to edit the domain's username once you set it. That is, unless you want to go modifying the database by hand.
First modify the database by logging into the MySQL command prompt and issuing the following commands. Log into the MySQL command prompt:
$mysql -u root -p [MySQL root password]
Modify the Postfix Admin database:
USE postfixmail; ALTER TABLE domain ADD COLUMN uid INT COMMENT 'The unix user id for this domain', ADD COLUMN gid INT COMMENT 'The unix group id for this domain', ADD COLUMN home_dir text; quit;
Now open the following files in a text editor and make the given changes: In the file templates/admin_create-domain.php after this:
<tr>
<td><?php print $PALANG['pAdminCreate_domain_domain'] . ":"; ?></td>
<td><input class="flat" type="text" name="fDomain" value="<?php print $tDomain; ?>" /></td>
<td><?php print $pAdminCreate_domain_domain_text; ?></td>
</tr>
Add this:
<?php // --- BEGIN: GID/UID Modification --- ?>
<tr>
<td>Domain Username:</td>
<td><input class="flat" type="text" name="fDomainUser" value="<?php print $tDomainUser; ?>" /></td>
<td> </td>
</tr>
<?php // --- END: GID/UID Modification --- ?>
In the file variables.inc.php after this:
$tUsername = ""; $tTransport = "";
Add this:
// BEGIN: GID/UID Modification $fDomainUser = ""; $tDomainUser = ""; // END: GID/UID Modification
In the file create-domain.php: Change this:
'fBackupmx' => '0');
To this:
// BEGIN: GID/UID Modification
'fBackupmx' => '0', 'fDomainUser' => '');
// END: GID/UID Modification
After this:
if (empty ($fDomain) or domain_exist ($fDomain) or !check_domain ($fDomain))
{
$error = 1;
$tDomain = escape_string ($_POST['fDomain']);
Add this:
// BEGIN: GID/UID Modification
$tDomainUser = escape_string ($_POST['fDomainUser']);
// END: GID/UID Modification
Change this:
$sql_query = "INSERT INTO $table_domain (domain,description,aliases,mailboxes,maxquota,transport,backupmx,created,modified) VALUES ('$fDomain','$fDescription',$fAliases,$fMailboxes,$fMaxquota,'$fTransport',$sqlBackupmx,NOW(),NOW())";
To this:
// BEGIN: GID/UID Modification
$gid = GetGID($fDomainUser);
$uid = GetUID($fDomainUser);
$homeDir = "/home/{$fDomainUser}";
$sql_query = "INSERT INTO $table_domain (domain,description,aliases,mailboxes,maxquota,transport,backupmx,created,modified,gid,uid,home_dir) VALUES ('$fDomain','$fDescription',$fAliases,$fMailboxes,$fMaxquota,'$fTransport',$sqlBackupmx,NOW(),NOW(),$gid,$uid,'$homeDir')";
// END: GID/UID Modification
After this:
$tMessage = $PALANG['pAdminCreate_domain_result_success'] . "<br />($fDomain)</br />";
}
}
}
Add this:
// BEGIN: GID/UID Modification
// Gets the GID for the given username
function GetGID($username)
{
return shell_exec('grep \'' . escapeshellarg($username) . '\' /etc/passwd | cut -d : -f 3');
}
function GetUID($username)
{
return shell_exec('grep \'' . escapeshellarg($username) . '\' /etc/passwd | cut -d : -f 4');
}
// END: GID/UID Modification
[edit] Postfix
For this tutorial Postfix must be configured with mysql support. Since the version in the yum repository is not built with this support Postfix must be installed from source.
Get the source code using wget as before. The correct URL can be found through the Postfix download page at http://www.postfix.org/download.html.
$wget [URL]
You should have downloaded the Postfix source code as a tar.gz file. As of this writing the latest stable source code file is named postfix-2.6.2.tar.gz. Before the source can be compiled it must be extracted from the archive.
$tar -zxvf postfix-2.6.5.tar.gz $cd postfix-2.6.5
The contents of the archive will be extracted to a postfix-2.6.5 folder in the same folder of the archive. Once extracted compile and install Postfix with the following. Be prepared to wait a little while for Postfix to compile.
$groupadd -r postfix $useradd -r -g postfix -s /sbin/nologin postfix $groupadd -r postdrop $make -f Makefile.init makefiles 'CCARGS=-DHAS_MYSQL -I/usr/include/mysql -DUSE_SASL_AUTH -DDEF_SERVER_SASL_TYPE=\"dovecot\"' 'AUXLIBS=-L/usr/lib64/mysql -lmysqlclient -lz -lm' $make $make install
If you are having problems with -lmysqlclient then there's probably a wrong path for AUXLIBS. If you want to find your -lmysqlclient path you can do it like this:
find / -name "-lmysqlclient*"
After much scrolling you will be asked several installation questions. Just accept the default values. For reference the default values are as follows:
install_root: [/] tempdir: [Your extracted directory] config_directory: [/etc/postfix] command_directory: [/usr/sbin] daemon_directory: [/usr/libexec/postfix] data_directory: [/var/lib/postfix] html_directory: [no] mail_owner: [postfix] mailq_path: [/usr/bin/mailq] manpage_directory: [/usr/local/man] newaliases_path: [/usr/bin/newaliases] queue_directory: [/var/spool/postfix] readme_directory: [no] sendmail_path: [/usr/sbin/sendmail] setgid_group: [postdrop]
[edit] Config Changes
Once Postfix is installed the configuration begins. The main configuration file for Postfix is called /etc/postfix/main.cf. Make the following changes:
myhostname = [mail.yourdomain.com] mydomain = [yourdomain.com] myorigin = $myhostname inet_interfaces = all mydestination = localhost local_recipient_maps = $alias_maps $virtual_mailbox_maps unix:passwd.byname mynetworks_style = host alias_maps = hash:/etc/aliases alias_database = hash:/etc/aliases virtual_mailbox_base = / virtual_alias_maps = proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_maps.cf virtual_mailbox_domains = proxy:mysql:/etc/postfix/sql/mysql_virtual_domains_maps.cf virtual_mailbox_maps = proxy:mysql:/etc/postfix/sql/mysql_virtual_mailbox_maps.cf
At the bottom of the main.cf configuration above you will notice the virtual_alias_maps, virtual_mailbox_domains, and virtual_mailbox_maps settings. These settings point to files which need to be created. These files tell Postfix how to get email info out of the database.
Create an sql folder in /etc/postfix:
$mkdir /etc/postfix/sql
Now create the following three files:
FILE: /etc/postfix/sql/mysql_virtual_alias_maps.cf
user = postfixmailuser password = [Password assigned to postfixmailuser above] hosts = localhost dbname = postfixmail query = SELECT goto FROM alias WHERE address='%s' AND active = '1'
FILE: /etc/postfix/sql/mysql_virtual_domains_maps.cf
user = postfixmailuser password = [Password assigned to postfixmailuser above] hosts = localhost dbname = postfixmail query = SELECT domain FROM domain WHERE domain='%u'
FILE: /etc/postfix/sql/mysql_virtual_mailbox_maps.cf
user = postfixmailuser password = [Password assigned to postfixmailuser above] hosts = localhost dbname = postfixmail query = SELECT 1 FROM mailbox WHERE username='%s' AND active = '1'
Since these three files hold the database password a little modification needs to be done to keep people out.
$chown -R postfix /etc/postfix/sql $chmod 700 /etc/postfix/sql
[edit] Starting Postfix
Copy the following startup script to the /etc/init.d folder. This startup script will allow you to start, reload, and stop the postfix mail manager.
FILE: /etc/init.d/postfix
#!/bin/bash
#
# postfix Postfix Mail Transfer Agent
#
# chkconfig: 2345 80 30
# description: Postfix is a Mail Transport Agent, which is the program \
# that moves mail from one machine to another.
# processname: master
# pidfile: /var/spool/postfix/pid/master.pid
# config: /etc/postfix/main.cf
# config: /etc/postfix/master.cf
#
# Based on startup script from Simon J Mudd <sjmudd@pobox.com>
# 25/02/99: Mostly s/sendmail/postfix/g by John A. Martin <jam@jamux.com>
# 23/11/00: Changes & suggestions by Ajay Ramaswamy <ajayr@bigfoot.com>
# 20/01/01: Changes to fall in line with RedHat 7.0 style
# 23/02/01: Fix a few untidy problems with help from Daniel Roesen.
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 0
[ -x /usr/sbin/postfix ] || exit 0
[ -d /etc/postfix ] || exit 0
[ -d /var/spool/postfix ] || exit 0
RETVAL=0
prog="postfix"
start() {
# Start daemons.
echo -n $"Starting postfix: "
/usr/bin/newaliases >/dev/null 2>&1
/usr/sbin/postfix start 2>/dev/null 1>&2 && success || failure $"$prog start"
RETVAL=$?
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/postfix
echo
return $RETVAL
}
stop() {
# Stop daemons.
echo -n $"Shutting down postfix: "
/usr/sbin/postfix stop 2>/dev/null 1>&2 && success || failure $"$prog stop"
RETVAL=$?
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/postfix
echo
return $RETVAL
}
reload() {
echo -n $"Reloading postfix: "
/usr/sbin/postfix reload 2>/dev/null 1>&2 && success || failure $"$prog reload"
RETVAL=$?
echo
return $RETVAL
}
abort() {
/usr/sbin/postfix abort 2>/dev/null 1>&2 && success || failure $"$prog abort"
return $?
}
flush() {
/usr/sbin/postfix flush 2>/dev/null 1>&2 && success || failure $"$prog flush"
return $?
}
check() {
/usr/sbin/postfix check 2>/dev/null 1>&2 && success || failure $"$prog check"
return $?
}
restart() {
stop
start
}
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
reload)
reload
;;
abort)
abort
;;
flush)
flush
;;
check)
check
;;
status)
status master
;;
condrestart)
[ -f /var/lock/subsys/postfix ] && restart || :
;;
*)
echo $"Usage: $0 {start|stop|restart|reload|abort|flush|check|status|condrestart}"
exit 1
esac
exit $?
Once created, set the permissions on the script so that it is executable
$chmod 755 /etc/init.d/postfix
Once the startup script is in place the service command can be used to control it. Issue the following to start Postfix. Note that Postfix will output any errors it has in the file /var/log/maillog.
$service postfix start
[edit] Dovecot
Dovecot will handle the local delivery of all email that has made it into the Linode. Incoming email will be accepted by Postfix and the handed off to Dovecot. Dovecot will then deliver the email to the user.
To make use of the CMUSieve Dovecot plugin, Dovecot must be installed from source. Download the latest version from http://www.dovecot.org/download.html. As of this writing the latest version is 1.1.16.
$wget [Dovecot URL]
Before installing two new users will be added. One to run Dovecot and another to keep the Postfix to Dovecot connection secure.
$groupadd -r dovecot $useradd -r -g dovecot -s /sbin/nologin dovecot $groupadd -r vmail $useradd -r -g vmail -s /sbin/nologin vmail
Now unpack and install Dovecot:
$tar -zxvf [The downloaded Dovecot archive] $cd [Unpacked directory] $./configure --prefix=/usr --with-mysql $make $make install
Now make deliver accessable to the vmail user with the following:
$chown 0.0 /usr/libexec/dovecot/deliver $chmod 755 /usr/libexec/dovecot/deliver $chmod 700 /usr/lib/dovecot/ $chown vmail /usr/lib/dovecot/ $cp -p /usr/libexec/dovecot/deliver /usr/lib/dovecot $chmod u+s /usr/lib/dovecot/deliver
[edit] Config Changes
After the install the Dovecot configuration file must be created and set up. For the initial creation simply copy over the example configuration file and then open it for editing.
$cp /usr/etc/dovecot-example.conf /usr/etc/dovecot.conf
FILE: /usr/etc/dovecot.conf
protocols = imap imaps pop3 pop3s
ssl_cert_file = /etc/pki/[Your Domain]CA/server.crt
ssl_key_file = /etc/pki/[Your Domain]CA/server.key
protocol lda {
postmaster_address = postmaster@[Your domain]
}
auth default {
mechanisms = plain login cram-md5 ntlm
# passdb pam {
# }
passdb sql {
args = /etc/dovecot/dovecot_sql_passdb.conf
}
#userdb passwd {
#}
userdb sql {
args = /etc/dovecot/dovecot_sql_userdb.conf
}
}
socket listen {
master {
# Master socket provides access to userdb information. It's typically
# used to give Dovecot's local delivery agent access to userdb so it
# can find mailbox locations.
path = /usr/var/run/dovecot/auth-master
mode = 0600
# Default user/group is the one who started dovecot-auth (root)
user = vmail
#group =
}
client {
# The client socket is generally safe to export to everyone. Typical use
# is to export it to your SMTP server so it can do SMTP AUTH lookups
# using it.
path = /var/spool/postfix/private/auth
mode = 0660
user = postfix
group = postfix
}
}
Like the Postfix Configuration section above the next step is to create some files which tell Dovecot how to access the database. Create the following directory.
$mkdir /etc/dovecot
Now create the following files:
FILE: /etc/dovecot/dovecot_sql_passdb.conf
driver = mysql connect = host=localhost dbname=postfixmail user=postfixmailuser password=[Password assigned to postfixmailuser above] default_pass_scheme = MD5-CRYPT password_query = SELECT password FROM mailbox WHERE username = '%u'
FILE: /etc/dovecot/dovecot_sql_userdb.conf
driver = mysql
connect = host=localhost dbname=postfixmail user=postfixmailuser password=[Password assigned to postfixmailuser above]
user_query = SELECT CONCAT('maildir:', domain.home_dir, '/mail/', mailbox.maildir, 'mail') as mail, domain.uid, domain.gid, CONCAT('quota=maildir:storage=', mailbox.quota) AS quota, CONCAT(domain.home_dir, '/mail/', mailbox.maildir) as home FROM domain JOIN mailbox ON domain.domain = mailbox.domain WHERE mailbox.username = '%u';
[edit] Postfix Reconfiguration
Now Postfix must be told about the new Dovecot installation. This configuration section will get Postfix talking to Dovecot.
FILE: /etc/postfix/master.cf
# Added for the dovecot server
dovecot unix - n n - - pipe
flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -d ${recipient}
FILE: /etc/postfix/main.cf
virtual_transport = dovecot dovecot_destination_recipient_limit = 1 smtpd_recipient_limit = 500 smtpd_sasl_type=dovecot smtpd_sasl_path=private/auth smtpd_sasl_auth_enable=yes smtpd_recipient_restrictions=permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
[edit] Starting Dovecot
With Dovecot finally setup it can now be started. Since some changes were made to the Postfix configuration files that will need to be restarted. Also, note that Dovecot will output information to the file /var/log/maillog.
Create a startup script for Dovecot containing the following. [8]
FILE: /etc/init.d/dovecot
#!/bin/sh
# License is public domain.
DAEMON=/usr/sbin/dovecot
test -x $DAEMON || exit 1
set -e
base_dir=`$DAEMON -a|grep '^base_dir: '|sed 's/^base_dir: //'`
pidfile=$base_dir/master.pid
if test -f $pidfile; then
running=yes
else
running=no
fi
case "$1" in
start)
echo -n "Starting Dovecot"
$DAEMON
echo "."
;;
stop)
if test $running = yes; then
echo "Stopping Dovecot"
kill `cat $pidfile`
echo "."
else
echo "Dovecot is already stopped."
fi
;;
reload)
if test $running = yes; then
echo -n "Reloading Dovecot configuration"
kill -HUP `cat $pidfile`
echo "."
else
echo "Dovecot isn't running."
fi
;;
restart|force-reload)
echo -n "Restarting Dovecot"
if test $running = yes; then
kill `cat $pidfile`
sleep 1
fi
$DAEMON
echo "."
;;
*)
echo "Usage: /etc/init.d/dovecot {start|stop|reload|restart|force-reload}" >&2
exit 1
;;
esac
exit 0
With the startup script created give it privileges to execute with the following.
$chmod 755 /etc/init.d/dovecot
[edit] Dovecot CMUSieve
Installing the Sieve plugin for Dovecot will allow you or your users to redirect their email using scripts. In this tutorial Sieve will be used to move email marked as spam or viruses into the users Trash folder.
To start download the Sieve plug in for your Dovecot installation. The plugin can be found at the Dovecot download site: http://www.dovecot.org/download.html. At the writing of this tutorial the plugin version is 1.1.6.
$wget [Sieve plugin] $tar -zxvf [The Sieve plugin you downloaded] $cd [The extracted directory] $./configure --prefix=/usr --with-dovecot=[Path to the downloaded and unpacked Dovecot archive. For example ../dovecot-1.1.11] $make $make install
Now create a spot for the global sieve script:
$mkdir /usr/etc/dovecot $chown vmail.vmail /usr/etc/dovecot $chmod 777 /usr/etc/dovecot
Finally create the global sieve script:
Create FILE: /usr/etc/dovecot/default.sieve
require ["fileinto", "copy"];
if header :contains "X-Spam-Status" "YES" {
fileinto "spam";
}
else {
fileinto :copy "ham";
}
The above script will cause any spam messages to be put into a separate "spam" folder. Also, any messages that get through to the inbox will be copied to the "ham" folder. Later in the tutorial a script will be created which will update the Bayes database based upon these two directories.
[edit] Config Changes
Edit the main Dovecot configuration file to enable the freshly installed sieve plugin.
FILE: /usr/etc/dovecot.conf
protocol lda {
mail_plugins = cmusieve
mail_plugin_dir = /usr/lib/dovecot/lda
sieve_global_path = /usr/etc/dovecot/default.sieve
}
[edit] Testing Email
Congratulations, you should now have a Linode that serves webpages and email! Before continuing you should test your email setup.
Logon to Postfix Admin and add a domain and then add an email address to that domain. You can then fire up you favorite email client and test away. Take a look at the /var/log/maillog to see if there are any problems while you send and receive test email.
You can also hand test the email service by telnetting into your Linode at port 25. Once there you should be greeted with the following:
220 <Your domain> ESMTP Postfix
Respond with:
$ehlo [Your domain]
The server should tell you:
250-<Your domain> 250-PIPELINING 250-SIZE 10240000 250-VRFY 250-ETRN 250-AUTH PLAIN LOGIN 250-ENHANCEDSTATUSCODES 250-8BITMIME 250 DSN
Tell the server who you are:
$mail from:<[Your email address]>
It should say ok:
250 2.1.0 Ok
Tell the server who you want to email:
$rcpt to:<[Your test email address]>
Again, it should say ok:
250 2.1.5 Ok
Tell it you are ready to send the message body:
$data
It will tell you how to quit:
354 End data with <CR><LF>.<CR><LF>
Send it the message:
$Hello World! $.
It should tell you that the message was recieved:
250 2.0.0 Ok: queued as ECCDD66022
Finally, exit out of telnet:
$quit
[edit] Open Relay Test
Once everything is working correctly, make sure you do not have an open relay. This ensures that your Linode will not be used by spammers. See Mail relay testing.
[edit] Squirrelmail
Squirrelmail will provide webmail access for the Linode setup in this tutorial.
Download Squirrelmail (http://www.squirrelmail.org/download.php) to your main domains web directory as you did in the [#postfix.admin|postfix.admin] section. Then untar it and move to the new directory.
$wget [Squirrelmail archive] $tar -zxvf [Squirrelmail archive] $cd [Unpacked archive]
Also create some directories that Squirrelmail will use for temporary storage.
$mkdir -p /var/local/squirrelmail/attach $mkdir /var/local/squirrelmail/data $chown -R lighttpd.lighttpd /var/local/squirrelmail/ $chmod -R 730 /var/local/squirrelmail/
Squirrelmail requires the PHP PEAR DB module so install that as well.
$pear install DB
Installation is pretty straight forward and starts with database setup.
[edit] Create the Database
Logon to the mysql client and create a new database for Squirrelmail to use.
$mysql -u root -p [MySQL root password]
At the mysql command prompt enter the following:
CREATE DATABASE squirrelmail;
GRANT select,insert,update,delete ON squirrelmail.*
TO squirreluser@localhost IDENTIFIED BY '[New squirreluser passsword]';
USE squirrelmail;
CREATE TABLE address (
owner varchar(128) DEFAULT '' NOT NULL,
nickname varchar(16) DEFAULT '' NOT NULL,
firstname varchar(128) DEFAULT '' NOT NULL,
lastname varchar(128) DEFAULT '' NOT NULL,
email varchar(128) DEFAULT '' NOT NULL,
label varchar(255),
PRIMARY KEY (owner,nickname),
KEY firstname (firstname,lastname)
);
CREATE TABLE userprefs (
user varchar(128) DEFAULT '' NOT NULL,
prefkey varchar(64) DEFAULT '' NOT NULL,
prefval BLOB DEFAULT '' NOT NULL,
PRIMARY KEY (user,prefkey)
);
quit;
[edit] Config Changes
Squirrelmail can be configured with a perl script that is supplied. To run the perl script issue the following command.
$perl config/conf.pl
You should be greeted with a SquirrelMail Configuration screen. Make the following changes:
- Main Menu item: 2. Server Settings
- 1. Domain: [Your domain name]
- Main Menu item: 9. Database
- 1. DSN for Address Book: mysql://squirreluser:[squirreluser passsword from above]@localhost/squirrelmail
- 3. DSN for Preferences: mysql://squirreluser:[squirreluser passsword from above]@localhost/squirrelmail
[edit] MailScanner
The final piece of software to install and configure is MailScanner. This software will send all email to SpamAssassin and ClamAV for scanning. Once scanning is complete it will send the email back to Postfix for delivery.
To begin download the MailScanner package for "RedHat, Fedora and Mandrake Linux" from http://www.mailscanner.info/downloads.html. This archive contains a binary distribution that can be installed in CentOS.
$wget [MailScanner archive]
Before MailScanner can be installed the package rpm-build must be installed. Fortunately, this package exists in the yum repository.
$yum install rpm-build
Now unpack the MailScanner package that you downloaded and move to the new directory.
$tar -zxvf [MailScanner archive] $cd [Unpacked directory]
Now you can begin installing MailScanner. Installation is not done with the normal ./configure, make, make install routine. Instead MailScanner comes with an install script that does it all for you. Issue the following command.
$./install.sh
[edit] SpamAssassin and ClamAV
With MailScanner setup both SpamAssassin and ClamAV need to be installed. This is easily done with a package available from the MailScanner download site.
From http://www.mailscanner.info/downloads.html download the ClamAV and SpamAssassin easy installation package. Then untar it and move to the unpacked directory.
$wget [Easy installation package] $tar -zxvf [Easy installation package] $cd [Unpacked directory] $./install.sh
[edit] Config Changes
The MailScanner configuration file is installed at /etc/MailScanner/MailScanner.conf. Make the following changes to the configuration file.
You will notice a line for "Max Children = 1" in the configuration below. Use this if you have a Linode 360 plan. Increase this if you have a bigger plan just remember that each child uses roughly 20 MB of ram.
The following setup will flag spam and viruses and will deliver them. It will not quarantine or automatically delete them. Later on in this tutorial CMUSeive will be used to put these flagged messages into a 'spam' folder for the user.
FILE: /etc/MailScanner/MailScanner.conf
%org-name% = [Short name of you organization] %org-long-name% = [Full name of your organization] %web-site% = [Your domain name] Max Children = 1 Run As User = postfix Run As Group = postfix Incoming Queue Dir = /var/spool/postfix/hold Outgoing Queue Dir = /var/spool/postfix/incoming MTA = postfix Maximum Attachments Per Message = 100 Still Deliver Silent Viruses = yes Web Bug Replacement = http://[your domain]/images/1x1spacer.gif Quarantine Infections = no Sign Clean Messages = no Notify Senders = no Notify Senders Of Blocked Filenames Or Filetypes = no Notify Senders Of Other Blocked Content = no Phishing Modify Subject = yes Use Watermarking = yes Treat Invalid Watermarks With No Sender as Spam = spam Watermark Secret = %org-name%-Secret-[Random junk] High Scoring Spam Actions = deliver header "X-Spam-Status: Yes" SpamAssassin User State Dir = /var/spool/MailScanner/spamassassin
Remember to upload a '1x1spacer.gif' to your domain for the 'Web Bug Replacement' setting.
Another tweak that you may find useful is to increase the "Queue Scan Interval". This is the length of time that MailScanner will wait before checking for new messages. Tweak with this value if you have IO issues.
Queue Scan Interval = 20
[edit] Postfix Config Changes
Since MailScanner will be running as the postfix user the directories it uses need to be opened up to that user. The following commands will open up those directories.
$mkdir /var/spool/MailScanner/spamassassin $chown -R postfix.postfix /var/spool/MailScanner/incoming $chmod 730 /var/spool/MailScanner/
Postfix needs to put all incoming mail into it's hold queue so that MailScanner can pick it up. Make the following change to /etc/postfix/main.cf
FILE: /etc/postfix/main.cf
header_checks = regexp:/etc/postfix/header_checks
Also open up the /etc/postfix/header_checks file and add the following line.
FILE: /etc/postfix/header_checks
/^Received:/ HOLD
[edit] SpamAssassin Config Changes
SpamAssassin uses a Bayesian (Bayes) classifier to identify spam messages. In this tutorial the data for Bayes will be stored in a MySQL database.
The SQL that will be used to create the database tables is in the SpamAssassin source archive. Unfortunately, the version downloaded above does not include this SQL script. To get the SQL download the SpamAssassin source archive from http://spamassassin.apache.org/downloads.cgi.
$tar -zxvf [Source archive] $cd [Source archive]
Now logon to the mysql client and create a new database user for SpamAssassin.
$mysql -u root -p
At the mysql command prompt enter the following:
CREATE DATABASE sa_bayes; GRANT ALL ON sa_bayes.* TO sa_user@localhost IDENTIFIED BY '[Database password for new sa_user]'; flush privileges; quit;
Use the sql/bayes_mysql.sql file from the source downloaded above to create and populate a database for the Bayes data.
$mysql -u sa_user -p sa_bayes < sql/bayes_mysql.sql
Now tell SpamAssassin about the new database by editing the /etc/Mailscanner/spam.assassin.prefs.conf file.
FILE: /etc/Mailscanner/spam.assassin.prefs.conf
#bayes_path /etc/MailScanner/bayes/bayes #bayes_file_mode 0660 bayes_store_module Mail::SpamAssassin::BayesStore::SQL bayes_sql_dsn DBI:mysql:sa_bayes:localhost bayes_sql_username sa_user bayes_sql_password [Database password for sa_user] bayes_sql_override_username root
[edit] ClamAV Config Changes
The only thing needed for ClamAV is to remove the shell from the clamav user added by the install.
$usermod -s /sbin/nologin clamav
[edit] Restart
Now startup MailScanner and restart Postfix.
$service MailScanner start $service postfix restart
[edit] Teaching Bayes
The sa-learn command is used to teach SpamAssassin about spam and ham. The following script will run the sa-learn command on all mail directories under a given username.
Please note that the sa-learn command is quite resource intensive and can take a while to run. Run it at night while your load is light.
#!/bin/sh
#
# Description:
# Runs sa-learn to train the Spamassassin bayes filter and then deletes all mail older
# than seven days
#
# For use with the tutorial at:
# http://www.linode.com/wiki/index.php/CentOS
#
# Check for correct usage
if [ $# -ne 1 ]; then
echo 1>&2 You must supply a username!
echo 1>&2 Usage: $0 username
exit 1
fi
echo "Learning SPAM"
echo ""
echo "running sa-learn --spam"
sa-learn --spam --no-sync --showdots /home/$1/mail/*/mail/.spam/cur
sa-learn --spam --no-sync --showdots /home/$1/mail/*/mail/.spam/new
echo "removing spam"
find /home/$1/mail/*/mail/.spam/cur -type f -mtime +7 -exec rm {} \;
find /home/$1/mail/*/mail/.spam/new -type f -mtime +7 -exec rm {} \;
echo "running sa-learn --ham"
sa-learn --ham --no-sync --showdots /home/$1/mail/*/mail/.ham/cur
sa-learn --ham --no-sync --showdots /home/$1/mail/*/mail/.ham/new
echo "removing ham"
find /home/$1/mail/*/mail/.ham/cur -type f -mtime +7 -exec rm {} \;
find /home/$1/mail/*/mail/.ham/new -type f -mtime +7 -exec rm {} \;
echo "syncing"
sa-learn --sync
echo "Done!"
[edit] Make a Backup
If you elected to create a backup copy in the Create a Backup Disk Image now is the time to make use of it.
Login to the Linode Manager and delete the book disk backup that you created earlier. Make sure you are deleting the backup partition! This will free up enough space to make a duplicate of the primary disk image.
Once the disk image is deleted click on the primary disk image to go to the Edit Disk Image page. Then click on the Duplicate Image button to make a backup copy.
[edit] Final Thoughts
Now that you have a Linode ready for virtual hosting what's next? Make it yours! Take it apart, put it back together, and figure out what configuration works for you. Just make sure you take notes! Also, come back and update this page if you find a problem or have a better way of doing things.
Whatever you do, make sure you keep your Linode secure and up-to-date. Regularly run yum update and keep on top of security patches. You are responsible for keeping on top of all security patches for the software installed from source.
The easiest way to keep track of source security patches is to subscribe to mailing lists. These are the announcement mailing lists for the source software used in this Tutorial.
Postfix Admin has no mailing list so be sure to visit the site once a month or so.
Enjoy your Linode!
[edit] Other Options
[edit] Apache Installation
This section was replaced by the Lighttpd section above.
Apache is the most popular web server available today. In this tutorial Apache will be setup to serve pages in virtual mode. That is several domains will be hosted from a single IP address.
[edit] Installation
To install Apache run:
$yum install httpd mod_ssl
[edit] Config Changes
After Apache has been installed it needs to be configured before it is started. Edit the configuration file /etc/httpd/conf/httpd.conf with your favorite editor. You can leave the other settings at their default values.
FILE: /etc/httpd/conf/httpd.conf
ServerTokens Prod
Timeout 45
KeepAlive On
Listen [Your Linode IP]:80
ServerAdmin [Your Email Address]
ServerName [Your Domain Name]:80
# UserDir disable
UserDir public_html
<Directory /home/*/public_html>
AllowOverride FileInfo AuthConfig Limit
Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
<Limit GET POST OPTIONS>
Order allow,deny
Allow from all
</Limit>
<LimitExcept GET POST OPTIONS>
Order deny,allow
Deny from all
</LimitExcept>
</Directory>
DirectoryIndex index.html index.htm index.html.var index.php main.php
NameVirtualHost *:80
Include /etc/httpd/conf/httpd_vhosts.conf
FILE: /etc/httpd/conf.d/ssl.conf
SSLCertificateFile /etc/pki/[YourDomain]CA/server.crt SSLCertificateKeyFile /etc/pki/[YourDomain]CA/server.key
[edit] Virtual Hosting
Apache needs to know about each domain that you want to host. In this tutorial this is done through the config file. Every time you wish to host a new domain or sub-domain you will have to edit the config file.
There is a trade off here between the number of domains and ease of setup. There are other ways of hosting multiple websites on one Linode but they can be more difficult to setup. Hosting through the config file will work fine until you reach a certain number of domains. At that point you will begin to run into file descriptor problems. If you are at that point look for another solution than this tutorial provides. [9]
To make things a little easier all of the virtual host declarations will be placed in a separate file. To do so create a file in /etc/httpd/conf/ called httpd_vhosts.conf. Then, to that file, add the following for each domain that you are hosting.
You will also need to add a new user for each domain as well as the following directories.
/home/[Username]/public_html /var/log/httpd/[Username]
A shell script which will add domain users and setup their folders can be found here: Domain Adding Script. To use this script, upload it to your server, and simply supply a username.
$sh addDomain.sh [Username]
The Include line added to the config file above will pull in the httpd_vhosts.conf that was just created. That means all hosting changes are consolidated to a single file.
Now start Apache:
$service httpd start $chkconfig --level 3 httpd on
[edit] Setup Your first domain
Now is the time to setup your first domain. Add a new domain user with the addDomain.sh script. Add the domain to the httpd_vhosts.conf file described above. Now is also a good time to test your webserver configuration.
You should add the main domain that you will be using for this Linode. Also, at this time also add two subdomains that will be used, one for webmail and the other for Postfix administration.
To start you will need to create two directories for these subdomains. Create a mailadmin and webmail folder under your main usernames web folder.
$mkdir /home/[Your Domain Username]/public_html/mailadmin $mkdir /home/[Your Domain Username]/public_html/webmail
The following domains will be added:
- mailadmin.[Your Domain].com
- webmail.[Your Domain].com
- [Your Domain].com
CREATE FILE: /etc/httpd/conf/httpd_vhosts.conf
<VirtualHost *:80>
DocumentRoot /home/[Domain Username]/public_html/mailadmin
ServerName mailadmin.[Domain Name: example.com]
ErrorLog /var/log/httpd/[Domain Username]/mailadmin-error_log
CustomLog /var/log/httpd/[Domain Username]/mailadmin-access_log common
</VirtualHost>
<VirtualHost *:80>
DocumentRoot /home/[Domain Username]/public_html/webmail
ServerName webmail.[Domain Name: example.com]
ErrorLog /var/log/httpd/[Domain Username]/webmail-error_log
CustomLog /var/log/httpd/[Domain Username]/webmail-access_log common
</VirtualHost>
<VirtualHost *:80>
DocumentRoot /home/[Domain Username]/public_html
ServerName [Domain Name: example.com]
ServerAlias *.[Domain Name: example.com]
ErrorLog /var/log/httpd/[Domain Username]/error_log
CustomLog /var/log/httpd/[Domain Username]/access_log common
</VirtualHost>
Since this is the main domain name https should also be setup. Edit /etc/httpd/conf.d/ssl.conf make the following changes.
FILE: /etc/httpd/conf.d/ssl.conf
NameVirtualHost *:443
<VirtualHost *:443>
DocumentRoot "/home/[Your Domain User]/public_html/mailadmin"
ServerName mailadmin.[Your Domain].com:443
ErrorLog /var/log/httpd/[Your Domain Username]/mailadmin-ssl_error_log
TransferLog /var/log/httpd/[Your Domain Username]/mailadmin-ssl_access_log
LogLevel warn
SSLEngine on
SSLProtocol all -SSLv2
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
SSLCertificateFile /etc/pki/[Your Domain]CA/server.crt
SSLCertificateKeyFile /etc/pki/[Your Domain]CA/server.key
<Files ~ "\.(cgi|shtml|phtml|php3?)$">
SSLOptions +StdEnvVars
</Files>
<Directory "/home/[Your Domain Username]/mailadmin/cgi-bin">
SSLOptions +StdEnvVars
</Directory>
SetEnvIf User-Agent ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
CustomLog /var/log/httpd/[Your Domain Username]/mailadmin-ssl_request_log \
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
</VirtualHost>
<VirtualHost *:443>
DocumentRoot "/home/[Your Domain User]/public_html/webmail"
ServerNae webmail.[Your Domain].com:443
ErrorLog /var/log/httpd/[Your Domain Username]/webmail-ssl_error_log
TransferLog /var/log/httpd/[Your Domain Username]/webmail-ssl_access_log
LogLevel warn
SSLEngine on
SSLProtocol all -SSLv2
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
SSLCertificateFile /etc/pki/[Your Domain]CA/server.crt
SSLCertificateKeyFile /etc/pki/[Your Domain]CA/server.key
<Files ~ "\.(cgi|shtml|phtml|php3?)$">
SSLOptions +StdEnvVars
</Files>
<Directory "/home/[Your Domain Username]/webmail/cgi-bin">
SSLOptions +StdEnvVars
</Directory>
SetEnvIf User-Agent ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
CustomLog /var/log/httpd/[Your Domain Username]/webmail-ssl_request_log \
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
</VirtualHost>
<VirtualHost *:443>
DocumentRoot "/home/[Your Domain User]/public_html"
ServerName www.[Your Domain].com:443
ErrorLog /var/log/httpd/[Your Domain Username]/ssl_error_log
TransferLog /var/log/httpd/[Your Domain Username]/ssl_access_log
LogLevel warn
SSLEngine on
SSLProtocol all -SSLv2
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
SSLCertificateFile /etc/pki/[Your Domain]CA/server.crt
SSLCertificateKeyFile /etc/pki/[Your Domain]CA/server.key
<Files ~ "\.(cgi|shtml|phtml|php3?)$">
SSLOptions +StdEnvVars
</Files>
<Directory "/home/[Your Domain Username]/cgi-bin">
SSLOptions +StdEnvVars
</Directory>
SetEnvIf User-Agent ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
CustomLog /var/log/httpd/[Your Domain Username]/ssl_request_log \
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
</VirtualHost>
Now restart Apache.
$service httpd restart
[edit] PHP
If you opted to install Apached instead of Lighttpd then you can install PHP with yum. Installing PHP using yum is a very simple process. Simply issue the following command and you are done.
$yum install php php-common php-mysql php-mbstring php-imap php-pear-DB $service httpd restart
