Table of Contents

Base OS Config

The base OS is supplied by Contegix. It is running CentOS, which we have brought up to 5.5 via 'yum update'.

We needed to comment out the IPv6 hosts file entry in order to make mysql access control work properly.

SSH has been moved to port 2206.

We have created accounts for those people who could reasonably be expected to do admin-type functions. We just used useradd, and didn't worry about user ID's staying in sync with our other machines. There will be no shell accounts for non-sysadmin users on amber.

iptables is configured by 'system-config-securitylevel-tui' or editing /etc/sysconfig/iptables directly. If editing the config file, run 'service iptables restart' afterwards.

selinux is disabled by 'echo 0 > /selinux/enforce'

FIXME There is an admin panel to access the VM. We need to document it.

Apache

We copied over almost all of the debian configs from bud into /etc/httpd. This means that we still have the sites-available/ and sites-enabled/ directories, and that we don't have to rework our configs into a way that fits the 'CentOS way' of setting up Apache. The original CentOS config file is in /etc/httpd/conf/httpd.conf.dist if we need it for anything. One change we did make was putting all our sites under /srv/www/html.

We used chkconfig to make sure Apache started at boot, and enabled ports 80 and 443 in iptables.

To set up SSL, we did:

# cd /etc/pki/tls/certs

# make apache.pem

Country Name (2 letter code) [GB]:US

State or Province Name (full name) [Berkshire]:Missouri

Locality Name (eg, city) [Newbury]:St. Louis

Organization Name (eg, company) [My Company Ltd]:St. Louis Unix User's Group

Organizational Unit Name (eg, section) []:Admin Team

Common Name (eg, your name or your server's hostname) []:amber.sluug.org

Email Address []:sysadmin@sluug.org

Then we did:

# yum install mod_ssl

In /etc/httpd/conf.d/ssl.conf, we set the following two values:

SSLCertificateFile /etc/pki/tls/certs/sluug.pem

SSLCertificateKeyFile /etc/pki/tls/certs/sluug.pem

And then changed:

<VirtualHost _default_:443>

to

<VirtualHost amber.sluug.org:443>

Then we restarted apache.

PHP

PHP didn't require much configuration. We just did:

yum install php php-mysql php-mbstring php-imap

Mysql

Install mysql:

# yum install mysql mysql-server

# mysql_secure_installation

Edit /etc/my.cnf. Notice that we are bound to 127.0.0.1, and don't accept queries over the network. Also, the query log is set to /var/log/mysql_query.log. This is good for troubleshooting, but should be turned off for normal use.

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log=/var/log/mysql_query.log
user=mysql
# Default to using old password format for compatibility with mysql 3.x
# clients (those using the mysqlclient10 compatibility package).
old_passwords=0
bind-address=127.0.0.1

# Disabling symbolic-links is recommended to prevent assorted security risks;
# to do so, uncomment this line:
# symbolic-links=0

[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

Postfixadmin

Postfixadmin is a web tool for managing virtual mailboxes across multiple domains. In our case, the mailboxes and domains are both defined in mysql, while the actual mail spools live under /home/vmail/user@domain.tld. When receiving mail, postfix looks in mysql to see what to do with the mail. It knows exactly where to look based on the contents of the /etc/postfix/mysql* files. Similarly, when courier gets an IMAP or POP3 request, it looks in mysql to authenticate users and to learn where their mail spools are. Postfixadmin lets us easily populate the database with the needed records and avoid manually running SQL.

Download postfixadmin from http://sourceforge.net/projects/postfixadmin/. Untar it into /srv/www/amber.sluug.org and create a symlink postfixadmin→postfixadmin.x.y.z.

Log into mysql as the root user. Run:

mysql> CREATE DATABASE postfix;
mysql> CREATE USER postfix@localhost IDENTIFIED BY 'xxxxxxx';
mysql> GRANT ALL PRIVILEGES ON postfix.* TO postfix;
mysql> flush privileges;

Navigate to https://amber.sluug.org/postfixadmin/setup.php. Generate the setup password as prompted and copy it into /srv/www/amber.sluug.org/postfixadmin/config.inc.php as $CONF['setup_password'].

Also in that file, set:

$CONF['database_type'] = 'mysqli';
$CONF['database_host'] = 'localhost';
$CONF['database_user'] = 'postfix';
$CONF['database_password'] = 'xxxxxxx';
$CONF['database_name'] = 'postfix';
$CONF['database_prefix'] = '';
$CONF['encrypt'] = 'md5crypt';

Then go back to https://amber.sluug.org/postfixadmin/setup.php. It will create an admin user and build the database structure.

After postfixadmin is set up, mailboxes can be manually created, or we can do a bulk populate. The bulk populate script is ~jmuse/bulk_add_md5.pl. It expects to find a file called ~jmuse/.md5, of the format:

accountname:md5_hash:Real Name

Each account name needs to be on a separate line. The script should really be smart enough to check for duplicates, or accounts already present, but it isn't at the moment. Running the script without arguments will populate the mailbox table and create the appropriate maildir under /home/vmail. Because we only have one domain at the moment, it assumes that the domain part is 'sluug.org'. If we ever expected to need this tool after the migration, these would be good changes to make. The script works on the principle that we can copy md5 hashes from /etc/shadow on bud into the postfix DB.

#!/usr/bin/perl

# Script to take data in the form
# accountname:md5_hash:real_name
# and put it into the postfix database

# Warning: no error checking or duplicate checking!

use warnings;
use strict;
use DBI;

open (FILE,"/home/jmuse/.md5") or die $!;

my $dbuser='postfix';
my $dbpass='xxxxxx';
my $db='postfix';
my $dbh=DBI->connect('DBI:mysql:postfix',$dbuser,$dbpass) || die $!;
while (<FILE>) {
        my $line=$_;
        my ($user,$pass,$realname)=split(":",$line);
        my $mailuser=$user . '@sluug.org';
        my $mailboxname=$user. '@sluug.org/';
        my $query="INSERT INTO mailbox (username,password,name,maildir,quota,local_part,domain,created,modified,active) VALUES (?,?,?,?,0,?,'sluug.org','2011-05-21 12:44:58','2011-05-21 12:44:58',1)";
        my $query_handle=$dbh->prepare($query);
        $query_handle->execute($mailuser,$pass,$realname,$mailboxname,$user);
        system("/usr/lib/courier-imap/bin/maildirmake /home/vmail/$mailboxname");
        system ("/bin/chown -R vmail:vmail /home/vmail/$mailboxname");
}

Postfix/Amavisd-new/Spamassassin/ClamAV/Postgrey

Mysql support is required in postfix for our virtual domain setup to work. We've removed the standard CentOS postfix and installed the one from CentOS-Plus. This is done by

yum remove postfix

Then edit /etc/yum.repos.d/CentOS-Base.repo. We need to change first the base repo:

[base]
name=CentOS-$releasever - Base
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os
#baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
exclude=postfix spamassass* 

and then the updates repo:

[updates]
name=CentOS-$releasever - Updates
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates
#baseurl=http://mirror.centos.org/centos/$releasever/updates/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
exclude=postfix spamass*

Then run:

# yum install postfix

From the docs at http://wiki.centos.org/AdditionalResources/Repositories/RPMForge?action=show&redirect=Repositories%2FRPMForge, we enabled rpmforge for more current spamassassin and clamav builds.

#wget http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.2-2.el5.rf.x86_64.rpm

#rpm -K rpmforge-release-0.5.2-2.el5.rf.*.rpm

#rpm -i rpmforge-release-0.5.2-2.el5.rf.*.rpm

#yum –enablerepo=rpmforge,rpmforge-extras install amavisd-new clamav clamav-devel clamd spamassassin #yum install postgrey

We created id user 'vmail' for virtual mail delivery, UID/GID 5000/500.

inet_interfaces in /etc/postfix/main.cf is set to 'all'

myhostname in /etc/postfix/main.cf is set to 'amber.sluug.org'

Also in main.cf, add a line saying:

content_filter=amavisfeed:[127.0.0.1]:10024

Set mydestination in main.cf (DO NOT add sluug.org, that will be covered by the virtual DB mappings):

mydestination = $myhostname, localhost.$mydomain, localhost

And an entry for smtpd_recipient_restrictions:

smtpd_recipient_restrictions =
   permit_mynetworks,
   reject_unauth_destination,
   check_policy_service unix:postgrey/socket,
   permit

The following block in main.cf configures virtual domain mappings:

virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf
virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_domains_maps.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf
virtual_mailbox_limit_maps = mysql:/etc/postfix/mysql_virtual_mailbox_limit_maps.cf
virtual_mailbox_base = /home/vmail/
virtual_mailbox_limit = 51200000
virtual_minimum_uid = 5000
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
virtual_transport = virtual

And this configures quotas, also in main.cf:

virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf
virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_domains_maps.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf
virtual_mailbox_limit_maps = mysql:/etc/postfix/mysql_virtual_mailbox_limit_maps.cf
virtual_mailbox_base = /home/vmail/
virtual_mailbox_limit = 51200000
virtual_minimum_uid = 5000
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
virtual_transport = virtual

Also in /etc/postfix/main.cf, add or uncomment line "recipient_delimiter = +". This specifies the separator between user names and address extensions (user+foo).

Also in /etc/postfix/main.cf, add "disable_vrfy_command=yes". Disable VRFY….From Jeff's presentation.

Now, edit the mapping files. IMPORTANT: These files contain database passwords! They need to be root:postfix 640!

Create /etc/postfix/mysql_relay_domains_maps.cf:

user = postfix
password = xxxxxxxx
hosts = 127.0.0.1
dbname = postfix
table = domain
select_field = domain
where_field = domain
additional_conditions = and backupmx = '1'

Create mysql_virtual_alias_maps.cf:

user = postfix
password = xxxxxx
hosts = 127.0.0.1
dbname = postfix
table = alias
select_field = goto
where_field = address

Create mysql_virtual_domains_maps.cf"

user = postfix
password = xxxxxx
hosts = 127.0.0.1
dbname = postfix
table = domain
select_field = domain
where_field = domain
#additional_conditions = and backupmx = '0' and active = '1'

Create mysql_virtual_mailbox_limit_maps.cf:

user = postfix
password = xxxxxx
hosts = 127.0.0.1
dbname = postfix
table = mailbox
select_field = quota
where_field = username
#additional_conditions = and active = '1'

Create mysql_virtual_mailbox_maps.cf:

user = postfix
password = xxxxxx
hosts = 127.0.0.1
dbname = postfix
table = mailbox
select_field = maildir
where_field = username
#additional_conditions = and active = '1'

/etc/amavisd.conf requires some changes http://wiki.centos.org/HowTos/Amavisd

Append the following to /etc/postfix/master.cf:

amavisfeed unix    -       -       n        -      2     lmtp
    -o lmtp_data_done_timeout=1200
    -o lmtp_send_xforward_command=yes
    -o disable_dns_lookups=yes
    -o max_use=20

127.0.0.1:10025 inet n    -       n       -       -     smtpd
    -o content_filter=
    -o smtpd_delay_reject=no
    -o smtpd_client_restrictions=permit_mynetworks,reject
    -o smtpd_helo_restrictions=
    -o smtpd_sender_restrictions=
    -o smtpd_recipient_restrictions=permit_mynetworks,reject
    -o smtpd_data_restrictions=reject_unauth_pipelining
    -o smtpd_end_of_data_restrictions=
    -o smtpd_restriction_classes=
    -o mynetworks=127.0.0.0/8
    -o smtpd_error_sleep_time=0
    -o smtpd_soft_error_limit=1001
    -o smtpd_hard_error_limit=1000
    -o smtpd_client_connection_count_limit=0
    -o smtpd_client_connection_rate_limit=0
    -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_milters,no_address_mappings
    -o local_header_rewrite_clients=
    -o smtpd_milters=
    -o local_recipient_maps=
    -o relay_recipient_maps=

Finally, put it all together:

postfix check
service postfix restart
sa-update
service spamassassin start
service amavisd start
service clamd start
service postgrey start
chkconfig --level 35 postgrey on

Courier

Download the most current versions of the following from http://www.courier-mta.org/download.php

As an unprivileged user, do:

mkdir $HOME/rpm
mkdir $HOME/rpm/SOURCES
mkdir $HOME/rpm/SPECS
mkdir $HOME/rpm/BUILD
mkdir $HOME/rpm/SRPMS
mkdir $HOME/rpm/RPMS
mkdir $HOME/rpm/RPMS/i386
echo "%_topdir $HOME/rpm" >> $HOME/.rpmmacros

In the directory where you downloaded the tarballs, run:

rpmbuild -ta courier-authlib-0.63.0.tar.bz2

After the build completes, you will find the completed packages in $HOME/rpm/RPMS/x86_64. As root, run:

#rpm -ivh courier-authlib-0.63.0-1.x86_64.rpm courier-authlib-devel-0.63.0-1.x86_64.rpm courier-authlib-mysql-0.63.0-1.x86_64.rpm

Then repeat the rpmbuild and installation again with courier-imap-4.8.0.tar.bz2.

Use chkconfig to verify that both courier-authlib and courier-imap start in runlevels 3 and 5.

As root, edit /etc/authlib/authmysqlrc:

MYSQL_SERVER            127.0.0.1
MYSQL_USERNAME          postfix
MYSQL_PASSWORD          xxxxxxxx
MYSQL_DATABASE          postfix
MYSQL_CRYPT_PWFIELD     password
DEFAULT_DOMAIN                  sluug.org
MYSQL_UID_FIELD         5000
MYSQL_GID_FIELD         5000
MYSQL_LOGIN_FIELD       username
MYSQL_HOME_FIELD        '/home/vmail'
MYSQL_NAME_FIELD        name
MYSQL_MAILDIR_FIELD     maildir
MYSQL_QUOTA_FIELD concat(quota,'S')

In /usr/lib/courier-imap/share, copy the original certs to ${certname}.dist. Then run ./mkimapdcert and ./mkpop3dcert to generate new ones. The configuration files for imapd, imapd-ssl, pop3d, and pop3d-ssl are in /usr/lib/courier-imap/etc. They shouldn't need changing, but this is where we define the certificate names the SSL-enabled services use.

Be sure that TCP 110, 143, 993, and 995 are enabled in iptables.

Mailman

We installed mailman 2.1.12 from http://sourceforge.net/projects/mailman/files because there doesn't seem to be an htdig patch for 2.1.13. We untarred the mailman package to /usr/local/src/mailman-2.1.2 and then ran:

#patch -p1 < ../htdig-2.1.12-0.1.patch

We followed the mailman build instructions from MailMan, although we didn't have a problem to fix regarding language support. Then:

cd /usr/local/mailman/templates
sudo chmod 02775 *
cd /usr/local/mailman/messages
sudo chmod 02775 *
cd /usr/local/mailman/archives
sudo chown apache private
cd /usr/local/mailman
sudo cp scripts/mailman /etc/init.d/mailman
chkconfig --add mailman
chkconfig --level 35 mailman on

Mailman wouldn't start because the mailman list was missing.

FIXME Did someone rsync over lists from bud? What happened in this step? It should have been lists/, data/, archives/, followed by /usr/local/mailman/bin/genaliases.

See MailMan for configuration files and options, including Apache.

Webmail

We have installed roundcube as our Webmail tool.