PPPower Server: Difference between revisions

From Alteeve Wiki
Jump to navigation Jump to search
 
(94 intermediate revisions by 2 users not shown)
Line 5: Line 5:
= Post OS Install =
= Post OS Install =


First, the packages we will want to install:
First, some post-install preparation. We'll need to set up some basic security, a program to report server statistics, and some 3rd-party yum repositories for additional software.
 
Yum repo install.
<source lang="bash">yum -y install yum-protectbase
rpm -Uvh https://alteeve.ca/an-repo/el6/RPMS/noarch/alteeve-repo-0.1-3.noarch.rpm
yum clean expire-cache
yum -y update
</source>
 
The yum-protectbase plugin will ensure that the 3rd-party repos play nicely and never overwrite the Base repos.  To use this plugin with a specific repo, add <span class="code">protect=0</span> or <span class="code">protect=1</span> to the repo's config file.


<source lang="bash">
<source lang="bash">
yum install httpd httpd-tools postgresql-server postgresql-plperl postgresql-contrib postgresql mysql-server telnet mod_ssl mysql-server php-mysql gcc jwhois bind
cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.orig
vim /etc/yum.repos.d/CentOS-Base.repo
# add protect=1 to each paragraph
diff -U 0 /etc/yum.repos.d/CentOS-Base.repo.orig /etc/yum.repos.d/CentOS-Base.repo
</source>
<source lang="bash">
--- /etc/yum.repos.d/CentOS-Base.repo.orig 2012-05-07 01:07:47.688145406 -0400
+++ /etc/yum.repos.d/CentOS-Base.repo 2012-05-07 01:08:15.915322496 -0400
@@ -18,0 +19 @@
+protect=1
@@ -26,0 +28 @@
+protect=1
@@ -34,0 +37 @@
+protect=1
@@ -43,0 +47 @@
+protect=1
@@ -52,0 +57 @@
+protect=1
</source>
</source>


Packages that are currently needed for personal stuff.
=== Protecting against malicious users with Denyhosts. ===
 
Denyhosts is a daemon that watches for too many failed logins via ssh. It uses TCP-wrappers to deny the user access to ssh (or any service) on the server after X failed logins. It has the option to download a list of known malicious IPs and add them to /hosts.deny, making possible to block attackers before they attack the server.
 
Install denyhosts
<source lang="bash">yum -y install denyhosts</source>


Edit the config to your preferences.
<source lang="bash">
<source lang="bash">
yum install perl-XML-Simple perl-MIME-Lite perl-DBD-MySQL perl-DBD-Pg
cp /etc/denyhosts.conf /etc/denyhosts.conf.orig
vim /etc/denyhosts.conf
</source>
<source lang="bash">
BLOCK_SERVICE = ALL
SYNC_SERVER = http://xmlrpc.denyhosts.net:9911
SYNC_DOWNLOAD = yes
</source>
<source lang="bash">
diff -U 0 /etc/denyhosts.conf.orig /etc/denyhosts.conf
</source>
<source lang="diff">
--- /etc/denyhosts.conf.orig 2012-05-13 02:33:05.584566483 -0400
+++ /etc/denyhosts.conf 2012-05-13 02:34:19.386558503 -0400
@@ -96 +96 @@
-#BLOCK_SERVICE = ALL
+BLOCK_SERVICE = ALL
@@ -98 +98 @@
-BLOCK_SERVICE  = sshd
+#BLOCK_SERVICE  = sshd
@@ -547 +547 @@
-#SYNC_SERVER = http://xmlrpc.denyhosts.net:9911
+SYNC_SERVER = http://xmlrpc.denyhosts.net:9911
@@ -582 +582 @@
-#SYNC_DOWNLOAD = yes
+SYNC_DOWNLOAD = yes
</source>
</source>


= Apache =
White-list any trusted machines, including <span class="code">localhost</span>.
 
<source lang="bash">
After all changes, use this to make sure there are no syntax errors.
cp /etc/hosts.allow /etc/hosts.allow.orig
vim /etc/hosts.allow
</source>
<source lang="bash">
127.0.0.1
206.108.5.162
</source>
<source lang="bash">
diff -U 0 /etc/hosts.allow.orig /etc/hosts.allow
</source>
<source lang="diff">
--- /etc/hosts.allow.orig 2012-05-13 02:36:02.613767847 -0400
+++ /etc/hosts.allow 2012-05-13 02:40:37.473523845 -0400
@@ -10,0 +11,2 @@
+127.0.0.1
+206.108.5.162
</source>


Start the service.
<source lang="bash">
<source lang="bash">
service httpd configtest
chkconfig denyhosts on
/etc/init.d/denyhosts start
</source>
</source>
<source lang="text">
<source lang="text">
Syntax OK
Starting denyhosts:                                        [  OK ]
</source>
</source>


{{note|1=This needs to be explained.}}
=== Additional software to install ===
 
To view neatly-summarized daily logs, and system resource usage.
<source lang="bash">yum -y install logwatch htop</source>


Packages for web server and wiki install.
<source lang="bash">
<source lang="bash">
diff -u httpd.conf.orig httpd.conf
yum install httpd httpd-tools postgresql94-server postgresql94-plperl postgresql94-contrib postgresql94 mysql-server telnet mod_ssl mysql-server php-mysql gcc jwhois bind \
            acpid bind-utils syslinux screen man bzip2 zip unzip php-pgsql php yum-utils policycoreutils-python rsync
chkconfig acpid on
</source>
</source>
<source lang="diff">
 
--- httpd.conf.orig 2010-05-28 03:11:06.000000000 -0400
Packages that are currently needed for personal stuff.
+++ httpd.conf 2011-05-13 21:56:27.000000000 -0400
 
@@ -100,12 +100,12 @@
<source lang="bash">
# MaxClients: maximum number of server processes allowed to start
yum install perl-XML-Simple perl-MIME-Lite perl-DBD-MySQL perl-DBD-Pg perl-Digest-Perl-MD5 mod_auth_pgsql perl-Digest-SHA perl-CGI perl-Time-HiRes
# MaxRequestsPerChild: maximum number of requests a server process serves
</source>
<IfModule prefork.c>
 
-StartServers      8
= Apache =
-MinSpareServers    5
 
Apache is configured first with a global configuration, which also defines the "default" website which is shown when the server is called by it's IP address (or by a domain that is not configured). Then with per-domain configurations known as "virtual host containers".
 
First, the global configuration and default domain. We will put our default website in <span class="code">/var/www/default/</span>. So the first step is to create the needed directories.
 
<source lang="bash">
mkdir -p /var/www/default/{html,cgi-bin,logs}
chown -R apache:apache /var/www
</source>
 
Now to edit the configuration file.
 
<source lang="bash">
cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.orig
vim /etc/httpd/conf/httpd.conf
</source>
 
{{note|1=This needs to be explained.}}
 
Make the following changes.
 
<source lang="bash">
diff -U 0 /etc/httpd/conf/httpd.conf.orig /etc/httpd/conf/httpd.conf
</source>
<source lang="diff">
--- /etc/httpd/conf/httpd.conf.orig 2012-05-13 19:32:07.718570148 -0400
+++ /etc/httpd/conf/httpd.conf 2012-05-13 21:48:18.439736244 -0400
@@ -103,6 +103,6 @@
-StartServers      8
-MinSpareServers    5
-MaxSpareServers  20
-MaxSpareServers  20
-ServerLimit      256
-ServerLimit      256
Line 52: Line 162:
+MaxClients      512
+MaxClients      512
+MaxRequestsPerChild  8000
+MaxRequestsPerChild  8000
</IfModule>
@@ -119,5 +119,5 @@
# worker MPM
@@ -116,11 +116,11 @@
# ThreadsPerChild: constant number of worker threads in each server process
# MaxRequestsPerChild: maximum number of requests a server process serves
<IfModule worker.c>
-StartServers        4
-StartServers        4
-MaxClients        300
-MaxClients        300
Line 69: Line 173:
+MaxSpareThreads    150  
+MaxSpareThreads    150  
+ThreadsPerChild    50
+ThreadsPerChild    50
MaxRequestsPerChild  0
@@ -262 +262 @@
</IfModule>
@@ -259,7 +259,7 @@
# e-mailed.  This address appears on some server-generated pages, such
# as error documents.  e.g. admin@your-domain.com
#
-ServerAdmin root@localhost
-ServerAdmin root@localhost
+ServerAdmin admin@alteeve.com
+ServerAdmin admin@alteeve.ca
@@ -276,0 +277 @@
#
+ServerName omiya.alteeve.ca:80
# ServerName gives the name and port that the server uses to identify itself.
@@ -292 +293 @@
@@ -274,6 +274,7 @@
# redirections work in a sensible way.
#
#ServerName www.example.com:80
+#ServerName *:80
#
# UseCanonicalName: Determines how Apache constructs self-referencing
@@ -289,7 +290,7 @@
# documents. By default, all requests are taken from this directory, but
# symbolic links and aliases may be used to point to other locations.
#
-DocumentRoot "/var/www/html"
-DocumentRoot "/var/www/html"
+DocumentRoot "/var/www/default/html"
+DocumentRoot "/var/www/default/html"
@@ -317 +318 @@
#
# Each directory to which Apache has access can be configured with respect
@@ -314,7 +315,7 @@
#
# This should be changed to whatever you set DocumentRoot to.
#
-<Directory "/var/www/html">
-<Directory "/var/www/html">
+<Directory "/var/www/default/html">
+<Directory "/var/www/default/html">
@@ -551 +552 @@
#
# Possible values for the Options directive are "None", "All",
@@ -548,9 +549,9 @@
# We include the /icons/ alias for FancyIndexed directory listings.  If you
# do not use FancyIndexing, you may comment this out.
#
-Alias /icons/ "/var/www/icons/"
-Alias /icons/ "/var/www/icons/"
+Alias /icons/ "/var/www/default/icons/"
+Alias /icons/ "/var/www/default/icons/"
@@ -553 +554 @@
-<Directory "/var/www/icons">
-<Directory "/var/www/icons">
+<Directory "/var/www/default/icons">
+<Directory "/var/www/default/icons">
    Options Indexes MultiViews FollowSymLinks
@@ -576 +577 @@
    AllowOverride None
    Order allow,deny
@@ -573,13 +574,13 @@
# The same rules about trailing "/" apply to ScriptAlias directives as to
# Alias.
#
-ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
-ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
+ScriptAlias /cgi-bin/ "/var/www/default/cgi-bin/"
+ScriptAlias /cgi-bin/ "/var/www/default/cgi-bin/"
@@ -582 +583 @@
#
# "/var/www/cgi-bin" should be changed to whatever your ScriptAliased
# CGI directory exists, if you have that configured.
#
-<Directory "/var/www/cgi-bin">
-<Directory "/var/www/cgi-bin">
+<Directory "/var/www/default/cgi-bin">
+<Directory "/var/www/default/cgi-bin">
    AllowOverride None
@@ -855 +856 @@
    Options None
    Order allow,deny
@@ -852,11 +853,11 @@
# copying them to /your/include/path/, even on a per-VirtualHost basis.
#
-Alias /error/ "/var/www/error/"
-Alias /error/ "/var/www/error/"
+Alias /error/ "/var/www/default/error/"
+Alias /error/ "/var/www/default/error/"
@@ -859 +860 @@
<IfModule mod_negotiation.c>
<IfModule mod_include.c>
-    <Directory "/var/www/error">
-    <Directory "/var/www/error">
+    <Directory "/var/www/default/error">
+    <Directory "/var/www/default/error">
        AllowOverride None
@@ -990 +991 @@
        Options IncludesNoExec
        AddOutputFilter Includes html
@@ -987,7 +988,7 @@
#
# Use name-based virtual hosting.
#
-#NameVirtualHost *:80
-#NameVirtualHost *:80
+NameVirtualHost *:80
+NameVirtualHost *:80
#
@@ -1004,5 +1005,5 @@
# NOTE: NameVirtualHost cannot be used without a port specifier
# (e.g. :80) if mod_ssl is being used, due to the nature of the
@@ -1001,9 +1002,10 @@
# server name.
#
#<VirtualHost *:80>
-#    ServerAdmin webmaster@dummy-host.example.com
-#    ServerAdmin webmaster@dummy-host.example.com
-#    DocumentRoot /www/docs/dummy-host.example.com
-#    DocumentRoot /www/docs/dummy-host.example.com
Line 167: Line 211:
-#    ErrorLog logs/dummy-host.example.com-error_log
-#    ErrorLog logs/dummy-host.example.com-error_log
-#    CustomLog logs/dummy-host.example.com-access_log common
-#    CustomLog logs/dummy-host.example.com-access_log common
+#    ServerAdmin admin@alteeve.com
+#    ServerAdmin admin@alteeve.ca
+#    DocumentRoot /var/www/default/html
+#    DocumentRoot /var/www/default/html
+#    ServerName unknown.alteeve.com
+#    ServerName unknown.alteeve.ca
+#    ErrorLog /var/www/default/logs/error.log
+#    ErrorLog /var/www/default/logs/error.log
+#    CustomLog /var/www/default/logs/access.log common
+#    CustomLog /var/www/default/logs/access.log common
#</VirtualHost>
@@ -1009,0 +1011 @@
+
</source>
</source>


== SSL Virtual Hosts ==
After all changes, use this to make sure there are no syntax errors.


SSL provides for secure client to server communications.
<source lang="bash">
apachectl -t
</source>
<source lang="text">
[Sun May 13 21:48:11 2012] [warn] NameVirtualHost *:80 has no VirtualHosts
Syntax OK
</source>


=== Creating The Signed Certificate ===
Note that the <span class="code">[Sun May 13 21:48:11 2012] [warn] NameVirtualHost *:80 has no VirtualHosts</span> is expected at this stage as we've not yet configured any virtual hosts.


This section assumes you are using a 3rd party signing authority. Specifically, I use http://www.trustico.ca/ (resellers of http://RapidSSL.com and others). This is also for a domain-specific certificate. Wildcard certificates will differ.
All virtual host configuration files need to be created in the <span class="code">/etc/httpd/conf.d</span> directory and the file must have the <span class="code">.conf</span> suffix in order to be read by apache. These files will be read in order, so if you want to ensure that one file is read before another, as we will do shortly, you can prefix the configuration file with an integer to ensure read order.


First, create 2048bit private key. Note that this will require a pass-phrase, which you will need to enter whenever the Apache daemon <span class="code">httpd</span> daemon starts. If you do not want this, remove the <span class="code">-des3</span> switch.
I like to redirect all unknown server requests to <span class="code">http://unknown.alteeve.ca</span>. For this, I will create an initial configuration file called <span class="code">00_default.conf</span>.


<source lang="bash">
<source lang="bash">
openssl genrsa -des3 -out /etc/pki/CA/private/alteeve.com.key 2048
vim /etc/httpd/conf.d/00_default.conf
</source>
</source>
<source lang="text">
<source lang="text">
Generating RSA private key, 2048 bit long modulus
<VirtualHost *:80>
..................................+++
        ServerAdmin admin@alteeve.ca
.............................................................+++
        DocumentRoot /var/www/default/html
e is 65537 (0x10001)
        ServerName unknown.alteeve.ca
Enter pass phrase for /etc/pki/CA/private/alteeve.com.key:
        ErrorLog /var/www/default/logs/error.log
Verifying - Enter pass phrase for /etc/pki/CA/private/alteeve.com.key:
        CustomLog /var/www/default/logs/access.log common
</VirtualHost>
</source>
</source>


Now create a [[CSR]] (Certificate signing request) which we will send to the signing authority. Do not enter anything in the <span class="code">extra</span> section below.
Now we will do two kinds of checks; One for syntax and one to check the configuration of virtual host containers.
 
<source lang="bash">
apachectl -t
</source>
<source lang="text">
Syntax OK
</source>


{{note|1=The <span class="code">Common Name</span> must be the fully qualified domain name. In this example, I want to create a certificate for the domain <span class="code">https://alteeve.com</span>, so I will enter <span class="code">alteeve.com</span>. If you prefer to use a <span class="code">www.</span> prefix, include it. I will rewrite requests using the <span class="code">www.</span> prefix to not use it.}}
We no longer see the warning from before as we now have our first virtual host configured.


<source lang="bash">
<source lang="bash">
openssl req -new -key /etc/pki/CA/private/alteeve.com.key -out alteeve.com.csr
apachectl -S
</source>
</source>
<source lang="text">
<source lang="text">
Enter pass phrase for /etc/pki/CA/private/alteeve.com.key:
VirtualHost configuration:
You are about to be asked to enter information that will be incorporated
wildcard NameVirtualHosts and _default_ servers:
into your certificate request.
_default_:443          omiya.alteeve.ca (/etc/httpd/conf.d/ssl.conf:74)
What you are about to enter is what is called a Distinguished Name or a DN.
*:80                  is a NameVirtualHost
There are quite a few fields but you can leave some blank
        default server unknown.alteeve.ca (/etc/httpd/conf.d/00_default.conf:1)
For some fields there will be a default value,
        port 80 namevhost unknown.alteeve.ca (/etc/httpd/conf.d/00_default.conf:1)
If you enter '.', the field will be left blank.
Syntax OK
-----
</source>
Country Name (2 letter code) [XX]:CA
 
State or Province Name (full name) []:Ontario
We can now start the web server for the first time.
Locality Name (eg, city) [Default City]:Oakville
 
Organization Name (eg, company) [Default Company Ltd]:Alteeve's Niche
<source lang="bash">
Organizational Unit Name (eg, section) []:IT
/etc/init.d/httpd start
Common Name (eg, your name or your server's hostname) []:alteeve.com
</source>
Email Address []:admin@alteeve.com   
<source lang="text">
Starting httpd:                                            [  OK  ]
</source>
 
Perfect! Time to configure some real domains.
 
== Common Virtual Host Configurations ==
 
All domains on this server will be housed under either:
 
* <span class="code">/var/www/domain.tld/{cgi-bin,html,logs,temp}</span>
 
Or, for [[SSL]] encrypted domains;
 
* <span class="code">/var/www/ssl_domain.tld/{cgi-bin,html,logs,temp}</span>
 
The four directories found under the domain are used for hosting executable scripts (<span class="code">cgi-bin</span>), standard [[HTML]] websites or websites with in-line code like [[PHP]] (<span class="code">html</span>), log files (<span class="code">logs</span>) and an optional temporary directory used for staging files (<span class="code">temp</span>).
 
== Standard Virtual Hosts ==
 
This section covers the configuration on standard virtual host containers (using [[TCP]] port 80).
 
In this example, we will setup the domain <span class="code">http://mizu-bu.org</span>.
 
First, create the directories for the domain's files.


Please enter the following 'extra' attributes
<source lang="bash">
to be sent with your certificate request
mkdir -p /var/www/mizu-bu.org/{cgi-bin,html,logs,temp}
A challenge password []:
An optional company name []:
</source>
</source>


Test that the CSR file is ok.
Now create the virtual host container's configuration file. Note that in this example, it is a [http://www.mediawiki.org/ MediaWiki] website, so we will tell apache to look for <span class="code">index.php</span> files by default.


<source lang="bash">
<source lang="bash">
openssl req -noout -text -in /etc/pki/CA/alteeve.com.csr
vim /etc/httpd/conf.d/mizu-bu.org.conf
</source>
</source>
<source lang="text">
<source lang="text">
Certificate Request:
<VirtualHost *:80>
    Data:
ServerAdmin digimer@alteeve.ca
         Version: 0 (0x0)
 
        Subject: C=CA, ST=Ontario, L=Oakville, O=Alteeve's Niche, OU=IT, CN=alteeve.com/emailAddress=admin@alteeve.com
ServerName mizu-bu.org
        Subject Public Key Info:
         ServerAlias www.mizu-bu.org
            Public Key Algorithm: rsaEncryption
 
                Public-Key: (2048 bit)
DirectoryIndex index.html
                Modulus:
   
                    ...
DocumentRoot /var/www/mizu-bu.org/html/
                Exponent: 65537 (0x10001)
<Directory /var/www/mizu-bu.org/html>
        Attributes:
Options +Includes Indexes FollowSymLinks MultiViews
            a0:00
AllowOverride Options
    Signature Algorithm: sha1WithRSAEncryption
Order allow,deny
        ...
allow from all
</Directory>
 
ScriptAlias /cgi-bin/ /var/www/mizu-bu.org/cgi-bin/
<Directory "/var/www/mizu-bu.org/cgi-bin">
AllowOverride None
Options ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
</Directory>
 
ErrorLog /var/www/mizu-bu.org/logs/error.log
 
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel debug
 
CustomLog /var/www/mizu-bu.org/logs/access.log combined
ServerSignature On
</VirtualHost>
</source>
</source>


Copy the exact contents of the <span class="code">alteeve.com.csr</span> file and provide it to your signing authority as per their instructions. Once you complete their CSR form, they should email you a signed certificate and an intermediary certificate. At this point, the CSR file is no longer needed.
As before, test the syntax and virtual host configurations.
 
Save the signed certificate:


<source lang="bash">
<source lang="bash">
vim /etc/pki/CA/ssl_alteeve.com.crt
apachectl -S
</source>
</source>
<source lang="text">
<source lang="text">
-----BEGIN CERTIFICATE-----
VirtualHost configuration:
...
wildcard NameVirtualHosts and _default_ servers:
-----END CERTIFICATE-----
_default_:443          omiya.alteeve.ca (/etc/httpd/conf.d/ssl.conf:74)
*:80                  is a NameVirtualHost
        default server unknown.alteeve.ca (/etc/httpd/conf.d/00_default.conf:1)
        port 80 namevhost unknown.alteeve.ca (/etc/httpd/conf.d/00_default.conf:1)
        port 80 namevhost mizu-bu.org (/etc/httpd/conf.d/mizu-bu.org.conf:1)
Syntax OK
</source>
</source>


Save the intermediary certificate. Change the certificate name to that of your provider. If they provide you with this file, simply save it in the <span class="code">/etc/pki/CA/</span> directory.


<span class="code"></span>
<source lang="bash">
<source lang="bash">
vim /etc/pki/CA/RapidSSL_CA_bundle.pem
</source>
</source>
<source lang="text">
<source lang="text">
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
</source>
</source>


=== Creating An SSL Virtual Host ===
== SSL Virtual Hosts ==


Create a new virtual host container for the new SSL protected virtual host. We will leave the normal unencrypted virtual-host alone for now. Once we're done, we'll use it to capture and redirect <span class="code">http://</span> requests to their <span class="code">https://</span> equivalents. I make my virtual host directories writeable by my normal user account. Feel free to adapt this to your preferences.
SSL provides for secure client to server communications.


Setup the directories and then create a trivial <span class="code">index.html</span> file.
=== Per-Domain SSL Cert ===
 
This covers setting up an SSL certificate for one domain only.
 
==== Per-Domain SS - Creating The Signed Certificate ====
 
This section assumes you are using a 3rd party signing authority. Specifically, I use http://www.trustico.ca/ (resellers of http://RapidSSL.com and others). This is also for a domain-specific certificate. Wildcard certificates will differ.
 
First, create 2048bit private key. Note that this will require a pass-phrase, which you will need to enter whenever the Apache daemon <span class="code">httpd</span> daemon starts. If you do not want this, remove the <span class="code">-des3</span> switch.


<source lang="bash">
<source lang="bash">
mkdir ssl_alteeve.com/{cgi-bin,html,logs,temp} -p
cd /etc/pki/CA/private/
chown apache:digimer ssl_alteeve.com -R
openssl genrsa -des3 -out /etc/pki/CA/private/alteeve.ca.key 2048
chmod g+w ssl_alteeve.com -R
vim /var/www/ssl_alteeve.com/html/index.html
</source>
</source>
<source lang="apache">
<source lang="text">
<head>
Generating RSA private key, 2048 bit long modulus
        <title>AN!Wiki - SSL Test Server</title>
..................................+++
</head>
.............................................................+++
<body>
e is 65537 (0x10001)
        <h1>SSL Test</h1>
Enter pass phrase for /etc/pki/CA/private/alteeve.ca.key:
</body>
Verifying - Enter pass phrase for /etc/pki/CA/private/alteeve.ca.key:
</source>
</source>


Now setup the Apache2 config. I like to use the <span class="code">ssl_</span> prefix for encrypted domains.
Now create a [[CSR]] (Certificate signing request) which we will send to the signing authority. Do not enter anything in the <span class="code">extra</span> section below.


{{note|1=This example is for a MediaWiki virtual host with short URLs configured. You will want to adapt the values to suit your needs.}}
{{note|1=The <span class="code">Common Name</span> must be the fully qualified domain name. In this example, I want to create a certificate for the domain <span class="code">https://alteeve.ca</span>, so I will enter <span class="code">alteeve.ca</span>. If you prefer to use a <span class="code">www.</span> prefix, include it. I will rewrite requests using the <span class="code">www.</span> prefix to not use it.}}


<source lang="bash">
<source lang="bash">
vim /etc/httpd/conf.d/ssl_alteeve.com.conf
openssl req -new -key /etc/pki/CA/private/alteeve.ca.key -out alteeve.ca.csr
</source>
</source>
<source lang="apache">
<source lang="text">
<VirtualHost *:443>
Enter pass phrase for /etc/pki/CA/private/alteeve.ca.key:
        ServerAdmin digimer@alteeve.com
You are about to be asked to enter information that will be incorporated
 
into your certificate request.
        ServerName alteeve.com
What you are about to enter is what is called a Distinguished Name or a DN.
 
There are quite a few fields but you can leave some blank
        DirectoryIndex index.php index.html
For some fields there will be a default value,
 
If you enter '.', the field will be left blank.
        # We can haz security?
-----
        SSLEngine on
Country Name (2 letter code) [XX]:CA
        SSLProtocol all
State or Province Name (full name) []:Ontario
        SSLCACertificateFile /etc/pki/CA/RapidSSL_CA_bundle.pem
Locality Name (eg, city) [Default City]:Oakville
        SSLCertificateFile /etc/pki/CA/ssl_alteeve.com.crt
Organization Name (eg, company) [Default Company Ltd]:Alteeve's Niche
        SSLCertificateKeyFile /etc/pki/CA/private/alteeve.com.key
Organizational Unit Name (eg, section) []:IT
Common Name (eg, your name or your server's hostname) []:alteeve.ca
Email Address []:admin@alteeve.ca   


        DocumentRoot /var/www/ssl_alteeve.com/html/
Please enter the following 'extra' attributes
        Alias /w /var/www/ssl_alteeve.com/html/index.php
to be sent with your certificate request
        <Directory /var/www/ssl_alteeve.com/html>
A challenge password []:
                Options +Includes Indexes FollowSymLinks MultiViews
An optional company name []:
                AllowOverride All
</source>
                Order allow,deny
                allow from all
        </Directory>


        ScriptAlias /cgi-bin/ /var/www/ssl_alteeve.com/cgi-bin/
Test that the CSR file is ok.
        <Directory "/var/www/ssl_alteeve.com/cgi-bin">
                AllowOverride None
                Options ExecCGI -MultiViews +SymLinksIfOwnerMatch
                Order allow,deny
                Allow from all
        </Directory>


        ErrorLog /var/www/ssl_alteeve.com/logs/error.log
<source lang="bash">
        TransferLog /var/www/ssl_alteeve.com/logs/transfer.log
openssl req -noout -text -in /etc/pki/CA/alteeve.ca.csr
 
        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel debug
 
        CustomLog /var/www/ssl_alteeve.com/logs/access.log combined
        ServerSignature On
</VirtualHost>
</source>
</source>
==== Bad Identity Error ====
If you get an error about the server not providing identity information, you may have be loading images, CSS, javascript or similar using a URL from a remote domain with no SSL or badly configured SSL.
For example, on Firefox 4, you may see:
<source lang="text">
<source lang="text">
This web site does not supply identity information.
Certificate Request:
 
    Data:
Your connection to this site is only partially encrypted, and does not prevent eavesdropping.
        Version: 0 (0x0)
                                                                        [ More Information ]
        Subject: C=CA, ST=Ontario, L=Oakville, O=Alteeve's Niche, OU=IT, CN=alteeve.ca/emailAddress=admin@alteeve.ca
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    ...
                Exponent: 65537 (0x10001)
        Attributes:
            a0:00
    Signature Algorithm: sha1WithRSAEncryption
        ...
</source>
</source>


In my case, this turned out to be a problem where mediawiki was loading a Creative Commons logo from their server using <span class="code">http://</span> link to the icon. Once this was changed to <span class="code">https://</span> (in <span class="code">LocalSettings.php</span>), the error went away.
Copy the exact contents of the <span class="code">alteeve.ca.csr</span> file and provide it to your signing authority as per their instructions. Once you complete their CSR form, they should email you a signed certificate and an intermediary certificate. At this point, the CSR file is no longer needed.


=== Testing and Using the New Configuration ===
Save the signed certificate:
 
Test your new Apache configuration.


<source lang="bash">
<source lang="bash">
apachectl -t
vim /etc/pki/CA/ssl_alteeve.ca.crt
</source>
</source>
<source lang="text">
<source lang="text">
Syntax OK
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
</source>
</source>


Now restart Apache. Note that you will be asked to enter the pass-phrase you used when you created your private key.
Save the intermediary certificate. Change the certificate name to that of your provider. If they provide you with this file, simply save it in the <span class="code">/etc/pki/CA/</span> directory.


<source lang="bash">
<source lang="bash">
/etc/init.d/httpd restart
vim /etc/pki/CA/RapidSSL_CA_bundle.pem
</source>
</source>
<source lang="text">
<source lang="text">
Stopping httpd:                                            [  OK  ]
-----BEGIN CERTIFICATE-----
Starting httpd: Apache/2.2.15 mod_ssl/2.2.15 (Pass Phrase Dialog)
...
Some of your private key files are encrypted for security reasons.
-----END CERTIFICATE-----
In order to read them you have to provide the pass phrases.
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
</source>
 
=== Wildcard SSL Certificate ===
 
These certs work for any <span class="code">*.example.com</span> domain.


Server alteeve.com:443 (RSA)
==== Wildcard SSL - Creating The Signed Certificate ====
Enter pass phrase:


OK: Pass Phrase Dialog successful.
This section assumes you are using a 3rd party signing authority. Specifically, I use http://www.trustico.ca/ (resellers of http://RapidSSL.com and others). This is also for a domain-specific certificate. Wildcard certificates will differ.
                                                          [  OK  ]
</source>


{{warning|1=From now on, you will need to enter the pass-phrase to start Apache. Consider this when restarting your server and when deciding if you want the Apache server to start with your server. As my server is in a VM and it's underlying disk is also encrypted, I will enable it at boot time. I'll need to be watching the boot process anyway. This may not apply to you.}}
Unlike the per-domain SSL certificate, this one will ''not'' require a pass-phrase to decrypt.


Now make sure that you can still connect to your server on [[TCP]] port 80 (normal http port). The contents after the <span class="code">GET</span> request will obviously vary depending on your configuration:
First, create 2048bit private key.


<source lang="bash">
<source lang="bash">
telnet localhost 80
cd /etc/pki/CA/private/
openssl genrsa -out /etc/pki/CA/private/wildcard_alteeve.ca.key 2048
</source>
</source>
<source lang="text">
<source lang="text">
Trying ::1...
Generating RSA private key, 2048 bit long modulus
Connected to localhost.
..<snip>..+++
Escape character is '^]'.
..<snip>..+++
GET
e is 65537 (0x10001)
<head>
</source>
<title>Asakusa.alteeve.com</title>
 
</head>
Verify it was created:
<body>
 
Default - Requested domain not found
<syntaxhighlight lang="bash">
</body>
ls -lah /etc/pki/CA/private/wildcard_alteeve.ca.key
Connection closed by foreign host.
</syntaxhighlight>
<syntaxhighlight lang="text">
-rw-r--r-- 1 root root 1.7K Feb 26 15:40 /etc/pki/CA/private/wildcard_alteeve.ca.key
</syntaxhighlight>
 
Now create a [[CSR]] (Certificate signing request) which we will send to the signing authority. Do not enter anything in the <span class="code">extra</span> section below.
 
{{note|1=The <span class="code">Common Name</span> must be the short, fully qualified domain name with a leading <span class="code">*.</span> to make it a wildcard. In this example, I want to create a certificate domains under <span class="code">alteeve.ca</span>, so I will enter <span class="code">*.alteeve.ca</span>.}}
 
<source lang="bash">
openssl req -new -key /etc/pki/CA/private/wildcard_alteeve.ca.key -out wildcard_alteeve.ca.csr
</source>
<source lang="text">
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CA
State or Province Name (full name) []:Ontario
Locality Name (eg, city) [Default City]:Toronto
Organization Name (eg, company) [Default Company Ltd]:Alteeve's Niche! Inc.
Organizational Unit Name (eg, section) []:IT
Common Name (eg, your name or your server's hostname) []:*.alteeve.ca
Email Address []:admin@alteeve.ca
 
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
</source>
</source>


Now to check that the SSL port is listening properly. We can't use <span class="code">[[telnet]]</span> because of the SSL encryption. Instead we will use <span class="code">openssl</span>.
Check that it was generated.
 
<syntaxhighlight lang="bash">
ls -lah /etc/pki/CA/private/wildcard_alteeve.ca.csr
</syntaxhighlight>
<syntaxhighlight lang="text">
-rw-r--r-- 1 root root 1.1K Feb 26 16:19 /etc/pki/CA/private/wildcard_alteeve.ca.csr
</syntaxhighlight>
 
Test that the CSR file is ok.


<source lang="bash">
<source lang="bash">
openssl s_client -connect localhost:443 -state -debug
openssl req -noout -text -in /etc/pki/CA/private/wildcard_alteeve.ca.csr
</source>
</source>
<source lang="text">
<source lang="text">
CONNECTED(00000003)
Certificate Request:
SSL_connect:before/connect initialization
    Data:
write to 0x196a050 [0x1a0b3a0] (113 bytes => 113 (0x71))
        Version: 0 (0x0)
0000 - 16 03 01 00 6c 01 00 00-68 03 01 4d f8 f4 a4 f9  ....l...h..M....
        Subject: C=CA, ST=Ontario, L=Toronto, O=Alteeve's Niche! Inc., OU=IT, CN=*.alteeve.ca/emailAddress=admin@alteeve.ca
0010 - 07 b3 11 f8 3d ff 5d 80-ed 69 87 52 e2 60 80 57  ....=.]..i.R.`.W
        Subject Public Key Info:
0020 - 59 c7 83 4c ea 5b e5 37-06 e0 13 00 00 3a 00 39  Y..L.[.7.....:.9
            Public Key Algorithm: rsaEncryption
0030 - 00 38 00 88 00 87 00 35-00 84 00 16 00 13 00 0a  .8.....5........
                Public-Key: (2048 bit)
0040 - 00 33 00 32 00 9a 00 99-00 45 00 44 00 2f 00 96  .3.2.....E.D./..
                Modulus:
0050 - 00 41 00 05 00 04 00 15-00 12 00 09 00 14 00 11  .A..............
                    ...
0060 - 00 08 00 06 00 03 00 ff-02 01 00 00 04 00 23      ..............#
                Exponent: 65537 (0x10001)
0071 - <SPACES/NULS>
        Attributes:
SSL_connect:SSLv2/v3 write client hello A
            a0:00
read from 0x196a050 [0x1a10900] (7 bytes => 7 (0x7))
    Signature Algorithm: sha1WithRSAEncryption
0000 - 16 03 01 00 35 02                                ....5.
        ...
0007 - <SPACES/NULS>
</source>
read from 0x196a050 [0x1a1090a] (51 bytes => 51 (0x33))
 
0000 - 00 31 03 01 4d f8 f4 a4-7d 35 00 74 24 43 bc c9  .1..M...}5.t$C..
Copy the exact contents of the <span class="code">wildcard_alteeve.ca.csr</span> file and provide it to your signing authority as per their instructions. Once you complete their CSR form, they should email you a signed certificate and an intermediary certificate. At this point, the CSR file is no longer needed.
0010 - 84 5d fe e3 90 1a
 
Save the signed certificate:
 
<source lang="bash">
vim /etc/pki/CA/wildcard_ssl_alteeve.ca.crt
</source>
<source lang="text">
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
</source>
 
Save the intermediary certificate. Change the certificate name to that of your provider. If they provide you with this file, simply save it in the <span class="code">/etc/pki/CA/</span> directory.
 
<source lang="bash">
vim /etc/pki/CA/RapidSSL_CA_bundle.pem
</source>
<source lang="text">
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
</source>
 
==== Copying Wildcard to a new Server ==
read from 0x196a050 [0x1a10903] (5 bytes => 5 (0x5))
read from 0x196a050 [0x1a10903] (5 bytes => 5 (0x5))
0000 - 17 03 01 00 60                                   ....`
0000 - 16 03 01 02 0d                                   .....
read from 0x196a050 [0x1a10908] (96 bytes => 96 (0x60))
read from 0x196a050 [0x1a10908] (525 bytes => 525 (0x20D))
0000 - 46 4c 99 93 29 c9 ed 66-81 43 89 39 26 2b d1 b0   FL..)..f.C.9&+..
0000 - 0c 00 02 09 00 80 d6 7d-e4 40 cb bb dc 19 36 d6   .......}.@....6.
0010 - 19 73 eb 51 18 45 54 49-74 43 e0 92 1b f8 af f0   .s.Q.ETItC......
0010 - 93 d3 4a fd 0a d5 0c 84-d2 39 a4 5f 52 0b b8 81   ..J......9._R...
0020 - 0d e1 08 79 96 38 e1 5e-29 9d 66 9c 30 04 8e c4   ...y.8.^).f.0...
0020 - 74 cb 98 bc e9 51 84 9f-91 2e 63 9c 72 fb 13 b4   t....Q....c.r...
0030 - 10 83 49 7e 09 d7 8a ff-4b 11 f9 13 3e ac 77 73   ..I~....K...>.ws
0030 - b4 d7 17 7e 16 d5 5a c1-79 ba 42 0b 2a 29 fe 32   ...~..Z.y.B.*).2
0040 - e8 94 e3 f3 74 db 4e 5f-67 13 1d c4 3a 06 98 b3   ....t.N_g...:...
0040 - 4a 46 7a 63 5e 81 ff 59-01 37 7b ed dc fd 33 16   JFzc^..Y.7{...3.
0050 - da 20 41 3c ca 9a fb 3f-f3 d7 64 a1 e9 f4 0a 98   . A<...?..d.....
0050 - 8a 46 1a ad 3b 72 da e8-86 00 78 04 5b 07 a7 db  .F..;r....x.[...
<head>
0060 - ca 78 74 08 7d 15 10 ea-9f cc 9d dd 33 05 07 dd   .xt.}.......3...
<title>AN!Wiki - SSL Test Server</title>
0070 - 62 db 88 ae aa 74 7d e0-f4 d6 e2 bd 68 b0 e7 39  b....t}.....h..9
</head>
0080 - 3e 0f 24 21 8e b3 00 01-02 00 80 51 5c 13 33 38  >.$!.......Q\.38
<body>
0090 - 83 ef 76 6f 23 52 55 bf-23 ba 7f f0 a4 ca 35 01  ..vo#RU.#.....5.
<h1>SSL Test</h1>
00a0 - 9c 70 e1 61 b2 0d 7b 5c-1c 32 02 c1 ac 14 be e9  .p.a..{\.2......
</body>
00b0 - b9 7a 5d 11 9b 53 48 64-cd 12 b8 15 4c df cc 10  .z]..SHd....L...
read from 0x196a050 [0x1a10903] (5 bytes => 5 (0x5))
00c0 - 4e 2b e7 cd 3f 33 68 1a-60 cc f7 18 25 7c e5 ca  N+..?3h.`...%|..
0000 - 15 03 01                                          ...
00d0 - c8 cb 45 ba 2a 6d dc 84-5f 26 6f 9a a3 73 b9 7f  ..E.*m.._&o..s..
0005 - <SPACES/NULS>
00e0 - 02 cb 7b a7 ac 59 9f f3-6e c9 01 ed b9 35 99 49  ..{..Y..n....5.I
read from 0x196a050 [0x1a10908] (32 bytes => 32 (0x20))
00f0 - 37 77 68 65 ec e2 f7 17-03 e7 f5 f5 86 33 e6 6c  7whe.........3.l
0000 - 2e bb a7 d6 dc ce 6c 34-dc 2e 43 c7 89 02 a9 5c  ......l4..C....\
0100 - 06 3c 15 83 98 74 2e b9-83 31 11 01 00 20 6e 17   .<...t...1... n.
0010 - 3b 3e d0 43 1c ec fa c7-89 48 fd 76 58 82 ef 45  ;>.C.....H.vX..E
0110 - 3d 2d ec 3e 19 b2 9e 5b-37 38 3a 31 57 3d 0e c1  =-.>...[78:1W=..
SSL3 alert read:warning:close notify
0120 - 6b c4 b4 83 d9 6b f0 d3-44 db 9f 18 55 15 e1 09  k....k..D...U...
closed
0130 - 73 59 8c 46 3d a4 47 58-b1 71 a3 32 b5 06 26 8c  sY.F=.GX.q.2..&.
write to 0x196a050 [0x1a14e53] (37 bytes => 37 (0x25))
0140 - 27 88 9e 13 c8 12 5d 94-9b 24 54 10 aa 79 e5 b4  '.....]..$T..y..
0000 - 15 03 01 00 20 d8 6f 46-24 e9 fa 0c c9 9f aa 2d  .... .oF$......-
0150 - 43 f5 5e 4c 01 dc 02 aa-69 02 37 71 4e 26 1c 0b  C.^L....i.7qN&..
0010 - db 69 2a d8 fb 61 66 b0-23 23 f9 a4 ac 49 b7 e6   .i*..af.##...I..
0160 - 40 19 c9 95 4d af 93 35-07 7a ff b1 96 7f 03 ce  @...M..5.z......
0020 - 31 73 56 05 ed                                    1sV..
0170 - 7a eb a2 1c 97 6b d2 97-d2 0f 1a f5 b2 af fb 65  z....k.........e
SSL3 alert write:warning:close notify
0180 - 86 b9 e3 38 30 ba f5 02-d6 6b fc da 94 93 8b b3  ...80....k......
</source>
0190 - 96 b5 b7 58 dc 36 55 6d-e9 47 e5 4a 33 1d b9 d9  ...X.6Um.G.J3...
 
01a0 - ec 33 e8 fb 58 c8 74 13-ff dd 40 b7 35 56 63 03  .3..X.t...@.5Vc.
Perfect!
01b0 - 9f 16 2f 72 be 56 56 c3-15 3a c3 10 09 f0 9d f2  ../r.VV..:......
 
01c0 - 42 52 5a ce d6 db 61 0e-d0 e2 ac 2e 9e 04 30 8e  BRZ...a.......0.
=== Open Port 443 On The Firewall ===
01d0 - 0d d7 07 f9 3e 0a a8 3b-8d 11 5c 6e 21 47 28 2d  ....>..;..\n!G(-
 
01e0 - 28 31 a6 3d d0 e9 2e 7a-de 4a 00 2a a8 6f 5d 82  (1.=...z.J.*.o].
At this point, if you try to connect to the SSL virtual host remotely, you will fail because port 443 is not yet open.
01f0 - 45 df 3e 06 e3 11 e3 3c-b9 1e 34 b8 bd 60 fd a7  E.>....<..4..`..
 
0200 - a2 c1 c8 19 61 19 da 10-e4 c3 70 7e 5f            ....a.....p~_
Use your favourite program to open inbound TCP port 443. I like to directly edit the firewall's config.
SSL_connect:SSLv3 read server key exchange A
 
read from 0x196a050 [0x1a10903] (5 bytes => 5 (0x5))
<source lang="bash">
0000 - 16 03 01 00 04                                    .....
vim /etc/sysconfig/iptables
read from 0x196a050 [0x1a10908] (4 bytes => 4 (0x4))
</source>
0000 - 0e                                                .
<source lang="text">
0004 - <SPACES/NULS>
# Firewall configuration written by system-config-firewall
SSL_connect:SSLv3 read server done A
# Manual customization of this file is not recommended.
write to 0x196a050 [0x1a1add0] (139 bytes => 139 (0x8B))
*filter
0000 - 16 03 01 00 86 10 00 00-82 00 80 7f 9d d2 3b 68  ..............;h
:INPUT ACCEPT [0:0]
0010 - 49 c9 dd ed 4f 35 a0 70-3a 28 0f ce c1 5a 81 ce  I...O5.p:(...Z..
:FORWARD ACCEPT [0:0]
0020 - cd 46 c5 e5 a4 44 25 04-4e b4 48 d8 3b a6 d4 44  .F...D%.N.H.;..D
:OUTPUT ACCEPT [0:0]
0030 - 4e 9a dc 20 fa 52 9f eb-52 3b 3c 3e 34 dc ed 34  N.. .R..R;<>4..4
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
0040 - e5 b7 10 f9 6d 3a c0 84-64 bf b8 91 54 6c 37 1b  ....m:..d...Tl7.
-A INPUT -p icmp -j ACCEPT
0050 - eb 75 7a 95 aa e8 83 6f-e0 16 f2 af 77 0f 7a 0c  .uz....o....w.z.
-A INPUT -i lo -j ACCEPT
0060 - a8 82 27 a4 a5 f2 f0 1b-d2 6e 46 c4 ef 10 7c 39  ..'......nF...|9
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
0070 - 6c 87 74 ec 68 7e d5 9a-10 ab 10 03 75 a2 fb 4b  l.t.h~......u..K
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
0080 - 8c 49 4c da 64 49 bd 27-ba 51 a4                  .IL.dI.'.Q.
-A INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT
SSL_connect:SSLv3 write client key exchange A
-A INPUT -j REJECT --reject-with icmp-host-prohibited
write to 0x196a050 [0x1a1add0] (6 bytes => 6 (0x6))
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
0000 - 14 03 01 00 01 01                                ......
COMMIT
SSL_connect:SSLv3 write change cipher spec A
</source>
write to 0x196a050 [0x1a1add0] (53 bytes => 53 (0x35))
<source lang="bash">
0000 - 16 03 01 00 30 b4 8a 74-4d a4 bf b1 54 04 8a 25  ....0..tM...T..%
/etc/init.d/iptables restart
0010 - 24 f8 81 f1 64 9f 1f 6d-fb bd a7 4c 57 6a a5 63  $...d..m...LWj.c
</source>
0020 - fb 3a dd 8e e3 f9 38 f6-22 fd 7e 42 81 2e a2 41  .:....8.".~B...A
<source lang="text">
0030 - 1f 74 d1 27 02                                    .t.'.
iptables: Flushing firewall rules:                        [  OK  ]
SSL_connect:SSLv3 write finished A
iptables: Setting chains to policy ACCEPT: filter          [  OK  ]
SSL_connect:SSLv3 flush data
iptables: Unloading modules:                              [ OK  ]
read from 0x196a050 [0x1a10903] (5 bytes => 5 (0x5))
iptables: Applying firewall rules:                        [  OK  ]
0000 - 16 03 01 00 ca                                    .....
</source>
read from 0x196a050 [0x1a10908] (202 bytes => 202 (0xCA))
 
0000 - 04 00 00 c6 00 00 00 00-00 c0 6c f3 41 26 c8 6b  ..........l.A&.k
=== Browse to the New Virtual Host ===
0010 - 1e 9c 2e 78 af 75 b2 46-34 f4 30 c3 bd e4 ee 2f  ...x.u.F4.0..../
 
0020 - f6 28 37 f6 7c 55 3b c7-08 ad 1e 48 f1 83 9f 9a   .(7.|U;....H....
You should now be able to access the new SSL virtual host! Simply browse to <span class="code">https://alteeve.com</span> (replace with your domain).
0030 - d4 ef 9b 7d 5a 9c f7 5b-92 e9 2f ca c3 e5 44 c7  ...}Z..[../...D.
 
0040 - 7a c1 ed db 98 1a 18 bd-25 30 3c 50 ad 96 23 22  z.......%0<P..#"
[[Image:SSL_Test_Page_01.png|thumb|center|741px|Test SSL virtual host in Firefox 4.]]
0050 - 7e a1 b7 eb 1d b5 cc 69-2a 43 63 13 4f 21 90 32  ~......i*Cc.O!.2
 
0060 - 87 94 0b 6a 66 da 99 fa-45 79 cc 53 29 35 59 0d  ...jf...Ey.S)5Y.
Note the '<span class="code">alteeve.com</span>' to the left of the address bar showing that the site is encrypted and verified!
0070 - 02 93 c6 c6 af f3 52 79-b5 36 c0 a6 4d 22 9f af  ......Ry.6..M"..
 
0080 - 4a f2 86 b4 50 68 83 b1-ab a6 a6 ac 6e 4e 18 3d  J...Ph......nN.=
= PostgreSQL =
0090 - 80 a7 b4 85 77 06 69 60-fa b2 22 9a 79 14 c6 3e  ....w.i`..".y..>
 
00a0 - 3e 68 33 4e 1e a9 40 09-47 d0 02 97 8b ba 39 db  >h3N..@.G.....9.
We need to initialize the postgres core databases before we can start it for the first time.
00b0 - 2f b1 1c 2e 66 49 d3 bc-99 cc 56 4f 1d f4 c6 7b  /...fI....VO...{
 
00c0 - 58 3e 28 df b1 ce 2b 45-36 ca                    X>(...+E6.
<source lang="bash">
SSL_connect:SSLv3 read server session ticket A
service postgresql initdb
read from 0x196a050 [0x1a10903] (5 bytes => 5 (0x5))
</source>
0000 - 14 03 01 00 01                                    .....
<source lang="text">
read from 0x196a050 [0x1a10908] (1 bytes => 1 (0x1))
Initializing database:                                     [  OK  ]
0000 - 01                                                .
</source>
read from 0x196a050 [0x1a10903] (5 bytes => 5 (0x5))
 
0000 - 16 03 01 00 30                                    ....0
From now on, we can start PostgreSQL normally.
read from 0x196a050 [0x1a10908] (48 bytes => 48 (0x30))
 
0000 - c0 79 35 bf c6 1e 7e d4-04 cf 68 c7 9d f5 9f 42  .y5...~...h....B
<source lang="bash">
0010 - 03 91 5f 72 ae 5b ec a8-aa e7 af e8 f3 39 1b cd  .._r.[.......9..
/etc/init.d/postgresql restart
0020 - 13 05 56 f2 1b 28 c9 42-4b 67 88 48 20 c2 a5 06  ..V..(.BKg.H ...
</source>
SSL_connect:SSLv3 read finished A
<source lang="text">
---
Stopping postgresql service:                              [  OK  ]
Certificate chain
Starting postgresql service:                              [ OK  ]
0 s:/serialNumber=0TS5WzauQRJ7sc2b-hTGwK1yxSfEDphF/C=CA/O=alteeve.ca/OU=GT13908817/OU=See www.rapidssl.com/resources/cps (c)11/OU=Domain Control Validated - FreeSSL/CN=alteeve.ca
</source>
  i:/C=US/O=GeoTrust, Inc./CN=RapidSSL CA
 
1 s:/C=US/O=GeoTrust, Inc./CN=RapidSSL CA
Create the admin user called <span class="code">alteeve</span> which will own the databases we will create and use.
  i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
 
2 s:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
<source lang="bash">
  i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
su - postgres
---
createuser -S -d -R alteeve
Server certificate
psql template1
-----BEGIN CERTIFICATE-----
</source>
MIIEvjCCA6agAwIBAgIDAhUkMA0GCSqGSIb3DQEBBQUAMDwxCzAJBgNVBAYTAlVT
 
MRcwFQYDVQQKEw5HZW9UcnVzdCwgSW5jLjEUMBIGA1UEAxMLUmFwaWRTU0wgQ0Ew
At the shell, run the following:
HhcNMTEwNjE0MTIxOTAxWhcNMTEwNzE2MTU1NjE0WjCB2TEpMCcGA1UEBRMgMFRT
 
NVd6YXVRUko3c2MyYi1oVEd3SzF5eFNmRURwaEYxCzAJBgNVBAYTAkNBMRQwEgYD
<source lang="sql">
VQQKEwthbHRlZXZlLmNvbTETMBEGA1UECxMKR1QxMzkwODgxNzExMC8GA1UECxMo
ALTER USER alteeve WITH PASSWORD 'secret';
U2VlIHd3dy5yYXBpZHNzbC5jb20vcmVzb3VyY2VzL2NwcyAoYykxMTErMCkGA1UE
</source>
CxMiRG9tYWluIENvbnRyb2wgVmFsaWRhdGVkIC0gRnJlZVNTTDEUMBIGA1UEAxML
<source lang="text">
YWx0ZWV2ZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDHtXUD
ALTER ROLE
x6m1IbJ6m3CN8kRd4Bj0BVLGk9MXpTrHRgNo0QFTG+i400xWRrLKYzSILE97I0kH
</source>
7443XIqs14ib7aEBkLwy2EYwbYIzWeq1OCyKFuFj57o52Cr6imslRQvJTbjSvqk6
<source lang="sql">
4/9hYPmkmU4/wiULIQfGGx5jcS49MUKYAfSIuIAmt79bALFXhrTYcObs6pjhF0Wn
\q
/4Pgdm+KULsdy8WP9AGETlnDTShzcDnI2oVDuQeuVyYEJLLW1HwDr09yAI8g7SZ3
</source>
s79OAWKLYhsQFmWS9bta3INc8lbzYDQs72L07s8mbZtKXnQFdPsjhgdvz7BIbbot
 
iV0P4MABHJGvAF/zAgMBAAGjggEpMIIBJTAfBgNVHSMEGDAWgBRraT1qGEJK3Y8C
Tell PostgreSQL to require a password for the <span class="code">alteeve</span> user.
ZTn9NSSGeJEWMDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEG
 
CCsGAQUFBwMCMBYGA1UdEQQPMA2CC2FsdGVldmUuY29tMEMGA1UdHwQ8MDowOKA2
<source lang="bash">
oDSGMmh0dHA6Ly9yYXBpZHNzbC1jcmwuZ2VvdHJ1c3QuY29tL2NybHMvcmFwaWRz
vim /var/lib/pgsql/data/pg_hba.conf
c2wuY3JsMB0GA1UdDgQWBBShK06vVQh7NL50/FdB3ryP2UodyTAMBgNVHRMBAf8E
</source>
AjAAMEkGCCsGAQUFBwEBBD0wOzA5BggrBgEFBQcwAoYtaHR0cDovL3JhcGlkc3Ns
<source lang="diff">
LWFpYS5nZW90cnVzdC5jb20vcmFwaWRzc2wuY3J0MA0GCSqGSIb3DQEBBQUAA4IB
--- /var/lib/pgsql/data/pg_hba.conf.orig 2011-06-15 17:57:25.666509143 -0400
AQBmi2+o1dKEx4kx+6W64RFeL2dv3w08CxpLrNk47ikKTdkGmCwlClm7OQOwzTsG
+++ /var/lib/pgsql/data/pg_hba.conf 2011-06-15 17:58:54.077510393 -0400
kz5ZkM8GF3R3u82RNNBvuY9TV+0UML3pbASEtvAWnSmbsUf4hGRfAzbq4dYTl1tQ
@@ -65,6 +65,7 @@
ubJZzPjvIwGZkW5e6NB3VDhJGFjnDlQ1wDe1nnmy1MbZ/ycx1L8ErtMKkEu8NLxT
+LznTCK3s7yM10FE/OBQLpqsulzuiAP8DlMyqt2kJO6mfD3cnXqCC5+4keChEnej
lffQxJ7x19mZaIDor61o9RpfZgZ4yVb4NjcW+n0n3x2i2HyMW1Dbxv4G/5aG9R/k
# TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD
Nc7PQ2ZT2qFQtcBz7B70yCAT
+local   all        alteeve                          md5
-----END CERTIFICATE-----
subject=/serialNumber=0TS5WzauQRJ7sc2b-hTGwK1yxSfEDphF/C=CA/O=alteeve.ca/OU=GT13908817/OU=See www.rapidssl.com/resources/cps (c)11/OU=Domain Control Validated - FreeSSL/CN=alteeve.ca
# "local" is for Unix domain socket connections only
issuer=/C=US/O=GeoTrust, Inc./CN=RapidSSL CA
local  all        all                              ident
---
</source>
No client certificate CA names sent
 
---
Reload PostgreSQL's configuration.
SSL handshake has read 3984 bytes and written 311 bytes
 
---
<source lang="bash">
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
/etc/init.d/postgresql reload
Server public key is 2048 bit
</source>
Secure Renegotiation IS supported
 
Compression: zlib compression
Now create a Database that is owned by the <span class="code">alteeve</span> user, then connect to it to make sure we're asked for a password.
Expansion: zlib compression
 
SSL-Session:
<source lang="bash">
    Protocol  : TLSv1
su postgres -c "createdb an_wiki -O alteeve"
    Cipher    : DHE-RSA-AES256-SHA
psql an_wiki -U alteeve
    Session-ID: 2880725EB8BDD73F469C17BCA54DF373DFE8EDE3D52A1C8F5E0A5919694FB111
</source>
    Session-ID-ctx:
<source lang="text">
    Master-Key: F329DEA0DF39FF181ACFBCA69BEC417D7CAA4399D73229A1D912CC8236A858FD099B834F5B32C9BF979C4B5948196FC9
Password for user alteeve:
    Key-Arg  : None
psql (8.4.7)
    Krb5 Principal: None
Type "help" for help.
    PSK identity: None
 
    PSK identity hint: None
an_wiki=>
    TLS session ticket:
</source>
    0000 - 6c f3 41 26 c8 6b 1e 9c-2e 78 af 75 b2 46 34 f4  l.A&.k...x.u.F4.
 
    0010 - 30 c3 bd e4 ee 2f f6 28-37 f6 7c 55 3b c7 08 ad  0..../.(7.|U;...
Now load a database from a backup file.
    0020 - 1e 48 f1 83 9f 9a d4 ef-9b 7d 5a 9c f7 5b 92 e9  .H.......}Z..[..
 
    0030 - 2f ca c3 e5 44 c7 7a c1-ed db 98 1a 18 bd 25 30  /...D.z.......%0
<source lang="bash">
    0040 - 3c 50 ad 96 23 22 7e a1-b7 eb 1d b5 cc 69 2a 43  <P..#"~......i*C
psql an_wiki -U alteeve -f /var/www/ssl_alteeve.com/temp/an_wiki_3.out
    0050 - 63 13 4f 21 90 32 87 94-0b 6a 66 da 99 fa 45 79  c.O!.2...jf...Ey
</source>
    0060 - cc 53 29 35 59 0d 02 93-c6 c6 af f3 52 79 b5 36  .S)5Y.......Ry.6
<source lang="text">
    0070 - c0 a6 4d 22 9f af 4a f2-86 b4 50 68 83 b1 ab a6  ..M"..J...Ph....
Password for user alteeve:
    0080 - a6 ac 6e 4e 18 3d 80 a7-b4 85 77 06 69 60 fa b2  ..nN.=....w.i`..
SET
    0090 - 22 9a 79 14 c6 3e 3e 68-33 4e 1e a9 40 09 47 d0  ".y..>>h3N..@.G.
SET
    00a0 - 02 97 8b ba 39 db 2f b1-1c 2e 66 49 d3 bc 99 cc  ....9./...fI....
SET
    00b0 - 56 4f 1d f4 c6 7b 58 3e-28 df b1 ce 2b 45 36 ca  VO...{X>(...+E6.
SET
SET
CREATE SCHEMA
ALTER SCHEMA
CREATE LANGUAGE
psql:/var/www/ssl_alteeve.com/temp/an_wiki_3.out:27: ERROR:  must be member of role "postgres"
SET
CREATE FUNCTION
ALTER FUNCTION
CREATE FUNCTION
ALTER FUNCTION
CREATE FUNCTION
ALTER FUNCTION
CREATE FUNCTION
ALTER FUNCTION
SET
SET
CREATE TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
setval
--------
      1
(1 row)


CREATE TABLE
    Compression: 1 (zlib compression)
ALTER TABLE
    Start Time: 1308161188
CREATE TABLE
    Timeout  : 300 (sec)
ALTER TABLE
    Verify return code: 0 (ok)
CREATE TABLE
---
ALTER TABLE
GET
CREATE TABLE
write to 0x196a050 [0x1a14e56] (74 bytes => 74 (0x4A))
ALTER TABLE
0000 - 17 03 01 00 20 8a 4c 57-8c b9 d5 d4 c6 1b 56 ce  .... .LW......V.
CREATE SEQUENCE
0010 - 93 b5 78 6b 5f 0e c5 a2-39 2a f9 7a 20 7d 68 85  ..xk_...9*.z }h.
ALTER TABLE
0020 - af 52 e3 5f fc 17 03 01-00 20 c6 c4 19 74 61 64  .R._..... ...tad
setval
0030 - 42 59 e0 52 3f 42 44 53-8b c9 40 69 1c 3d 9b 7f  BY.R?BDS..@i.=..
--------
0040 - aa e8 8f a4 5c de c9 d4-0a a4                    ....\.....
      8
read from 0x196a050 [0x1a10903] (5 bytes => 5 (0x5))
(1 row)
0000 - 17 03 01 00 60                                    ....`
 
read from 0x196a050 [0x1a10908] (96 bytes => 96 (0x60))
CREATE TABLE
0000 - 46 4c 99 93 29 c9 ed 66-81 43 89 39 26 2b d1 b0  FL..)..f.C.9&+..
ALTER TABLE
0010 - 19 73 eb 51 18 45 54 49-74 43 e0 92 1b f8 af f0  .s.Q.ETItC......
CREATE TABLE
0020 - 0d e1 08 79 96 38 e1 5e-29 9d 66 9c 30 04 8e c4  ...y.8.^).f.0...
ALTER TABLE
0030 - 10 83 49 7e 09 d7 8a ff-4b 11 f9 13 3e ac 77 73  ..I~....K...>.ws
CREATE TABLE
0040 - e8 94 e3 f3 74 db 4e 5f-67 13 1d c4 3a 06 98 b3  ....t.N_g...:...
ALTER TABLE
0050 - da 20 41 3c ca 9a fb 3f-f3 d7 64 a1 e9 f4 0a 98  . A<...?..d.....
CREATE TABLE
<head>
ALTER TABLE
<title>AN!Wiki - SSL Test Server</title>
CREATE TABLE
</head>
ALTER TABLE
<body>
CREATE SEQUENCE
<h1>SSL Test</h1>
ALTER TABLE
</body>
setval
read from 0x196a050 [0x1a10903] (5 bytes => 5 (0x5))
--------
0000 - 15 03 01                                          ...
  2500
0005 - <SPACES/NULS>
(1 row)
read from 0x196a050 [0x1a10908] (32 bytes => 32 (0x20))
0000 - 2e bb a7 d6 dc ce 6c 34-dc 2e 43 c7 89 02 a9 5c  ......l4..C....\
0010 - 3b 3e d0 43 1c ec fa c7-89 48 fd 76 58 82 ef 45  ;>.C.....H.vX..E
SSL3 alert read:warning:close notify
closed
write to 0x196a050 [0x1a14e53] (37 bytes => 37 (0x25))
0000 - 15 03 01 00 20 d8 6f 46-24 e9 fa 0c c9 9f aa 2d  .... .oF$......-
0010 - db 69 2a d8 fb 61 66 b0-23 23 f9 a4 ac 49 b7 e6  .i*..af.##...I..
0020 - 31 73 56 05 ed                                    1sV..
SSL3 alert write:warning:close notify
</source>
 
Perfect!
 
=== Open Port 443 On The Firewall ===


CREATE TABLE
At this point, if you try to connect to the SSL virtual host remotely, you will fail because port 443 is not yet open.
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
setval
--------
  4416
(1 row)


CREATE TABLE
Use your favourite program to open inbound TCP port 443. I like to directly edit the firewall's config.
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
setval
--------
  3465
(1 row)


CREATE TABLE
<source lang="bash">
ALTER TABLE
vim /etc/sysconfig/iptables
CREATE TABLE
</source>
ALTER TABLE
<source lang="text">
CREATE TABLE
# Firewall configuration written by system-config-firewall
ALTER TABLE
# Manual customization of this file is not recommended.
CREATE SEQUENCE
*filter
ALTER TABLE
:INPUT ACCEPT [0:0]
setval
:FORWARD ACCEPT [0:0]
--------
:OUTPUT ACCEPT [0:0]
    34
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
(1 row)
-A INPUT -p icmp -j ACCEPT
 
-A INPUT -i lo -j ACCEPT
CREATE TABLE
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
ALTER TABLE
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
CREATE TABLE
-A INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT
ALTER TABLE
-A INPUT -j REJECT --reject-with icmp-host-prohibited
CREATE TABLE
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
ALTER TABLE
COMMIT
CREATE SEQUENCE
</source>
ALTER TABLE
<source lang="bash">
  setval
/etc/init.d/iptables restart
--------
</source>
    957
<source lang="text">
(1 row)
iptables: Flushing firewall rules:                        [  OK  ]
iptables: Setting chains to policy ACCEPT: filter          [  OK  ]
iptables: Unloading modules:                              [  OK  ]
iptables: Applying firewall rules:                        [  OK ]
</source>
 
=== Browse to the New Virtual Host ===
 
You should now be able to access the new SSL virtual host! Simply browse to <span class="code">https://alteeve.ca</span> (replace with your domain).


CREATE TABLE
[[Image:SSL_Test_Page_01.png|thumb|center|741px|Test SSL virtual host in Firefox 4.]]
ALTER TABLE
 
CREATE TABLE
Note the '<span class="code">alteeve.ca</span>' to the left of the address bar showing that the site is encrypted and verified!
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
setval
--------
      1
(1 row)


CREATE TABLE
== Common apachectl -t Configuration Problems ==
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
setval
--------
  3274
(1 row)


CREATE TABLE
=== httpd: apr_sockaddr_info_get() failed for <domain> ===
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
setval
--------
  3547
(1 row)


CREATE TABLE
Make sure that the hostname for the server resolves to an IP address. This is done by ensuring that the name returned by <span class="code">hostname</span> has a [[DNS]] entry or has an entry in the <span class="code">/etc/hosts</span> file.
ALTER TABLE
 
CREATE TABLE
=== [warn] NameVirtualHost *:80 has no VirtualHosts ===
ALTER TABLE
 
CREATE SEQUENCE
This will be shown when no virtual host containers have been configured ye.
ALTER TABLE
 
setval
= PostgreSQL =
--------
  3513
(1 row)


CREATE TABLE
We need to initialize the postgres core databases before we can start it for the first time.
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
setval
--------
      1
(1 row)


CREATE TABLE
<source lang="bash">
ALTER TABLE
/etc/init.d/postgresql-9.4 initdb
CREATE TABLE
</source>
ALTER TABLE
<source lang="text">
CREATE TABLE
Initializing database:                                    [  OK  ]
ALTER TABLE
</source>
CREATE TABLE
 
ALTER TABLE
From now on, we can start PostgreSQL normally.
CREATE TABLE
 
ALTER TABLE
<source lang="bash">
CREATE TABLE
/etc/init.d/postgresql-9.4 restart
ALTER TABLE
</source>
CREATE TABLE
<source lang="text">
ALTER TABLE
Stopping postgresql-9.4 service:                          [  OK  ]
CREATE TABLE
Starting postgresql-9.4 service:                          [  OK  ]
ALTER TABLE
</source>
ALTER TABLE
 
ALTER TABLE
Create the admin user called <span class="code">alteeve</span> which will own the databases we will create and use.
ALTER TABLE
 
ALTER TABLE
<source lang="bash">
ALTER TABLE
su - postgres
ALTER TABLE
createuser -S -d -R alteeve
ALTER TABLE
psql template1
ALTER TABLE
</source>
ALTER TABLE
 
ALTER TABLE
At the shell, run the following:
ALTER TABLE
 
ALTER TABLE
{{note|1=If your password has a single-quote in it, escape it with <span class="code">''</span> (ie: <span class="code">ALTER USER alteeve WITH PASSWORD 'someone''s secret password';</span>).}}
ALTER TABLE
 
ALTER TABLE
<source lang="sql">
ALTER TABLE
ALTER USER alteeve WITH PASSWORD 'secret';
ALTER TABLE
</source>
ALTER TABLE
<source lang="text">
ALTER TABLE
ALTER ROLE
ALTER TABLE
</source>
ALTER TABLE
<source lang="sql">
ALTER TABLE
\q
ALTER TABLE
</source>
ALTER TABLE
 
ALTER TABLE
Tell PostgreSQL to require a password for all local and incoming connections. Also enable access to the database from the local network.
ALTER TABLE
 
CREATE INDEX
<source lang="bash">
CREATE INDEX
vim /var/lib/pgsql/9.4/data/pg_hba.conf
CREATE INDEX
</source>
CREATE INDEX
<source lang="diff">
CREATE INDEX
# TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD
CREATE INDEX
host    all        all        10.222.0.0/16        md5
CREATE INDEX
 
CREATE INDEX
# "local" is for Unix domain socket connections only
CREATE INDEX
local  all        all                              md5
CREATE INDEX
# IPv4 local connections:
CREATE INDEX
host    all        all        127.0.0.1/32          md5
CREATE INDEX
# IPv6 local connections:
CREATE INDEX
host    all        all        ::1/128              md5
CREATE INDEX
</source>
CREATE INDEX
 
CREATE INDEX
Reload PostgreSQL's configuration.
CREATE INDEX
 
CREATE INDEX
<source lang="bash">
CREATE INDEX
/etc/init.d/postgresql-9.4 reload
CREATE INDEX
</source>
CREATE INDEX
 
CREATE INDEX
Now create a Database that is owned by the <span class="code">alteeve</span> user, then connect to it to make sure we're asked for a password.
CREATE INDEX
 
CREATE INDEX
<source lang="bash">
CREATE INDEX
su postgres -c "createdb an_wiki -O alteeve"
CREATE INDEX
psql an_wiki -U alteeve
CREATE INDEX
</source>
CREATE INDEX
<source lang="text">
CREATE INDEX
Password for user alteeve:
CREATE INDEX
psql (9.4.1)
CREATE INDEX
Type "help" for help.
CREATE INDEX
 
CREATE INDEX
an_wiki=>
CREATE INDEX
</source>
CREATE INDEX
 
CREATE INDEX
Now load a database from a backup file.
CREATE INDEX
 
CREATE INDEX
<source lang="bash">
CREATE INDEX
psql an_wiki -U alteeve -f /var/www/ssl_alteeve.ca/temp/an_wiki_3.out
CREATE INDEX
</source>
CREATE INDEX
<source lang="text">
CREATE INDEX
Password for user alteeve:
CREATE INDEX
</source>
CREATE INDEX
<source lang="text">
CREATE INDEX
SET
CREATE INDEX
SET
CREATE INDEX
SET
CREATE INDEX
SET
CREATE INDEX
SET
CREATE INDEX
SET
CREATE INDEX
CREATE SCHEMA
CREATE INDEX
ALTER SCHEMA
CREATE INDEX
psql:/root/an_wiki_2.out:25: ERROR:  language "plpgsql" already exists
CREATE INDEX
ALTER LANGUAGE
CREATE INDEX
SET
CREATE INDEX
CREATE TYPE
CREATE INDEX
ALTER TYPE
CREATE INDEX
CREATE FUNCTION
CREATE INDEX
ALTER FUNCTION
CREATE INDEX
CREATE FUNCTION
CREATE INDEX
ALTER FUNCTION
CREATE INDEX
CREATE FUNCTION
CREATE INDEX
ALTER FUNCTION
CREATE INDEX
CREATE FUNCTION
CREATE INDEX
ALTER FUNCTION
CREATE INDEX
SET
CREATE INDEX
SET
CREATE INDEX
CREATE TABLE
CREATE INDEX
ALTER TABLE
CREATE INDEX
CREATE SEQUENCE
CREATE INDEX
ALTER TABLE
CREATE INDEX
setval
CREATE INDEX
--------
CREATE INDEX
    39
CREATE INDEX
(1 row)
CREATE INDEX
 
CREATE INDEX
CREATE TABLE
CREATE INDEX
ALTER TABLE
CREATE INDEX
CREATE TABLE
CREATE INDEX
ALTER TABLE
CREATE INDEX
CREATE TABLE
CREATE TRIGGER
ALTER TABLE
CREATE TRIGGER
CREATE TABLE
CREATE TRIGGER
ALTER TABLE
CREATE TABLE
ALTER TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
ALTER TABLE
setval
--------
    28
(1 row)
CREATE TABLE
ALTER TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
ALTER TABLE
setval
--------
  2507
(1 row)
CREATE TABLE
ALTER TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
ALTER TABLE
setval
--------
  14274
(1 row)
CREATE TABLE
ALTER TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
ALTER TABLE
setval
--------
  6586
(1 row)
CREATE TABLE
ALTER TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
ALTER TABLE
setval
--------
    50
(1 row)
CREATE TABLE
ALTER TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
ALTER TABLE
ALTER TABLE
setval
REVOKE
--------
REVOKE
  1563
GRANT
(1 row)
GRANT
</source>


Voila!
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
setval
--------
      1
(1 row)


== Media Wiki Problem ==
CREATE TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
setval
--------
  6335
(1 row)


If you moved a MediaWiki DB and it generated an error like this in the log file:
CREATE TABLE
 
ALTER TABLE
<source lang="text">
CREATE TABLE
[Wed Jun 15 21:37:20 2011] [error] [client 206.108.5.162] PHP Warning: pg_query(): Query failed: ERROR:  relation "objectcache" does not exist\nLINE 1: ...ECT /* SqlBagOStuff::get  */  value,exptime  FROM objectcach...\n
ALTER TABLE
                                                            ^ in /var/www/ssl_alteeve.com/html/includes/db/DatabasePostgres.php on line 584
CREATE TABLE
[Wed Jun 15 21:37:20 2011] [error] [client 206.108.5.162] PHP Warning:  pg_query(): Query failed: ERROR:  relation "l10n_cache" does not exist\nLINE 1: ... LCStore_DB::get 206.108.5.162 */  lc_value  FROM l10n_cache...\n
ALTER TABLE
                                                            ^ in /var/www/ssl_alteeve.com/html/includes/db/DatabasePostgres.php on line 584
CREATE TABLE
</source>
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
  setval
--------
  6741
(1 row)


The fix is to run:
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
setval
--------
  6663
(1 row)


<source lang="sql">
CREATE TABLE
ALTER DATABASE an_wiki SET search_path=mediawiki;
ALTER TABLE
</source>
CREATE TABLE
 
ALTER TABLE
Of course, replace <span class="code">an_wiki</span> with the name of your wiki database.
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
setval
--------
      1
(1 row)


= MySQL =
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
setval
--------
    20
(1 row)


Start MySQL for the first time:
CREATE TABLE
 
ALTER TABLE
<source lang="bash">
CREATE TABLE
/etc/init.d/mysqld start
ALTER TABLE
</source>
CREATE TABLE
<source lang="text">
ALTER TABLE
Initializing MySQL database:  Installing MySQL system tables...
CREATE TABLE
OK
ALTER TABLE
Filling help tables...
CREATE TABLE
OK
ALTER TABLE
 
CREATE TABLE
To start mysqld at boot time you have to copy
ALTER TABLE
support-files/mysql.server to the right place for your system
CREATE TABLE
 
ALTER TABLE
PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER !
COPY 137
To do so, start the server, then issue the following commands:
COPY 2
 
COPY 9
/usr/bin/mysqladmin -u root password 'new-password'
COPY 0
/usr/bin/mysqladmin -u root -h asakusa.alteeve.com password 'new-password'
COPY 0
 
COPY 2372
Alternatively you can run:
COPY 28
/usr/bin/mysql_secure_installation
COPY 0
 
COPY 742
which will also give you the option of removing the test
COPY 872
databases and anonymous user created by default.  This is
COPY 92
strongly recommended for production servers.
COPY 21
 
COPY 0
See the manual for more instructions.
COPY 0
 
COPY 6626
You can start the MySQL daemon with:
COPY 0
cd /usr ; /usr/bin/mysqld_safe &
COPY 2
 
COPY 6586
You can test the MySQL daemon with mysql-test-run.pl
COPY 0
cd /usr/mysql-test ; perl mysql-test-run.pl
COPY 2
 
COPY 16
Please report any problems with the /usr/bin/mysqlbug script!
COPY 44
 
COPY 28
                                                          [  OK  ]
COPY 51
Starting mysqld:                                          [  OK  ]
COPY 104959
</source>
COPY 254
 
COPY 1497
Secure the server.
COPY 0
 
COPY 0
<source lang="bash">
COPY 6335
mysql_secure_installation
COPY 3901
</source>
COPY 0
<source lang="text">
COPY 0
NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MySQL
COPY 0
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!
COPY 0
 
COPY 0
 
COPY 385
In order to log into MySQL to secure it, we'll need the current
COPY 124
password for the root user.  If you've just installed MySQL, and
COPY 6525
you haven't set the root password yet, the password will be blank,
COPY 1
so you should just press enter here.
COPY 0
 
COPY 1276
Enter current password for root (enter for none):
COPY 0
OK, successfully used password, moving on...
COPY 0
 
COPY 1
Setting the root password ensures that nobody can log into the MySQL
COPY 7
root user without the proper authorisation.
COPY 0
 
COPY 2
Set root password? [Y/n] y
COPY 0
New password:
COPY 29
Re-enter new password:
COPY 0
Password updated successfully!
COPY 12
Reloading privilege tables..
ALTER TABLE
... Success!
ALTER TABLE
 
ALTER TABLE
 
ALTER TABLE
By default, a MySQL installation has an anonymous user, allowing anyone
ALTER TABLE
to log into MySQL without having to have a user account created for
ALTER TABLE
them.  This is intended only for testing, and to make the installation
ALTER TABLE
go a bit smoother.  You should remove them before moving into a
ALTER TABLE
production environment.
ALTER TABLE
 
ALTER TABLE
Remove anonymous users? [Y/n] y
ALTER TABLE
... Success!
ALTER TABLE
 
ALTER TABLE
Normally, root should only be allowed to connect from 'localhost'.  This
ALTER TABLE
ensures that someone cannot guess at the root password from the network.
ALTER TABLE
 
ALTER TABLE
Disallow root login remotely? [Y/n] 
ALTER TABLE
... Success!
ALTER TABLE
 
ALTER TABLE
By default, MySQL comes with a database named 'test' that anyone can
ALTER TABLE
access.  This is also intended only for testing, and should be removed
ALTER TABLE
before moving into a production environment.
ALTER TABLE
 
ALTER TABLE
Remove test database and access to it? [Y/n]
ALTER TABLE
- Dropping test database...
ALTER TABLE
... Success!
ALTER TABLE
- Removing privileges on test database...
ALTER TABLE
... Success!
CREATE INDEX
 
CREATE INDEX
Reloading the privilege tables will ensure that all changes made so far
CREATE INDEX
will take effect immediately.
CREATE INDEX
 
CREATE INDEX
Reload privilege tables now? [Y/n]
CREATE INDEX
... Success!
CREATE INDEX
 
CREATE INDEX
Cleaning up...
CREATE INDEX
 
CREATE INDEX
 
CREATE INDEX
 
CREATE INDEX
All done!  If you've completed all of the above steps, your MySQL
CREATE INDEX
installation should now be secure.
CREATE INDEX
 
CREATE INDEX
Thanks for using MySQL!
CREATE INDEX
</source>
CREATE INDEX
 
CREATE INDEX
= BIND =
CREATE INDEX
 
CREATE INDEX
{{note|1=This is not meant to cover creating the actual zone files for DNS. It's goal is to setup BIND on your [[EL6]] server only.}}
CREATE INDEX
 
CREATE INDEX
This is the BIND named server that handles DNS resolution. It will be setup in two parts; The global options and then the zones file.
CREATE INDEX
 
CREATE INDEX
== Install bind ==
CREATE INDEX
 
CREATE INDEX
<source lang="bash">
CREATE INDEX
yum install bind bind-libs bind-utils
CREATE INDEX
</source>
CREATE INDEX
 
CREATE INDEX
== Global Configuration ==
CREATE INDEX
 
CREATE INDEX
Edit the main configuration file, making a backup first.
CREATE INDEX
 
CREATE INDEX
<source lang="bash">
CREATE INDEX
cp /etc/named.conf /etc/named.conf.orig
CREATE INDEX
vim /etc/named.conf
CREATE INDEX
</source>
CREATE INDEX
 
CREATE INDEX
Enable queries on any interface and answer queries for any domain, not just ours. Edit or add the following;
CREATE INDEX
 
CREATE INDEX
<source lang="dot">
CREATE INDEX
        listen-on port 53      { any; };
CREATE INDEX
        allow-query            { localhost; };
CREATE INDEX
        allow-query-cache      { any; };
CREATE INDEX
</source>
CREATE INDEX
 
CREATE INDEX
For now, we're going to disable DNSSEC. Make the following changes;
CREATE INDEX
 
CREATE INDEX
<source lang="dot">
CREATE INDEX
        dnssec-enable          no;
CREATE INDEX
        dnssec-validation      no;
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE TRIGGER
CREATE TRIGGER
CREATE TRIGGER
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
psql:/root/an_wiki_2.out:145782: WARNING:  no privileges could be revoked for "public"
REVOKE
psql:/root/an_wiki_2.out:145783: WARNING:  no privileges could be revoked for "public"
REVOKE
psql:/root/an_wiki_2.out:145784: WARNING:  no privileges were granted for "public"
GRANT
psql:/root/an_wiki_2.out:145785: WARNING:  no privileges were granted for "public"
GRANT
</source>
</source>


Now tell bind where to look for a domain name's IP when we don't know. Add;
Voila!
 
== Media Wiki Problem ==
 
If you moved a MediaWiki DB and it generated an error like this in the log file:


<source lang="dot">
<source lang="text">
        forwarders {
[Wed Jun 15 21:37:20 2011] [error] [client 206.108.5.162] PHP Warning:  pg_query(): Query failed: ERROR:  relation "objectcache" does not exist\nLINE 1: ...ECT /* SqlBagOStuff::get  */  value,exptime  FROM objectcach...\n
                // These are Google's open DNS servers
                                                            ^ in /var/www/ssl_alteeve.ca/html/includes/db/DatabasePostgres.php on line 584
                8.8.8.8;
[Wed Jun 15 21:37:20 2011] [error] [client 206.108.5.162] PHP Warning:  pg_query(): Query failed: ERROR:  relation "l10n_cache" does not exist\nLINE 1: ... LCStore_DB::get 206.108.5.162 */  lc_value  FROM l10n_cache...\n
                8.8.4.4;
                                                            ^ in /var/www/ssl_alteeve.ca/html/includes/db/DatabasePostgres.php on line 584
        };
</source>
</source>


This server will have a slave, and we want to notify that slave when a record changes. Add;
The fix is to run:


<source lang="dot">
<source lang="sql">
        notify                  yes;
ALTER DATABASE an_wiki SET search_path=mediawiki;
</source>
</source>


Done. I like to clean up the file to put the variables in line with one another. With this in mind, let's look at the changes as a unified <span class="code">diff</span>;
Of course, replace <span class="code">an_wiki</span> with the name of your wiki database.
 
= MySQL =
 
Start MySQL for the first time:


<source lang="bash">
<source lang="bash">
diff -u /etc/named.conf.orig /etc/named.conf
/etc/init.d/mysqld start
</source>
<source lang="diff">
--- /etc/named.conf.orig 2012-02-05 00:54:48.434068501 -0500
+++ /etc/named.conf 2012-02-05 13:45:16.484083319 -0500
@@ -8,18 +8,26 @@
//
options {
- listen-on port 53 { 127.0.0.1; };
- listen-on-v6 port 53 { ::1; };
- directory "/var/named";
- dump-file "/var/named/data/cache_dump.db";
-        statistics-file "/var/named/data/named_stats.txt";
-        memstatistics-file "/var/named/data/named_mem_stats.txt";
- allow-query    { localhost; };
- recursion yes;
-
- dnssec-enable yes;
- dnssec-validation yes;
- dnssec-lookaside auto;
+ listen-on port 53 { any; };
+ listen-on-v6 port 53 { ::1; };
+ directory "/var/named";
+ dump-file "/var/named/data/cache_dump.db";
+        statistics-file "/var/named/data/named_stats.txt";
+        memstatistics-file "/var/named/data/named_mem_stats.txt";
+ allow-query { any; };
+ allow-query-cache { any; };
+ recursion yes;
+ notify yes;
+
+ dnssec-enable no;
+ dnssec-validation no;
+ dnssec-lookaside auto;
+
+ forwarders {
+ // These are Google's open DNS servers
+ 8.8.8.8;
+ 8.8.4.4;
+ };
/* Path to ISC DLV key */
bindkeys-file "/etc/named.iscdlv.key";
</source>
</source>
<source lang="text">
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 asakusa.alteeve.ca password 'new-password'
Alternatively you can run:
/usr/bin/mysql_secure_installation
which will also give you the option of removing the test
databases and anonymous user created by default.  This is
strongly recommended for production servers.
See the manual for more instructions.


== Adding Zones ==
You can start the MySQL daemon with:
cd /usr ; /usr/bin/mysqld_safe &


This is where we tell BIND which zones we have SOA for. This includes the pointers to the actual files on disk with each domain's information.
You can test the MySQL daemon with mysql-test-run.pl
cd /usr/mysql-test ; perl mysql-test-run.pl


Backup then edit the zones file.
Please report any problems with the /usr/bin/mysqlbug script!


<source lang="bash">
                                                          [  OK  ]
cp /etc/named.rfc1912.zones /etc/named.rfc1912.zones.orig
Starting mysqld:                                          [  OK  ]
vim /etc/named.rfc1912.zones
</source>
</source>


In here is where we add the entries for the domains we have [[SOA]] for at the end of the file. These will differ for every install, so only two examples will be shown.
Secure the server.
 
<source lang="dot">
// Our zones which this server is SOA for.
zone "45years.ca" IN {
        type master;
        file "/etc/named/db.45years.ca";
        allow-transfer {
                192.139.81.117;
        };
};
 
zone "alteeve.com" in {
        type master;
        file "/etc/named/db.alteeve.com";
        allow-transfer {
                192.139.81.117;
        };
};
</source>
 
This tutorial does not aim to cover actual zone files, but here is one for reference:


<source lang="bash">
<source lang="bash">
cat /etc/named/db.45years.ca
mysql_secure_installation
</source>
</source>
<source lang="text">
<source lang="text">
$ORIGIN .
NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MySQL
$TTL 600 ; Time To Live.
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!
45years.ca IN SOA ns1.alteeve.com. admin.alteeve.com. (
2011081402 ; Serial Number (yyyymmdd##)
300 ; refresh (in seconds)
180 ; retry (in seconds)
600 ; expire (in seconds)
86400 ; minimum (in seconds)
)
NS ns1.alteeve.com.
NS ns2.alteeve.com.
A 192.139.81.121
MX 10 mail.45years.ca.
$ORIGIN 45years.ca.
localhost A 127.0.0.1
mail A 192.139.81.121
www CNAME 45years.ca.
</source>


== Adding a Firewall Entry ==


Assuming you have a firewall running, be sure to add an entry for [[TCP]] port 53.
In order to log into MySQL to secure it, we'll need the current
password for the root user.  If you've just installed MySQL, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.


== (Re)Start BIND ==
Enter current password for root (enter for none):
OK, successfully used password, moving on...


Once all the configuration files and domain zone files are in place, (re)start the <span class="code">named</span> service.
Setting the root password ensures that nobody can log into the MySQL
root user without the proper authorisation.


<source lang="bash">
Set root password? [Y/n] y
/etc/init.d/named restart
New password:
</source>
Re-enter new password:
<source lang="text">
Password updated successfully!
Stopping named: .                                         [  OK  ]
Reloading privilege tables..
Starting named:                                            [ OK  ]
  ... Success!
</source>


== Testing Name resolution ==


To properly test name resolution, you will want to resolve a domain we are [[SOA]] for and another domain which we are not. We will repeat this twice, once on the server and once from a remote machine to ensure that it is answering remote queries. Note that in the examples below, my DNS server's IP address is <span class="code">78.46.37.135</span>.
By default, a MySQL installation has an anonymous user, allowing anyone
to log into MySQL without having to have a user account created for
them. This is intended only for testing, and to make the installation
go a bit smoother. You should remove them before moving into a
production environment.


On the server;
Remove anonymous users? [Y/n] y
... Success!


Query <span class="code">alteeve.com</span>, which we're SOA for.
Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.


<source lang="bash">
Disallow root login remotely? [Y/n] 
dig alteeve.com @localhost
... Success!
</source>
 
<source lang="text">
By default, MySQL comes with a database named 'test' that anyone can
; <<>> DiG 9.7.3-P3-RedHat-9.7.3-8.P3.el6_2.2 <<>> alteeve.com @localhost
access. This is also intended only for testing, and should be removed
;; global options: +cmd
before moving into a production environment.
;; Got answer:
 
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 1418
Remove test database and access to it? [Y/n]
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 2
- Dropping test database...
... Success!
- Removing privileges on test database...
... Success!


;; QUESTION SECTION:
Reloading the privilege tables will ensure that all changes made so far
;alteeve.com. IN A
will take effect immediately.


;; ANSWER SECTION:
Reload privilege tables now? [Y/n]
alteeve.com. 600 IN A 192.139.81.121
... Success!


;; AUTHORITY SECTION:
Cleaning up...
alteeve.com. 600 IN NS ns1.alteeve.com.
alteeve.com. 600 IN NS ns2.alteeve.com.


;; ADDITIONAL SECTION:
ns1.alteeve.com. 600 IN A 192.139.81.117
ns2.alteeve.com. 600 IN A 192.139.81.119


;; Query time: 0 msec
;; SERVER: ::1#53(::1)
;; WHEN: Sun Feb  5 13:57:11 2012
;; MSG SIZE  rcvd: 113
</source>


Now query <span class="code">google.ca</span> which we obviously are not SOA for.
All done!  If you've completed all of the above steps, your MySQL
installation should now be secure.


<source lang="bash">
Thanks for using MySQL!
dig google.ca @localhost
</source>
</source>
<source lang="text">
; <<>> DiG 9.7.3-P3-RedHat-9.7.3-8.P3.el6_2.2 <<>> google.ca @localhost
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56760
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 13, ADDITIONAL: 0


;; QUESTION SECTION:
= BIND =
;google.ca. IN A


;; ANSWER SECTION:
{{note|1=This is not meant to cover creating the actual zone files for DNS. It's goal is to setup BIND on your [[EL6]] server only.}}
google.ca. 300 IN A 74.125.232.56


;; AUTHORITY SECTION:
This is the BIND named server that handles DNS resolution. It will be setup in two parts; The global options and then the zones file.
. 2967 IN NS f.root-servers.net.
. 2967 IN NS c.root-servers.net.
. 2967 IN NS b.root-servers.net.
. 2967 IN NS a.root-servers.net.
. 2967 IN NS k.root-servers.net.
. 2967 IN NS i.root-servers.net.
. 2967 IN NS e.root-servers.net.
. 2967 IN NS h.root-servers.net.
. 2967 IN NS l.root-servers.net.
. 2967 IN NS d.root-servers.net.
. 2967 IN NS j.root-servers.net.
. 2967 IN NS g.root-servers.net.
. 2967 IN NS m.root-servers.net.


;; Query time: 12 msec
== Install bind ==
;; SERVER: ::1#53(::1)
;; WHEN: Sun Feb  5 14:02:03 2012
;; MSG SIZE  rcvd: 254
</source>


Now from a remote machine, repeat the same queries to ensure that our DNS server will respond to external queries.
<source lang="bash">
yum install bind bind-libs bind-utils
</source>


On the server;
== Global Configuration ==


Query <span class="code">alteeve.com</span>, which we're SOA for.
Edit the main configuration file, making a backup first.


<source lang="bash">
<source lang="bash">
dig alteeve.com @78.46.37.135
cp /etc/named.conf /etc/named.conf.orig
vim /etc/named.conf
</source>
</source>
<source lang="text">
; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.2.rc1.fc16 <<>> alteeve.com @78.46.37.135
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 46628
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 2


;; QUESTION SECTION:
Enable queries on any interface and answer queries for any domain, not just ours. Edit or add the following;
;alteeve.com. IN A


;; ANSWER SECTION:
<source lang="dot">
alteeve.com. 600 IN A 192.139.81.121
        listen-on port 53      { any; };
        allow-query            { any; };
        allow-query-cache      { any; };
</source>


;; AUTHORITY SECTION:
For now, we're going to disable DNSSEC. Make the following changes;
alteeve.com. 600 IN NS ns2.alteeve.com.
alteeve.com. 600 IN NS ns1.alteeve.com.


;; ADDITIONAL SECTION:
<source lang="dot">
ns1.alteeve.com. 600 IN A 192.139.81.117
        dnssec-enable          no;
ns2.alteeve.com. 600 IN A 192.139.81.119
        dnssec-validation      no;
 
;; Query time: 138 msec
;; SERVER: 78.46.37.135#53(78.46.37.135)
;; WHEN: Sun Feb  5 14:04:09 2012
;; MSG SIZE  rcvd: 113
</source>
</source>


Now query <span class="code">google.ca</span> which we obviously are not SOA for.
Now tell bind where to look for a domain name's IP when we don't know. Add;


<source lang="bash">
<source lang="dot">
dig google.ca @78.46.37.135
        forwarders {
                // These are Google's open DNS servers
                8.8.8.8;
                8.8.4.4;
        };
</source>
</source>
<source lang="text">
; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.2.rc1.fc16 <<>> google.ca @78.46.37.135
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 18204
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 13, ADDITIONAL: 0


;; QUESTION SECTION:
This server will have a slave, and we want to notify that slave when a record changes. Add;
;google.ca. IN A
 
<source lang="dot">
        notify                  yes;
</source>


;; ANSWER SECTION:
Done. I like to clean up the file to put the variables in line with one another. With this in mind, let's look at the changes as a unified <span class="code">diff</span>;
google.ca. 138 IN A 74.125.232.56


;; AUTHORITY SECTION:
<source lang="bash">
. 2805 IN NS h.root-servers.net.
diff -u /etc/named.conf.orig /etc/named.conf
. 2805 IN NS c.root-servers.net.
</source>
. 2805 IN NS j.root-servers.net.
<source lang="diff">
. 2805 IN NS i.root-servers.net.
--- /etc/named.conf.orig 2012-02-05 00:54:48.434068501 -0500
. 2805 IN NS b.root-servers.net.
+++ /etc/named.conf 2012-02-05 13:45:16.484083319 -0500
. 2805 IN NS m.root-servers.net.
@@ -8,18 +8,26 @@
. 2805 IN NS g.root-servers.net.
//
. 2805 IN NS d.root-servers.net.
. 2805 IN NS a.root-servers.net.
options {
. 2805 IN NS l.root-servers.net.
- listen-on port 53 { 127.0.0.1; };
. 2805 IN NS f.root-servers.net.
- listen-on-v6 port 53 { ::1; };
. 2805 IN NS k.root-servers.net.
- directory "/var/named";
. 2805 IN NS e.root-servers.net.
- dump-file "/var/named/data/cache_dump.db";
 
-        statistics-file "/var/named/data/named_stats.txt";
;; Query time: 140 msec
-        memstatistics-file "/var/named/data/named_mem_stats.txt";
;; SERVER: 78.46.37.135#53(78.46.37.135)
- allow-query    { localhost; };
;; WHEN: Sun Feb 5 14:04:31 2012
- recursion yes;
;; MSG SIZE  rcvd: 254
-
</source>
- dnssec-enable yes;
 
- dnssec-validation yes;
Done!
- dnssec-lookaside auto;
 
+ listen-on port 53 { any; };
= Email =
+ listen-on-v6 port 53 { ::1; };
+ directory "/var/named";
+ dump-file "/var/named/data/cache_dump.db";
+        statistics-file "/var/named/data/named_stats.txt";
+        memstatistics-file "/var/named/data/named_mem_stats.txt";
+ allow-query { any; };
+ allow-query-cache { any; };
+ recursion yes;
+ notify yes;
+
+ dnssec-enable no;
+ dnssec-validation no;
+ dnssec-lookaside auto;
+
+ forwarders {
+ // These are Google's open DNS servers
+ 8.8.8.8;
+ 8.8.4.4;
+ };
   
/* Path to ISC DLV key */
bindkeys-file "/etc/named.iscdlv.key";
</source>


This is a pretty heavily customized postfix install using a custom schema. It was originally based on [http://www.howtoforge.com/virtual_users_and_domains_with_postfix_debian_etch this Debian Etch] tutorial, but adapted for PostgreSQL. Much time has passed and the operating system is now significantly changed, but it's lineage is thus. A more recent, but still Debian-focused version of the tutorial [http://workaround.org/ispmail/squeeze/big-picture is here]. I also used [http://en.gentoo-wiki.com/wiki/Mail_server_using_Postfix_and_Dovecot this tutorial] to help sort out the PostgreSQL stuff.
== Setting Up rndc ==


This will use a few applications;
This ensures that we're transferring zone data between the real master and slave servers.
* Postfix - The program that receives email.
* PostgreSQL - The database used to validate the existence of email accounts and validates incoming user credentials.
* Dovecot - Takes email coming from postfix, via amavis, and records them to disk. It also answers requests from users wanting to check their email.
* Amavis - Filters incoming email for spam (via spamassassin) and virsus (via clamav)


We will also be using graylisting, which is a spam fighting tactic where the first email from a given user to one of our users is bounced for a few minutes. Proper mail servers will acknowledge the bound, wait the time and resend. Spam mailers though are usually fire-and-forget and will not resend, thus effectively blocking the spam message. This is a very effective method of blocking spam with minimal chance of losing real mail from real users. Any subsequent message from the user would be allowed through with no delay, provided the user had in fact resent the first message as requested.
{{note|1=This will take a long time to finish. Please be patient!}}


== Install ==
<source lang="bash">
rndc-confgen -a
</source>
 
Eventually, this will be returned;
 
<source lang="text">
wrote key file "/etc/rndc.key"
</source>


To install the applications;
Now make sure everything is owned by <span class="name">named:named</span>.


<source lang="bash">
<source lang="text">
yum install postfix postfix-perl-scripts dovecot dovecot-pgsql spamassassin postgresql-server postgresql-plperl mutt
chown named:named /etc/rndc.key
chown -R named:named /etc/named
</source>
</source>


== Configuring Postfix ==
Now copy the <span class="code">rndc.key</span> to the other node:


Installation requires several steps. The AN!Console database must be loaded. Various applications need to be installed. Postfix, Dovecot and helper applications need to be configured and so on.
<source lang="bash">
rsync -av /etc/rndc.key root@ns2.alteeve.ca:/etc/
</source>
<source lang="text">
root@ns2.alteeve.ca's password:
sending incremental file list


This tutorial uses the following values that you may need to adjust;
sent 49 bytes  received 15 bytes  11.64 bytes/sec
* Database name; <span class="code">an_tools</span>
total size is 77  speedup is 1.20
* Database user; <span class="code">alteeve</span>
</source>
* Database password; <span class="code">secret</span>
* Database host; <span class="code">127.0.0.1</span>


{{note|1=Do not use the database host "<span class="code">localhost</span>" unless you are certain you can connect to the DB using a standard [[unix]] socket.}}
Done.


=== Building Support for PostgreSQL ===
== Adding Zones ==


{{warning|1=We need to build our own RPM in order to support postgresql. This means we will have to disable <span class="code">postfix</span> from future updates, placing the onus on us to make sure critical updates are applied. This will require downloading the latest source RPMs, re-enabling postgres and recompile/reinstall.}}
This is where we tell BIND which zones we have SOA for. This includes the pointers to the actual files on disk with each domain's information.


Add the source [[RPM]] repository by adding the following;
Backup then edit the zones file.


<source lang="bash">
<source lang="bash">
vim /etc/yum.repos.d/CentOS-Base.repo
cp /etc/named.rfc1912.zones /etc/named.rfc1912.zones.orig
vim /etc/named.rfc1912.zones
</source>
</source>
<source lang="bash">
 
# Source RPM repository
'''On the master server''':
[base-source]
 
name=CentOS-$releasever - Base - Source
In here is where we add the entries for the domains we have [[SOA]] for at the end of the file. These will differ for every install, so only two examples will be shown.
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os
 
#baseurl=http://vault.centos.org/$releasever/os/SRPMS/
<source lang="dot">
baseurl=http://vault.centos.org/6.0/os/SRPMS/
// Our zones which this server is SOA for.
gpgcheck=1
 
enabled=1
zone "digimer.ca" in {
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6
type master;
file "/etc/named/db.digimer.ca";
allow-transfer {
65.39.153.67;
10.255.5.4;
10.222.1.4;
};
};
</source>
 
'''On the slave server''':
 
<source lang="dot">
// Our zones which this server is SOA for.
 
zone "digimer.ca" in {
type slave;
file "/etc/named/bak.digimer.ca";
masters {
65.39.153.66;
10.255.5.3;
10.222.1.3;
};
};
</source>
</source>


Now download the source RPM for postfix.
 
This tutorial does not aim to cover actual zone files, but here is one for reference:


<source lang="bash">
<source lang="bash">
yumdownloader --source postfix
cat /etc/named/db.digimer.ca
</source>
</source>
<source lang="text">
<source lang="text">
Loaded plugins: fastestmirror
$ORIGIN .
Loading mirror speeds from cached hostfile
$TTL 600 ; Time To Live.
* base: centos.vieth-server.de
digimer.ca IN SOA ns1.alteeve.ca. admin.alteeve.ca. (
* extras: centos.vieth-server.de
2013022106 ; Serial Number (yyyymmdd##)
* updates: centos.vieth-server.de
300 ; refresh (in seconds)
base                              | 3.7 kB    00:00
180 ; retry (in seconds)
base-source                        | 1.9 kB    00:00
300 ; expire (in seconds)
extras                            | 3.5 kB    00:00
300 ; minimum (in seconds)
updates                            | 3.5 kB    00:00
)
No source RPM found for 2:postfix-2.6.6-2.2.el6_1.x86_64
NS ns1.alteeve.ca.
./postfix-2.6.6-2.el6.src.rpm already exists and appears to be complete
NS ns2.alteeve.ca.
nikko:/etc/postfix# rm postfix-2.6.6-2.el6.src.rpm
A 65.39.153.65
rm: remove regular file `postfix-2.6.6-2.el6.src.rpm'? y
MX 10 mail.digimer.ca.
nikko:/etc/postfix# yumdownloader --source postfix
$ORIGIN digimer.ca.
Loaded plugins: fastestmirror
localhost A 127.0.0.1
Loading mirror speeds from cached hostfile
mail A 64.34.141.3
* base: centos.vieth-server.de
www CNAME digimer.ca.
* extras: centos.vieth-server.de
* updates: centos.vieth-server.de
No source RPM found for 2:postfix-2.6.6-2.2.el6_1.x86_64
postfix-2.6.6-2.el6.src.rpm        | 3.3 MB    00:00
</source>
</source>


Now that we have the postfix source RPM, we will install it.
Start the <span class="code">named</span> daemon on the master node;


<source lang="bash">
<source lang="bash">
rpm -Uvh postfix-2.6.6-2.el6.src.rpm
/etc/init.d/named start
</source>
</source>
<source lang="text">
<source lang="text">
  1:postfix                warning: user mockbuild does not exist - using root
Starting named:                                            [  OK  ]
warning: group mockbuild does not exist - using root
</source>
warning: user mockbuild does not exist - using root
 
warning: group mockbuild does not exist - using root
In [[syslog]], you should see something like this;
warning: user mockbuild does not exist - using root
 
warning: group mockbuild does not exist - using root
<source lang="text">
warning: user mockbuild does not exist - using root
Feb 23 18:21:46 vm03-dns01 named[2126]: starting BIND 9.8.2rc1-RedHat-9.8.2-0.10.rc1.el6_3.6 -u named
warning: group mockbuild does not exist - using root
Feb 23 18:21:46 vm03-dns01 named[2126]: built with '--build=x86_64-redhat-linux-gnu' '--host=x86_64-redhat-linux-gnu' '--target=x86_64-redhat-linux-gnu' '--program-prefix=' '--prefix=/usr' '--exec-prefix=/usr' '--bindir=/usr/bin' '--sbindir=/usr/sbin' '--sysconfdir=/etc' '--datadir=/usr/share' '--includedir=/usr/include' '--libdir=/usr/lib64' '--libexecdir=/usr/libexec' '--sharedstatedir=/var/lib' '--mandir=/usr/share/man' '--infodir=/usr/share/info' '--with-libtool' '--localstatedir=/var' '--enable-threads' '--enable-ipv6' '--with-pic' '--disable-static' '--disable-openssl-version-check' '--with-dlz-ldap=yes' '--with-dlz-postgres=yes' '--with-dlz-mysql=yes' '--with-dlz-filesystem=yes' '--with-gssapi=yes' '--disable-isc-spnego' '--with-docbook-xsl=/usr/share/sgml/docbook/xsl-stylesheets' '--enable-fixed-rrset' 'build_alias=x86_64-redhat-linux-gnu' 'host_alias=x86_64-redhat-linux-gnu' 'target_alias=x86_64-redhat-linux-gnu' 'CFLAGS= -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic' 'CPPFLAGS= -DDIG_SIGCHASE'
warning: user mockbuild does not exist - using root
Feb 23 18:21:46 vm03-dns01 named[2126]: ----------------------------------------------------
warning: group mockbuild does not exist - using root
Feb 23 18:21:46 vm03-dns01 named[2126]: BIND 9 is maintained by Internet Systems Consortium,
warning: user mockbuild does not exist - using root
Feb 23 18:21:46 vm03-dns01 named[2126]: Inc. (ISC), a non-profit 501(c)(3) public-benefit
warning: group mockbuild does not exist - using root
Feb 23 18:21:46 vm03-dns01 named[2126]: corporation.  Support and training for BIND 9 are
warning: user mockbuild does not exist - using root
Feb 23 18:21:46 vm03-dns01 named[2126]: available at https://www.isc.org/support
warning: group mockbuild does not exist - using root
Feb 23 18:21:46 vm03-dns01 named[2126]: ----------------------------------------------------
warning: user mockbuild does not exist - using root
Feb 23 18:21:46 vm03-dns01 named[2126]: adjusted limit on open files from 4096 to 1048576
warning: group mockbuild does not exist - using root
Feb 23 18:21:46 vm03-dns01 named[2126]: found 2 CPUs, using 2 worker threads
########################################### [100%]
Feb 23 18:21:46 vm03-dns01 named[2126]: using up to 4096 sockets
warning: user mockbuild does not exist - using root
Feb 23 18:21:46 vm03-dns01 named[2126]: loading configuration from '/etc/named.conf'
warning: group mockbuild does not exist - using root
Feb 23 18:21:46 vm03-dns01 named[2126]: reading built-in trusted keys from file '/etc/named.iscdlv.key'
warning: user mockbuild does not exist - using root
Feb 23 18:21:46 vm03-dns01 named[2126]: using default UDP/IPv4 port range: [1024, 65535]
warning: group mockbuild does not exist - using root
Feb 23 18:21:46 vm03-dns01 named[2126]: using default UDP/IPv6 port range: [1024, 65535]
warning: user mockbuild does not exist - using root
Feb 23 18:21:46 vm03-dns01 named[2126]: listening on IPv4 interface lo, 127.0.0.1#53
warning: group mockbuild does not exist - using root
Feb 23 18:21:46 vm03-dns01 named[2126]: listening on IPv4 interface eth0, 65.39.153.66#53
warning: user mockbuild does not exist - using root
Feb 23 18:21:46 vm03-dns01 named[2126]: listening on IPv4 interface eth0:0, 10.255.5.3#53
warning: group mockbuild does not exist - using root
Feb 23 18:21:46 vm03-dns01 named[2126]: listening on IPv4 interface eth0:1, 10.222.1.3#53
Feb 23 18:21:46 vm03-dns01 named[2126]: listening on IPv6 interface lo, ::1#53
Feb 23 18:21:46 vm03-dns01 named[2126]: generating session key for dynamic DNS
Feb 23 18:21:46 vm03-dns01 named[2126]: sizing zone task pool based on 7 zones
Feb 23 18:21:46 vm03-dns01 named[2126]: using built-in DLV key for view _default
Feb 23 18:21:46 vm03-dns01 named[2126]: set up managed keys zone for view _default, file '/var/named/dynamic/managed-keys.bind'
Feb 23 18:21:46 vm03-dns01 named[2126]: Warning: 'empty-zones-enable/disable-empty-zone' not set: disabling RFC 1918 empty zones
Feb 23 18:21:46 vm03-dns01 named[2126]: automatic empty zone: 127.IN-ADDR.ARPA
Feb 23 18:21:46 vm03-dns01 named[2126]: automatic empty zone: 254.169.IN-ADDR.ARPA
Feb 23 18:21:46 vm03-dns01 named[2126]: automatic empty zone: 2.0.192.IN-ADDR.ARPA
Feb 23 18:21:46 vm03-dns01 named[2126]: automatic empty zone: 100.51.198.IN-ADDR.ARPA
Feb 23 18:21:46 vm03-dns01 named[2126]: automatic empty zone: 113.0.203.IN-ADDR.ARPA
Feb 23 18:21:46 vm03-dns01 named[2126]: automatic empty zone: 255.255.255.255.IN-ADDR.ARPA
Feb 23 18:21:46 vm03-dns01 named[2126]: automatic empty zone: 0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA
Feb 23 18:21:46 vm03-dns01 named[2126]: automatic empty zone: D.F.IP6.ARPA
Feb 23 18:21:46 vm03-dns01 named[2126]: automatic empty zone: 8.E.F.IP6.ARPA
Feb 23 18:21:46 vm03-dns01 named[2126]: automatic empty zone: 9.E.F.IP6.ARPA
Feb 23 18:21:46 vm03-dns01 named[2126]: automatic empty zone: A.E.F.IP6.ARPA
Feb 23 18:21:46 vm03-dns01 named[2126]: automatic empty zone: B.E.F.IP6.ARPA
Feb 23 18:21:46 vm03-dns01 named[2126]: automatic empty zone: 8.B.D.0.1.0.0.2.IP6.ARPA
Feb 23 18:21:46 vm03-dns01 named[2126]: command channel listening on 127.0.0.1#953
Feb 23 18:21:46 vm03-dns01 named[2126]: command channel listening on ::1#953
Feb 23 18:21:46 vm03-dns01 named[2126]: zone 0.in-addr.arpa/IN: loaded serial 0
Feb 23 18:21:46 vm03-dns01 named[2126]: zone 1.0.0.127.in-addr.arpa/IN: loaded serial 0
Feb 23 18:21:46 vm03-dns01 named[2126]: zone 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa/IN: loaded serial 0
Feb 23 18:21:46 vm03-dns01 named[2126]: zone digimer.ca/IN: loaded serial 2013022106
Feb 23 18:21:46 vm03-dns01 named[2126]: zone localhost.localdomain/IN: loaded serial 0
Feb 23 18:21:46 vm03-dns01 named[2126]: zone localhost/IN: loaded serial 0
Feb 23 18:21:46 vm03-dns01 named[2126]: managed-keys-zone ./IN: loaded serial 3
Feb 23 18:21:46 vm03-dns01 named[2126]: zone digimer.ca/IN: sending notifies (serial 2013022106)
Feb 23 18:21:46 vm03-dns01 named[2126]: running
</source>
 
You can test that it's working by querying one of your zones.
 
<source lang="bash">
dig digimer.ca @localhost
</source>
</source>
<source lang="text">
; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.10.rc1.el6_3.6 <<>> digimer.ca @localhost
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 18362
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 1


Now edit the <span class="code">.spec</span> file to enable postgres support.
;; QUESTION SECTION:
;digimer.ca. IN A


<source lang="bash">
;; ANSWER SECTION:
cp ~/rpmbuild/SPECS/postfix.spec ~/rpmbuild/SPECS/postfix.spec.orig
digimer.ca. 600 IN A 65.39.153.65
vim ~/rpmbuild/SPECS/postfix.spec
</source>


Make the following changes.
;; AUTHORITY SECTION:
digimer.ca. 600 IN NS ns1.alteeve.ca.
digimer.ca. 600 IN NS ns2.alteeve.ca.


* Enable PostgreSQL support
;; ADDITIONAL SECTION:
<source lang="text">
ns2.alteeve.ca. 268 IN A 78.46.37.135
%{?!PGSQL: %define PGSQL 1}
</source>


Increment the release version by one.
;; Query time: 0 msec
<source lang="text">
;; SERVER: ::1#53(::1)
Release: 3%{?dist}
;; WHEN: Sat Feb 23 18:27:04 2013
;; MSG SIZE  rcvd: 104
</source>
</source>


We can see the changes here:
Now start <span class="code">named</span> on the slave. First though, check <span class="code">/etc/named/</span> to see that there are no files there yet.


<source lang="bash">
<source lang="bash">
diff -u ~/rpmbuild/SPECS/postfix.spec.orig ~/rpmbuild/SPECS/postfix.spec
ls -lah /etc/named/
</source>
</source>
<source lang="diff">
<source lang="text">
--- /root/rpmbuild/SPECS/postfix.spec.orig      2012-02-11 16:54:54.495330859 -0500
total 8.0K
+++ /root/rpmbuild/SPECS/postfix.spec   2012-02-11 16:53:39.873331101 -0500
drwxr-x---  2 named named 4.0K Dec 6 15:49 .
@@ -1,5 +1,5 @@
drwxr-xr-x. 66 root root 4.0K Feb 23 18:13 ..
  %{?!MYSQL: %define MYSQL 1}
-%{?!PGSQL: %define PGSQL 0}
+%{?!PGSQL: %define PGSQL 1}
%define LDAP 2
%define PCRE 1
%define SASL 2
@@ -35,7 +35,7 @@
  Name: postfix
  Summary: Postfix Mail Transport Agent
Version: 2.6.6
-Release: 2%{?dist}
+Release: 3%{?dist}
Epoch: 2
Group: System Environment/Daemons
URL: http://www.postfix.org
</source>
</source>


Now rebuild the RPM, which means we need to install the build tools.
Now start <span class="code">named</span>;


<source lang="bash">
<source lang="bash">
yum groupinstall development
/etc/init.d/named start
yum install db4-devel openldap-devel cyrus-sasl-devel pcre-devel mysql-devel postgresql-devel openssl-devel
rpmbuild -bb ~/rpmbuild/SPECS/postfix.spec
</source>
</source>
<source lang="text">
<source lang="text">
(compile output)
Starting named:                                            [  OK  ]
Processing files: postfix-debuginfo-2.6.6-3.el6.x86_64
</source>
Checking for unpackaged file(s): /usr/lib/rpm/check-files /root/rpmbuild/BUILDROOT/postfix-2.6.6-3.el6.x86_64
 
Wrote: /root/rpmbuild/RPMS/x86_64/postfix-2.6.6-3.el6.x86_64.rpm
In syslog on the slave, you will see something like;
Wrote: /root/rpmbuild/RPMS/x86_64/postfix-perl-scripts-2.6.6-3.el6.x86_64.rpm
 
Wrote: /root/rpmbuild/RPMS/x86_64/postfix-debuginfo-2.6.6-3.el6.x86_64.rpm
<source lang="text">
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.rymr5C
Feb 23 18:29:28 vm04-dns02 named[2072]: starting BIND 9.8.2rc1-RedHat-9.8.2-0.10.rc1.el6_3.6 -u named
+ umask 022
Feb 23 18:29:28 vm04-dns02 named[2072]: built with '--build=x86_64-redhat-linux-gnu' '--host=x86_64-redhat-linux-gnu' '--target=x86_64-redhat-linux-gnu' '--program-prefix=' '--prefix=/usr' '--exec-prefix=/usr' '--bindir=/usr/bin' '--sbindir=/usr/sbin' '--sysconfdir=/etc' '--datadir=/usr/share' '--includedir=/usr/include' '--libdir=/usr/lib64' '--libexecdir=/usr/libexec' '--sharedstatedir=/var/lib' '--mandir=/usr/share/man' '--infodir=/usr/share/info' '--with-libtool' '--localstatedir=/var' '--enable-threads' '--enable-ipv6' '--with-pic' '--disable-static' '--disable-openssl-version-check' '--with-dlz-ldap=yes' '--with-dlz-postgres=yes' '--with-dlz-mysql=yes' '--with-dlz-filesystem=yes' '--with-gssapi=yes' '--disable-isc-spnego' '--with-docbook-xsl=/usr/share/sgml/docbook/xsl-stylesheets' '--enable-fixed-rrset' 'build_alias=x86_64-redhat-linux-gnu' 'host_alias=x86_64-redhat-linux-gnu' 'target_alias=x86_64-redhat-linux-gnu' 'CFLAGS= -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic' 'CPPFLAGS= -DDIG_SIGCHASE'
+ cd /root/rpmbuild/BUILD
Feb 23 18:29:28 vm04-dns02 named[2072]: ----------------------------------------------------
+ cd postfix-2.6.6
Feb 23 18:29:28 vm04-dns02 named[2072]: BIND 9 is maintained by Internet Systems Consortium,
+ rm -rf /root/rpmbuild/BUILDROOT/postfix-2.6.6-3.el6.x86_64
Feb 23 18:29:28 vm04-dns02 named[2072]: Inc. (ISC), a non-profit 501(c)(3) public-benefit
+ exit 0
Feb 23 18:29:28 vm04-dns02 named[2072]: corporation. Support and training for BIND 9 are
Feb 23 18:29:28 vm04-dns02 named[2072]: available at https://www.isc.org/support
Feb 23 18:29:28 vm04-dns02 named[2072]: ----------------------------------------------------
Feb 23 18:29:28 vm04-dns02 named[2072]: adjusted limit on open files from 4096 to 1048576
Feb 23 18:29:28 vm04-dns02 named[2072]: found 2 CPUs, using 2 worker threads
Feb 23 18:29:28 vm04-dns02 named[2072]: using up to 4096 sockets
Feb 23 18:29:28 vm04-dns02 named[2072]: loading configuration from '/etc/named.conf'
Feb 23 18:29:28 vm04-dns02 named[2072]: reading built-in trusted keys from file '/etc/named.iscdlv.key'
Feb 23 18:29:28 vm04-dns02 named[2072]: using default UDP/IPv4 port range: [1024, 65535]
Feb 23 18:29:28 vm04-dns02 named[2072]: using default UDP/IPv6 port range: [1024, 65535]
Feb 23 18:29:28 vm04-dns02 named[2072]: listening on IPv4 interface lo, 127.0.0.1#53
Feb 23 18:29:28 vm04-dns02 named[2072]: listening on IPv4 interface eth0, 65.39.153.67#53
Feb 23 18:29:28 vm04-dns02 named[2072]: listening on IPv4 interface eth0:0, 10.255.5.4#53
Feb 23 18:29:28 vm04-dns02 named[2072]: listening on IPv4 interface eth0:1, 10.222.1.4#53
Feb 23 18:29:28 vm04-dns02 named[2072]: listening on IPv6 interface lo, ::1#53
Feb 23 18:29:28 vm04-dns02 named[2072]: generating session key for dynamic DNS
Feb 23 18:29:28 vm04-dns02 named[2072]: sizing zone task pool based on 7 zones
Feb 23 18:29:28 vm04-dns02 named[2072]: using built-in DLV key for view _default
Feb 23 18:29:28 vm04-dns02 named[2072]: set up managed keys zone for view _default, file '/var/named/dynamic/managed-keys.bind'
Feb 23 18:29:28 vm04-dns02 named[2072]: Warning: 'empty-zones-enable/disable-empty-zone' not set: disabling RFC 1918 empty zones
Feb 23 18:29:28 vm04-dns02 named[2072]: automatic empty zone: 127.IN-ADDR.ARPA
Feb 23 18:29:28 vm04-dns02 named[2072]: automatic empty zone: 254.169.IN-ADDR.ARPA
Feb 23 18:29:28 vm04-dns02 named[2072]: automatic empty zone: 2.0.192.IN-ADDR.ARPA
Feb 23 18:29:28 vm04-dns02 named[2072]: automatic empty zone: 100.51.198.IN-ADDR.ARPA
Feb 23 18:29:28 vm04-dns02 named[2072]: automatic empty zone: 113.0.203.IN-ADDR.ARPA
Feb 23 18:29:28 vm04-dns02 named[2072]: automatic empty zone: 255.255.255.255.IN-ADDR.ARPA
Feb 23 18:29:28 vm04-dns02 named[2072]: automatic empty zone: 0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA
Feb 23 18:29:28 vm04-dns02 named[2072]: automatic empty zone: D.F.IP6.ARPA
Feb 23 18:29:28 vm04-dns02 named[2072]: automatic empty zone: 8.E.F.IP6.ARPA
Feb 23 18:29:28 vm04-dns02 named[2072]: automatic empty zone: 9.E.F.IP6.ARPA
Feb 23 18:29:28 vm04-dns02 named[2072]: automatic empty zone: A.E.F.IP6.ARPA
Feb 23 18:29:28 vm04-dns02 named[2072]: automatic empty zone: B.E.F.IP6.ARPA
Feb 23 18:29:28 vm04-dns02 named[2072]: automatic empty zone: 8.B.D.0.1.0.0.2.IP6.ARPA
Feb 23 18:29:28 vm04-dns02 named[2072]: command channel listening on 127.0.0.1#953
Feb 23 18:29:28 vm04-dns02 named[2072]: command channel listening on ::1#953
Feb 23 18:29:28 vm04-dns02 named[2072]: zone 0.in-addr.arpa/IN: loaded serial 0
Feb 23 18:29:28 vm04-dns02 named[2072]: zone 1.0.0.127.in-addr.arpa/IN: loaded serial 0
Feb 23 18:29:28 vm04-dns02 named[2072]: zone 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa/IN: loaded serial 0
Feb 23 18:29:28 vm04-dns02 named[2072]: zone localhost.localdomain/IN: loaded serial 0
Feb 23 18:29:28 vm04-dns02 named[2072]: zone localhost/IN: loaded serial 0
Feb 23 18:29:28 vm04-dns02 named[2072]: managed-keys-zone ./IN: loaded serial 0
Feb 23 18:29:28 vm04-dns02 named[2072]: running
Feb 23 18:29:28 vm04-dns02 named[2072]: zone digimer.ca/IN: Transfer started.
Feb 23 18:29:28 vm04-dns02 named[2072]: transfer of 'digimer.ca/IN' from 65.39.153.66#53: connected using 65.39.153.67#47099
Feb 23 18:29:28 vm04-dns02 named[2072]: zone digimer.ca/IN: transferred serial 2013022106
Feb 23 18:29:28 vm04-dns02 named[2072]: transfer of 'digimer.ca/IN' from 65.39.153.66#53: Transfer completed: 1 messages, 9 records, 247 bytes, 0.001 secs (247000 bytes/sec)
</source>
 
If you look in syslog on the master, you will see that the <span class="code">digimer.ca</span> domain was transferred;
 
<source lang="text">
Feb 23 18:29:28 vm03-dns01 named[2126]: client 65.39.153.67#47099: transfer of 'digimer.ca/IN': AXFR started
Feb 23 18:29:28 vm03-dns01 named[2126]: client 65.39.153.67#47099: transfer of 'digimer.ca/IN': AXFR ended
</source>
</source>


Install the updated postfix.
Indeed, you will now see that the <span class="code">/etc/named/bak.digimer.ca</span> file was created.


<source lang="bash">
<source lang="bash">
rpm -Uvh ~/rpmbuild/RPMS/x86_64/postfix-2.6.6-3.el6.x86_64.rpm ~/rpmbuild/RPMS/x86_64/postfix-perl-scripts-2.6.6-3.el6.x86_64.rpm
ls -lah /etc/named/
</source>
</source>
<source lang="text">
<source lang="text">
Preparing...               ########################################### [100%]
total 12K
  1:postfix                ########################################### [ 50%]
drwxr-x---  2 named named 4.0K Feb 23 18:29 .
  2:postfix-perl-scripts   ########################################### [100%]
drwxr-xr-x. 66 root  root  4.0K Feb 23 18:13 ..
-rw-r--r-1 named named  438 Feb 23 18:29 bak.digimer.ca
</source>
</source>


Now exclude <span class="code">postfix</span> from future updates.
We can confirm that it's working by querying the slave;


<source lang="bash">
<source lang="bash">
cp /etc/yum.conf /etc/yum.conf.orig
dig digimer.ca @localhost
vim /etc/yum.conf
diff -u /etc/yum.conf.orig /etc/yum.conf
</source>
</source>
<source lang="text">
<source lang="text">
--- /etc/yum.conf.orig  2012-02-11 16:59:53.720079168 -0500
; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.10.rc1.el6_3.6 <<>> digimer.ca @localhost
+++ /etc/yum.conf      2012-02-11 17:00:47.013331283 -0500
;; global options: +cmd
@@ -10,6 +10,7 @@
;; Got answer:
installonly_limit=5
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 15602
bugtracker_url=http://bugs.centos.org/set_project.php?project_id=16&ref=http://bugs.centos.org/bug_report_page.php?category=yum
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 0
distroverpkg=centos-release
 
+exclude=postfix*
;; QUESTION SECTION:
;digimer.ca. IN A
#  This is the default, if you make this bigger yum won't see if the metadata
# is newer on the remote and so you'll "gain" the bandwidth of not having to
</source>


=== Basic Postfix Configuration ===
;; ANSWER SECTION:
digimer.ca. 600 IN A 65.39.153.65


Since we'll be using virtual domains, users, aliases and mailboxes, we'll need to start by commenting out some of the default options in Postfix. By default, Postfix is set up for small numbers of local users, and it only allows connections from the localhost. Our configuration will be more scalable, allowing many domains and users to be stored in the Postgres database.
;; AUTHORITY SECTION:
digimer.ca. 600 IN NS ns1.alteeve.ca.
digimer.ca. 600 IN NS ns2.alteeve.ca.


Comment out the following:
;; Query time: 0 msec
<source lang="bash">vim /etc/postfix/main.cf</source>
;; SERVER: ::1#53(::1)
<source lang="bash">
;; WHEN: Sat Feb 23 18:32:52 2013
# inet_interfaces = localhost
;; MSG SIZE rcvd: 88
# mydestination = $myhostname, localhost.$mydomain, localhost
# alias_maps = hash:/etc/aliases  
# alias_database = hash:/etc/aliases
</source>
</source>


And uncomment/add these:
Excellent! Now you can add more DNS servers to the master server.
<source lang="bash">vim /etc/postfix/main.cf</source>
<source lang="bash">
inet_interfaces = all  # allows us to connect and test from another machine
mynetworks = 192.168.1.0/32, 127.0.0.0/8  # use the IP or subnet of your test machine here
</source>


=== Setup Virtual Domain Lookup ===
== Adding a Firewall Entry ==


This tells postfix how to find which domains we have.
Assuming you have a firewall running, be sure to add an entry for [[TCP]] port 53.
 
== (Re)Start BIND ==
 
Once all the configuration files and domain zone files are in place, (re)start the <span class="code">named</span> service.


<source lang="bash">
<source lang="bash">
vim /etc/postfix/pgsql-virtual-mailbox-domains.cf
/etc/init.d/named restart
</source>
</source>
<source lang="text">
<source lang="text">
user = alteeve
Stopping named: .                                         [  OK  ]
password = secret
Starting named:                                            [  OK  ]
hosts = 127.0.0.1
dbname = an_tools
query = SELECT 1 FROM domains WHERE dom_name='%s'
</source>
</source>


Now tell Postfix to use this new file by appending the following to the main postfix configuration file.
== Testing Name resolution ==
 
To properly test name resolution, you will want to resolve a domain we are [[SOA]] for and another domain which we are not. We will repeat this twice, once on the server and once from a remote machine to ensure that it is answering remote queries. Note that in the examples below, my DNS server's IP address is <span class="code">78.46.37.135</span>.


<source lang="bash">
On the server;
vim /etc/postfix/main.cf
</source>
<source lang="bash">
# Tell postfix to validate domains using our postgresql databae via the
# pgsql-virtual-mailbox-domains.cf
virtual_mailbox_domains=pgsql:/etc/postfix/pgsql-virtual-mailbox-domains.cf
</source>


Now reload postfix;
Query <span class="code">alteeve.ca</span>, which we're SOA for.


<source lang="bash">
<source lang="bash">
/etc/init.d/postfix reload
dig alteeve.ca @localhost
</source>
</source>
<source lang="text">
<source lang="text">
Reloading postfix:                                         [  OK  ]
; <<>> DiG 9.7.3-P3-RedHat-9.7.3-8.P3.el6_2.2 <<>> alteeve.ca @localhost
</source>
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 1418
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 2


Now we can test that domains resolve. In my case, I will test the look-up for <span class="code">alteeve.com</span>.
;; QUESTION SECTION:
;alteeve.ca. IN A


<source lang="bash">
;; ANSWER SECTION:
postmap -q alteeve.com pgsql:/etc/postfix/pgsql-virtual-mailbox-domains.cf
alteeve.ca. 600 IN A 192.139.81.121
</source>
 
<source lang="text">
;; AUTHORITY SECTION:
1
alteeve.ca. 600 IN NS ns1.alteeve.ca.
alteeve.ca. 600 IN NS ns2.alteeve.ca.
 
;; ADDITIONAL SECTION:
ns1.alteeve.ca. 600 IN A 192.139.81.117
ns2.alteeve.ca. 600 IN A 192.139.81.119
 
;; Query time: 0 msec
;; SERVER: ::1#53(::1)
;; WHEN: Sun Feb  5 13:57:11 2012
;; MSG SIZE  rcvd: 113
</source>
</source>


Now make sure it returns nothing when query a bad domain.
Now query <span class="code">google.ca</span> which we obviously are not SOA for.


<source lang="bash">
<source lang="bash">
postmap -q example.com pgsql:/etc/postfix/pgsql-virtual-mailbox-domains.cf
dig google.ca @localhost
</source>
</source>
<source lang="text">
<source lang="text">
<nothing returned>
; <<>> DiG 9.7.3-P3-RedHat-9.7.3-8.P3.el6_2.2 <<>> google.ca @localhost
</source>
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56760
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 13, ADDITIONAL: 0


=== Setup Mailbox Mapping ===
;; QUESTION SECTION:
;google.ca. IN A


This section will tell postfix which users for a given domain are valid.
;; ANSWER SECTION:
google.ca. 300 IN A 74.125.232.56


<source lang="bash">
;; AUTHORITY SECTION:
vim /etc/postfix/pgsql-virtual-mailbox-maps.cf
. 2967 IN NS f.root-servers.net.
</source>
. 2967 IN NS c.root-servers.net.
<source lang="text">
. 2967 IN NS b.root-servers.net.
user = alteeve
. 2967 IN NS a.root-servers.net.
password = secret
. 2967 IN NS k.root-servers.net.
hosts = 127.0.0.1
. 2967 IN NS i.root-servers.net.
dbname = an_tools
. 2967 IN NS e.root-servers.net.
query = SELECT 1 FROM email_file WHERE email='%s'
. 2967 IN NS h.root-servers.net.
. 2967 IN NS l.root-servers.net.
. 2967 IN NS d.root-servers.net.
. 2967 IN NS j.root-servers.net.
. 2967 IN NS g.root-servers.net.
. 2967 IN NS m.root-servers.net.
 
;; Query time: 12 msec
;; SERVER: ::1#53(::1)
;; WHEN: Sun Feb  5 14:02:03 2012
;; MSG SIZE  rcvd: 254
</source>
</source>


Tell postfix to use this new file when looking up users.
Now from a remote machine, repeat the same queries to ensure that our DNS server will respond to external queries.
 
On the server;
 
Query <span class="code">alteeve.ca</span>, which we're SOA for.


<source lang="bash">
<source lang="bash">
vim /etc/postfix/main.cf
dig alteeve.ca @78.46.37.135
</source>
</source>
And add:
<source lang="text">
<source lang="text">
# Tell postfix which table to look in when validating a local user via their
; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.2.rc1.fc16 <<>> alteeve.ca @78.46.37.135
# email address.
;; global options: +cmd
virtual_mailbox_maps=pgsql:/etc/postfix/pgsql-virtual-mailbox-maps.cf
;; Got answer:
</source>
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 46628
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 2
 
;; QUESTION SECTION:
;alteeve.ca. IN A
 
;; ANSWER SECTION:
alteeve.ca. 600 IN A 192.139.81.121
 
;; AUTHORITY SECTION:
alteeve.ca. 600 IN NS ns2.alteeve.ca.
alteeve.ca. 600 IN NS ns1.alteeve.ca.


Reload <span class="code">postfix<span>.
;; ADDITIONAL SECTION:
ns1.alteeve.ca. 600 IN A 192.139.81.117
ns2.alteeve.ca. 600 IN A 192.139.81.119


<source lang="bash">
;; Query time: 138 msec
/etc/init.d/postfix reload
;; SERVER: 78.46.37.135#53(78.46.37.135)
</source>
;; WHEN: Sun Feb 5 14:04:09 2012
<source lang="text">
;; MSG SIZE rcvd: 113
Reloading postfix:                                         [ OK ]
</source>
</source>


Now do a test of a valid user, which should return <span class="code">1</span>, and an invalid user, which should return nothing.
Now query <span class="code">google.ca</span> which we obviously are not SOA for.


<source lang="bash">
<source lang="bash">
postmap -q mkelly@alteeve.com pgsql:/etc/postfix/pgsql-virtual-mailbox-maps.cf
dig google.ca @78.46.37.135
</source>
</source>
<source lang="text">
<source lang="text">
1
; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.2.rc1.fc16 <<>> google.ca @78.46.37.135
</source>
;; global options: +cmd
<source lang="bash">
;; Got answer:
postmap -q nobody@alteeve.com pgsql:/etc/postfix/pgsql-virtual-mailbox-maps.cf
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 18204
</source>
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 13, ADDITIONAL: 0
<source lang="text">
 
<nothing returned>
;; QUESTION SECTION:
</source>
;google.ca. IN A


=== Setup Email Forwards ===
;; ANSWER SECTION:
google.ca. 138 IN A 74.125.232.56


This will allow for email addresses to be forwarded to other email addresses.
;; AUTHORITY SECTION:
. 2805 IN NS h.root-servers.net.
. 2805 IN NS c.root-servers.net.
. 2805 IN NS j.root-servers.net.
. 2805 IN NS i.root-servers.net.
. 2805 IN NS b.root-servers.net.
. 2805 IN NS m.root-servers.net.
. 2805 IN NS g.root-servers.net.
. 2805 IN NS d.root-servers.net.
. 2805 IN NS a.root-servers.net.
. 2805 IN NS l.root-servers.net.
. 2805 IN NS f.root-servers.net.
. 2805 IN NS k.root-servers.net.
. 2805 IN NS e.root-servers.net.


<source lang="bash">
;; Query time: 140 msec
vim /etc/postfix/pgsql-virtual-alias-maps.cf
;; SERVER: 78.46.37.135#53(78.46.37.135)
</source>
;; WHEN: Sun Feb  5 14:04:31 2012
<source lang="text">
;; MSG SIZE  rcvd: 254
user = alteeve
password = secret
hosts = 127.0.0.1
dbname = an_tools
query = SELECT fwd_destination FROM forwards WHERE fwd_source='%s'
</source>
</source>


Now tell postfix where to look.
Done!
 
= Email =
 
This is a pretty heavily customized postfix install using a custom schema. It was originally based on [http://www.howtoforge.com/virtual_users_and_domains_with_postfix_debian_etch this Debian Etch] tutorial, but adapted for PostgreSQL. Much time has passed and the operating system is now significantly changed, but it's lineage is thus. A more recent, but still Debian-focused version of the tutorial [http://workaround.org/ispmail/squeeze/big-picture is here]. I also used [http://en.gentoo-wiki.com/wiki/Mail_server_using_Postfix_and_Dovecot this tutorial] to help sort out the PostgreSQL stuff.


<source lang="bash">
This will use a few applications;
vim /etc/postfix/main.cf
* Postfix - The program that receives email.
</source>
* PostgreSQL - The database used to validate the existence of email accounts and validates incoming user credentials.
* Dovecot - Takes email coming from postfix, via amavis, and records them to disk. It also answers requests from users wanting to check their email.
* Amavis - Filters incoming email for spam (via spamassassin) and virsus (via clamav)


Add;
We will also be using graylisting, which is a spam fighting tactic where the first email from a given user to one of our users is bounced for a few minutes. Proper mail servers will acknowledge the bound, wait the time and resend. Spam mailers though are usually fire-and-forget and will not resend, thus effectively blocking the spam message. This is a very effective method of blocking spam with minimal chance of losing real mail from real users. Any subsequent message from the user would be allowed through with no delay, provided the user had in fact resent the first message as requested.


<source lang="text">
== Install ==
# This tells postfix where to forward incoming email to, where appropriate.
virtual_alias_maps=pgsql:/etc/postfix/pgsql-virtual-alias-maps.cf
</source>


Reload;
To install the applications;


<source lang="bash">
<source lang="bash">
/etc/init.d/postfix reload
yum install postfix postfix-perl-scripts dovecot dovecot-pgsql spamassassin postgresql-server postgresql-plperl mutt
</source>
<source lang="text">
Reloading postfix:                                        [  OK  ]
</source>
</source>


I've setup a forward where <span class="code">digimer@alteeve.com</span> forwards to <span class="code">mkelly@alteeve.com</span>, so we will use that for the next test.
== Configuring Postfix ==
 
Installation requires several steps. The AN!Console database must be loaded. Various applications need to be installed. Postfix, Dovecot and helper applications need to be configured and so on.
 
This tutorial uses the following values that you may need to adjust;
* Database name; <span class="code">an_tools</span>
* Database user; <span class="code">alteeve</span>
* Database password; <span class="code">secret</span>
* Database host; <span class="code">127.0.0.1</span>
 
{{note|1=Do not use the database host "<span class="code">localhost</span>" unless you are certain you can connect to the DB using a standard [[unix]] socket.}}
 
=== Building Support for PostgreSQL ===
 
{{warning|1=We need to build our own RPM in order to support postgresql. This means we will have to disable <span class="code">postfix</span> from future updates, placing the onus on us to make sure critical updates are applied. This will require downloading the latest source RPMs, re-enabling postgres and recompile/reinstall.}}
 
Add the source [[RPM]] repository by adding the following;


<source lang="bash">
<source lang="bash">
postmap -q digimer@alteeve.com pgsql:/etc/postfix/pgsql-virtual-alias-maps.cf
vim /etc/yum.repos.d/CentOS-Base.repo
</source>
</source>
<source lang="text">
<source lang="bash">
mkelly@alteeve.com
# Source RPM repository
[base-source]
name=CentOS-$releasever - Base - Source
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os
baseurl=http://vault.centos.org/6.3/os/Source/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6
</source>
</source>


An email address with no forward should return nothing.
Now download the source RPM for postfix.


<source lang="bash">
<source lang="bash">
postmap -q mkelly@alteeve.com pgsql:/etc/postfix/pgsql-virtual-alias-maps.cf
yumdownloader --source postfix
</source>
</source>
<source lang="text">
<source lang="text">
<nothing returned>
Loaded plugins: fastestmirror
</source>
Loading mirror speeds from cached hostfile
* base: centos.vieth-server.de
* extras: centos.vieth-server.de
* updates: centos.vieth-server.de
base                              | 3.7 kB    00:00
base-source                        | 1.9 kB    00:00
extras                            | 3.5 kB    00:00
updates                            | 3.5 kB    00:00
No source RPM found for 2:postfix-2.6.6-2.2.el6_1.x86_64
./postfix-2.6.6-2.el6.src.rpm already exists and appears to be complete
nikko:/etc/postfix# rm postfix-2.6.6-2.el6.src.rpm
rm: remove regular file `postfix-2.6.6-2.el6.src.rpm'? y
nikko:/etc/postfix# yumdownloader --source postfix
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
* base: centos.vieth-server.de
* extras: centos.vieth-server.de
* updates: centos.vieth-server.de
No source RPM found for 2:postfix-2.6.6-2.2.el6_1.x86_64
postfix-2.6.6-2.el6.src.rpm        | 3.3 MB    00:00
</source>


Excellent.
Now that we have the postfix source RPM, we will install it.


=== Setup Postfix Mail Delivery via Dovecot ===
<source lang="bash">vim /etc/postfix/main.cf</source>
<source lang="bash">
<source lang="bash">
# this option is ignored, but may be useful for reference
rpm -Uvh postfix-2.6.6-2.el6.src.rpm
virtual_mailbox_base=/email
</source>
 
<source lang="text">
# deliver mail via dovecot
  1:postfix                warning: user mockbuild does not exist - using root
virtual_transport = dovecot
warning: group mockbuild does not exist - using root
warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root
warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root
warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root
warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root
warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root
warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root
warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root
########################################### [100%]
warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root
warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root
warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root
warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root
</source>


# prevent postfix from sending multiple recipients per delivery request,
Now edit the <span class="code">.spec</span> file to enable postgres support.
# since dovecot only supports one recipient for each delivery
dovecot_destination_recipient_limit = 1
</source>


Tell Postfix what virtual_transport "dovecot" means, and how to use it.
<source lang="bash">vim /etc/postfix/master.cf</source>
Append this:
<source lang="bash">
<source lang="bash">
dovecot  unix  -      n      n      -      -      pipe
cp ~/rpmbuild/SPECS/postfix.spec ~/rpmbuild/SPECS/postfix.spec.orig
  flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${recipient}
vim ~/rpmbuild/SPECS/postfix.spec
</source>
</source>


=== Setup Postfix SMTP Authentication using Dovecot ===
Make the following changes.


Dovecot provides an SMTP authentication mechanism to Postfix called SASL. Enabling this will require users to authenticate against the server before sending mail.
* Enable PostgreSQL support
<source lang="text">
%{?!PGSQL: %define PGSQL 1}
</source>


<source lang="bash">vim /etc/postfix/main.cf</source>
Increment the release version by one.
Append the following to enable smtp authentication:
<source lang="text">
<source lang="bash">
Release: 3%{?dist}
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
broken_sasl_auth_clients = yes
 
# allow authenticated users to send mail through Postfix SMTP
# more info at /usr/share/doc/postfix-2.6.6/README_FILES/SMTPD_ACCESS_README
smtpd_recipient_restrictions =
        permit_mynetworks
        permit_sasl_authenticated
        reject_unauth_destination
</source>
</source>


== Configuring Dovecot ==
We can see the changes here:
 
Dovecot handles writing incoming mail to the disk and moving/deleting mail as the user wishes. We're going to create a user and group called <span class="code">vmail</span> which will be used to manage the email stored on disk.


<source lang="bash">
<source lang="bash">
useradd -m vmail
diff -u ~/rpmbuild/SPECS/postfix.spec.orig ~/rpmbuild/SPECS/postfix.spec
mkdir /email
chown -R vmail:vmail /email
</source>
</source>
 
<source lang="diff">
Dovecot is configured in <span class="code">/etc/dovecot</span> and the main configuration file is <span class="code">dovecot.conf</span>.
--- /root/rpmbuild/SPECS/postfix.spec.orig      2012-02-11 16:54:54.495330859 -0500
 
+++ /root/rpmbuild/SPECS/postfix.spec  2012-02-11 16:53:39.873331101 -0500
<source lang="bash">
@@ -1,5 +1,5 @@
cp /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.orig
%{?!MYSQL: %define MYSQL 1}
vim /etc/dovecot/dovecot.conf
-%{?!PGSQL: %define PGSQL 0}
+%{?!PGSQL: %define PGSQL 1}
%define LDAP 2
%define PCRE 1
%define SASL 2
@@ -35,7 +35,7 @@
Name: postfix
Summary: Postfix Mail Transport Agent
Version: 2.6.6
-Release: 2%{?dist}
+Release: 3%{?dist}
Epoch: 2
Group: System Environment/Daemons
URL: http://www.postfix.org
</source>
</source>


Dovecot uses <span class="code">.d</span> style configuration files.
Now rebuild the RPM, which means we need to install the build tools.
 
* Authentication


<source lang="bash">
<source lang="bash">
cp /etc/dovecot/conf.d/10-auth.conf /etc/dovecot/conf.d/10-auth.conf.orig
yum groupinstall development
vim /etc/dovecot/conf.d/10-auth.conf
yum install db4-devel openldap-devel cyrus-sasl-devel pcre-devel mysql-devel postgresql-devel openssl-devel
rpmbuild -bb ~/rpmbuild/SPECS/postfix.spec
</source>
</source>
Tell dovecot to accept plain-text passwords (needed for some old email clients, you may not need to enable this).
<source lang="text">
<source lang="text">
disable_plaintext_auth = no
(compile output)
Processing files: postfix-debuginfo-2.6.6-3.el6.x86_64
Checking for unpackaged file(s): /usr/lib/rpm/check-files /root/rpmbuild/BUILDROOT/postfix-2.6.6-3.el6.x86_64
Wrote: /root/rpmbuild/RPMS/x86_64/postfix-2.6.6-3.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/postfix-perl-scripts-2.6.6-3.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/postfix-debuginfo-2.6.6-3.el6.x86_64.rpm
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.rymr5C
+ umask 022
+ cd /root/rpmbuild/BUILD
+ cd postfix-2.6.6
+ rm -rf /root/rpmbuild/BUILDROOT/postfix-2.6.6-3.el6.x86_64
+ exit 0
</source>
</source>


Tell it not to use the database, and not local users for mail delivery.
Install the updated postfix.


<source lang="bash">
rpm -Uvh ~/rpmbuild/RPMS/x86_64/postfix-2.6.6-3.el6.x86_64.rpm ~/rpmbuild/RPMS/x86_64/postfix-perl-scripts-2.6.6-3.el6.x86_64.rpm
</source>
<source lang="text">
<source lang="text">
#!include auth-system.conf.ext
Preparing...               ########################################### [100%]
!include auth-sql.conf.ext
  1:postfix                ########################################### [ 50%]
  2:postfix-perl-scripts  ########################################### [100%]
</source>
</source>


* Mail store
Now exclude <span class="code">postfix</span> from future updates.
 
Tell dovecot where to store the email. The <span class="code">%d</span> tells dovecot to substitute the user's domain name and <span class="code">%n</span> is substituted by the user's email name. For example, <span class="code">mkelly@alteeve.com</span> becomes <span class="code">/email/alteeve.com/mkelly</span>.


<source lang="bash">
<source lang="bash">
cp /etc/dovecot/conf.d/10-mail.conf /etc/dovecot/conf.d/10-mail.conf.orig
cp /etc/yum.conf /etc/yum.conf.orig
vim /etc/dovecot/conf.d/10-mail.conf
vim /etc/yum.conf
diff -u /etc/yum.conf.orig /etc/yum.conf
</source>
</source>
<source lang="text">
<source lang="text">
mail_location = mbox:/email/%d/%n
--- /etc/yum.conf.orig  2012-02-11 16:59:53.720079168 -0500
+++ /etc/yum.conf      2012-02-11 17:00:47.013331283 -0500
@@ -10,6 +10,7 @@
installonly_limit=5
bugtracker_url=http://bugs.centos.org/set_project.php?project_id=16&ref=http://bugs.centos.org/bug_report_page.php?category=yum
distroverpkg=centos-release
+exclude=postfix*
#  This is the default, if you make this bigger yum won't see if the metadata
# is newer on the remote and so you'll "gain" the bandwidth of not having to
</source>
</source>


* User authentication.
=== Basic Postfix Configuration ===


We need to tell dovecot where to look for passwords when authenticating a user. Where to look is controlled in the
Since we'll be using virtual domains, users, aliases and mailboxes, we'll need to start by commenting out some of the default options in Postfix. By default, Postfix is set up for small numbers of local users, and it only allows connections from the localhost. Our configuration will be more scalable, allowing many domains and users to be stored in the Postgres database.
<span class="code">auth-sql.conf.ext</span> file and is broken down into user and password lookups. We will want to first tell Dovecot which user to use when accessing the mail store on disk.


Comment out the following:
<source lang="bash">vim /etc/postfix/main.cf</source>
<source lang="bash">
<source lang="bash">
cp /etc/dovecot/conf.d/auth-sql.conf.ext /etc/dovecot/conf.d/auth-sql.conf.ext.orig
# inet_interfaces = localhost
vim /etc/dovecot/conf.d/auth-sql.conf.ext
# mydestination = $myhostname, localhost.$mydomain, localhost
# alias_maps = hash:/etc/aliases 
# alias_database = hash:/etc/aliases
</source>
</source>
<source lang="text">
 
userdb {
And uncomment/add these:
   driver = static
<source lang="bash">vim /etc/postfix/main.cf</source>
  args = uid=vmail gid=vmail home=/email/%d/%n allow_all_users=yes
<source lang="bash">
}
inet_interfaces = all   # allows us to connect and test from another machine
mynetworks = 192.168.1.0/32, 127.0.0.0/8  # use the IP or subnet of your test machine here
message_size_limit = 36700160 # increase max message size to 35MB to allow for ~25MB attachments
</source>
</source>


* Now configure the SQL server access details.
=== Setup Virtual Domain Lookup ===
 
This tells postfix how to find which domains we have.
 
<source lang="bash">
vim /etc/postfix/pgsql-virtual-mailbox-domains.cf
</source>
<source lang="text">
user = alteeve
password = secret
hosts = 127.0.0.1
dbname = an_tools
query = SELECT 1 FROM domains WHERE dom_name='%s'
</source>


{{note|1=Make sure that PostgreSQL has sufficient <span class="code">max_connections</span> set in <span class="code">/var/lib/pgsql/data/postgresql.conf</span> to handle enough connections for the expected number of email connections, plus other connections from other applications.}}
Now tell Postfix to use this new file by appending the following to the main postfix configuration file.


<source lang="bash">
<source lang="bash">
cp /usr/share/doc/dovecot-2.0.9/example-config/dovecot-sql.conf.ext /etc/dovecot/dovecot-sql.conf.ext
vim /etc/postfix/main.cf
chown root:root /etc/dovecot/dovecot-sql.conf.ext
</source>
chmod 600 /etc/dovecot/dovecot-sql.conf.ext
<source lang="bash">
vim /etc/dovecot/dovecot-sql.conf.ext
# Tell postfix to validate domains using our postgresql databae via the
# pgsql-virtual-mailbox-domains.cf
virtual_mailbox_domains=pgsql:/etc/postfix/pgsql-virtual-mailbox-domains.cf
</source>
</source>


Tell dovecot to use PostgreSQL.
Now reload postfix;


<source lang="bash">
/etc/init.d/postfix reload
</source>
<source lang="text">
<source lang="text">
driver = pgsql
Reloading postfix:                                        [  OK  ]
</source>
</source>
 
 
Configure the connection string.
Now we can test that domains resolve. In my case, I will test the look-up for <span class="code">alteeve.ca</span>.
 
 
{{note|1=If your database uses a password with a space character in it, quote the password. Ie: <span class="code">password='super secret'</span>.}}
<source lang="bash">
 
postmap -q alteeve.ca pgsql:/etc/postfix/pgsql-virtual-mailbox-domains.cf
<source lang="text">
</source>
connect = host=127.0.0.1 dbname=an_tools user=alteeve password=secret
<source lang="text">
</source>
1
 
</source>
Tell dovecot to accept plain-text passwords (this is needed for some stupid MS clients, this will probably change soon).
 
 
Now make sure it returns nothing when query a bad domain.
<source lang="text">
 
default_pass_scheme = PLAIN
<source lang="bash">
</source>
postmap -q example.com pgsql:/etc/postfix/pgsql-virtual-mailbox-domains.cf
 
</source>
Tell dovecot how to pull use the user's password.
<source lang="text">
<nothing returned>
</source>
 
=== Setup Mailbox Mapping ===
 
This section will tell postfix which users for a given domain are valid.
 
<source lang="bash">
vim /etc/postfix/pgsql-virtual-mailbox-maps.cf
</source>
<source lang="text">
user = alteeve
password = secret
hosts = 127.0.0.1
dbname = an_tools
query = SELECT 1 FROM email_file WHERE email='%s'
</source>
 
Tell postfix to use this new file when looking up users.
 
<source lang="bash">
vim /etc/postfix/main.cf
</source>
 
And add:
 
<source lang="text">
# Tell postfix which table to look in when validating a local user via their
# email address.
virtual_mailbox_maps=pgsql:/etc/postfix/pgsql-virtual-mailbox-maps.cf
</source>
 
Reload <span class="code">postfix<span>.
 
<source lang="bash">
/etc/init.d/postfix reload
</source>
<source lang="text">
Reloading postfix:                                        [  OK  ]
</source>
 
Now do a test of a valid user, which should return <span class="code">1</span>, and an invalid user, which should return nothing.
 
<source lang="bash">
postmap -q digimer@alteeve.ca pgsql:/etc/postfix/pgsql-virtual-mailbox-maps.cf
</source>
<source lang="text">
1
</source>
<source lang="bash">
postmap -q nobody@alteeve.ca pgsql:/etc/postfix/pgsql-virtual-mailbox-maps.cf
</source>
<source lang="text">
<nothing returned>
</source>
 
=== Setup Email Forwards ===
 
This will allow for email addresses to be forwarded to other email addresses.
 
<source lang="bash">
vim /etc/postfix/pgsql-virtual-alias-maps.cf
</source>
<source lang="text">
user = alteeve
password = secret
hosts = 127.0.0.1
dbname = an_tools
query = SELECT fwd_destination FROM forwards WHERE fwd_source='%s'
</source>
 
Now tell postfix where to look.
 
<source lang="bash">
vim /etc/postfix/main.cf
</source>
 
Add;
 
<source lang="text">
# This tells postfix where to forward incoming email to, where appropriate.
virtual_alias_maps=pgsql:/etc/postfix/pgsql-virtual-alias-maps.cf
</source>
 
Reload;
 
<source lang="bash">
/etc/init.d/postfix reload
</source>
<source lang="text">
Reloading postfix:                                        [  OK  ]
</source>
 
I've setup a forward where <span class="code">digimer@alteeve.ca</span> forwards to <span class="code">digimer@alteeve.ca</span>, so we will use that for the next test.
 
<source lang="bash">
postmap -q digimer@alteeve.ca pgsql:/etc/postfix/pgsql-virtual-alias-maps.cf
</source>
<source lang="text">
digimer@alteeve.ca
</source>
 
An email address with no forward should return nothing.
 
<source lang="bash">
postmap -q digimer@alteeve.ca pgsql:/etc/postfix/pgsql-virtual-alias-maps.cf
</source>
<source lang="text">
<nothing returned>
</source>
 
Excellent.
 
=== Setup Postfix Mail Delivery via Dovecot ===
 
Define a mail transport method in the main Postfix config.
<source lang="bash">vim /etc/postfix/main.cf</source>
<source lang="bash">
# this option is ignored, but may be useful for reference
virtual_mailbox_base=/email
 
# deliver mail via dovecot
virtual_transport = dovecot
 
# prevent postfix from sending multiple recipients per delivery request,
# since dovecot only supports one recipient for each delivery
dovecot_destination_recipient_limit = 1
</source>
 
Tell Postfix what virtual_transport "dovecot" means, and how to use it.
<source lang="bash">vim /etc/postfix/master.cf</source>
Append this for RHEL/CentOS 6 machines. For other distros, make sure that /usr/libexec/dovecot/deliver exists and change the path if necessary.
<source lang="bash">
dovecot  unix  -      n      n      -      -      pipe
  flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${recipient}
</source>
 
=== Setup Postfix SMTP Authentication using Dovecot ===
 
Dovecot provides an SMTP authentication mechanism to Postfix called SASL. Enabling this will require users to authenticate against the server before sending mail.
 
<source lang="bash">vim /etc/postfix/main.cf</source>
Append the following to enable smtp authentication:
<source lang="bash">
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
broken_sasl_auth_clients = yes
 
# allow authenticated users to send mail through Postfix SMTP
# more info at /usr/share/doc/postfix-2.6.6/README_FILES/SMTPD_ACCESS_README
smtpd_recipient_restrictions =
        permit_mynetworks
        permit_sasl_authenticated
        reject_unauth_destination
 
# general smtpd settings
# - reject clients that speak too early
# - reject mail from a null address to many recipients (usually spam)
smtpd_data_restrictions =
        reject_unauth_pipelining
        reject_multi_recipient_bounce
        permit
</source>
 
== Configuring Dovecot ==
 
Dovecot handles writing incoming mail to the disk and moving/deleting mail as the user wishes. We're going to create a user and group called <span class="code">vmail</span> which will be used to manage the email stored on disk.
 
<source lang="bash">
useradd -m vmail
mkdir /email
chown -R vmail:vmail /email
</source>
 
Dovecot is configured in <span class="code">/etc/dovecot</span> and the main configuration file is <span class="code">dovecot.conf</span>.
 
<source lang="bash">
cp /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.orig
vim /etc/dovecot/dovecot.conf
</source>
 
Dovecot uses <span class="code">.d</span> style configuration files.
 
* Authentication
 
<source lang="bash">
cp /etc/dovecot/conf.d/10-auth.conf /etc/dovecot/conf.d/10-auth.conf.orig
vim /etc/dovecot/conf.d/10-auth.conf
</source>
 
Tell dovecot to accept plain-text passwords (needed for some old email clients, you may not need to enable this).
 
<source lang="text">
disable_plaintext_auth = no
</source>
 
Tell it not to use the database, and not local users for mail delivery.
 
<source lang="text">
#!include auth-system.conf.ext
!include auth-sql.conf.ext
</source>
 
* Mail store
 
Tell dovecot where to store the email. The <span class="code">%d</span> tells dovecot to substitute the user's domain name and <span class="code">%n</span> is substituted by the user's email name. For example, <span class="code">digimer@alteeve.ca</span> becomes <span class="code">/email/alteeve.ca/mkelly</span>.
 
<source lang="bash">
cp /etc/dovecot/conf.d/10-mail.conf /etc/dovecot/conf.d/10-mail.conf.orig
vim /etc/dovecot/conf.d/10-mail.conf
</source>
<source lang="text">
mail_location = mbox:/email/%d/%n
</source>
 
=== Dovecot Authentication and SQL Settings ===
 
We need to tell dovecot where to look for passwords when authenticating a user. Where to look is controlled in the
<span class="code">auth-sql.conf.ext</span> file and is broken down into user and password lookups. We will want to first tell Dovecot which user to use when accessing the mail store on disk.
 
<source lang="bash">
cp /etc/dovecot/conf.d/auth-sql.conf.ext /etc/dovecot/conf.d/auth-sql.conf.ext.orig
vim /etc/dovecot/conf.d/auth-sql.conf.ext
</source>
<source lang="text">
userdb {
  driver = static
  args = uid=vmail gid=vmail home=/email/%d/%n allow_all_users=yes
}
</source>
 
* Now configure the SQL server access details.
 
{{note|1=Make sure that PostgreSQL has sufficient <span class="code">max_connections</span> set in <span class="code">/var/lib/pgsql/data/postgresql.conf</span> to handle enough connections for the expected number of email connections, plus other connections from other applications.}}
 
<source lang="bash">
cp /usr/share/doc/dovecot-2.0.9/example-config/dovecot-sql.conf.ext /etc/dovecot/dovecot-sql.conf.ext
chown root:root /etc/dovecot/dovecot-sql.conf.ext
chmod 600 /etc/dovecot/dovecot-sql.conf.ext
vim /etc/dovecot/dovecot-sql.conf.ext
</source>
 
Tell dovecot to use PostgreSQL.
 
<source lang="text">
driver = pgsql
</source>
 
Configure the connection string.
 
{{note|1=If your database uses a password with a space character in it, quote the password. Ie: <span class="code">password='super secret'</span>.}}
 
<source lang="text">
connect = host=127.0.0.1 dbname=an_tools user=alteeve password=secret
</source>
 
Tell dovecot to accept plain-text passwords (this is needed for some stupid MS clients, this will probably change soon).
 
<source lang="text">
default_pass_scheme = PLAIN
</source>
 
Tell dovecot how to pull use the user's password.
 
<source lang="text">
password_query = SELECT email, password FROM email_password WHERE email='%u'
</source>
 
The last thing to setup is the user query. The query needs to return the [[UID]] and [[GID]] of the <span class="code">vmail</span> user we setup earlier. To get it, you can use the <span class="code">id</span> command.
 
<source lang="bash">
id vmail
</source>
<source lang="text">
uid=503(vmail) gid=503(vmail) groups=503(vmail)
</source>
 
The numbers we want are <span class="code">503</span> and <span class="code">503</span> for the UID and GID, respectively. Knowing this, we can set the userdb SQL string.
 
<source lang="text">
user_query = SELECT '/email/'||file AS email_dir, '503' AS uid, '503' AS gid FROM email_file WHERE email='%u'
</source>
 
=== Configure Listener Sockets ===
 
Setup the authentication socket to allow the vmail user. This will allow Dovecot to access the user authentication socket.
 
<source lang="bash">
vim /etc/dovecot/conf.d/10-master.conf
</source>
<source lang="bash">
  unix_listener auth-userdb {
    mode = 0600
    user = vmail
    group = vmail
  }
</source>
 
Configure Dovecot to authenticate Postfix SMTP requests.
 
<source lang="bash">
vim /etc/dovecot/conf.d/10-master.conf
</source>
<source lang="bash">
  unix_listener smtp-auth {
    mode = 0600
    user = postfix
    group = postfix
    path = /var/spool/postfix/private/auth
  }
</source>
 
Tell Dovecot to increase the number of allowed connections and child processes to handle heavier loads.
 
<source lang="bash">
vim /etc/dovecot/conf.d/10-master.conf
</source>
<source lang="bash">
default_process_limit = 200
default_client_limit = 2000
</source>
 
=== Enable Logging ===
 
This is very useful for debugging an initial setup. It will place details about login attempts in /var/log/maillog.
 
<source lang="bash">vim /etc/dovecot/conf.d/10-logging.conf</source>
<source lang="bash">
log_path = syslog
auth_verbose = yes
auth_debug = yes
mail_debug = yes
</source>
 
At this point, it's a good idea to restart the Postfix and Dovecot services, and test out the basic configuration.
<source lang="bash">
service postfix restart
service dovecot restart
</source>
 
Watch the maillog while attempting to authenticate with an email client like Thunderbird.
<source lang="bash">
tail -f /var/log/maillog
</source>
 
If basic authentication is working, we can go ahead and add another layer of complexity on top of it: SSL.
 
== SSL/TLS ==
 
Add TLS support to Postfix, to encrypt SMTP authentication traffic.
<source lang="bash">vim /etc/postfix/main.cf</source>
<source lang="bash">
smtpd_use_tls = yes
smtpd_tls_auth_only = yes
smtpd_tls_cert_file = /etc/pki/CA/ssl_mail.alteeve.ca.crt
smtpd_tls_key_file = /etc/pki/CA/private/mail.alteeve.ca.key
smtpd_tls_loglevel = 1
</source>
 
Add TLS support to Dovecot, to encrypt IMAP authentication traffic.
<source lang="bash">vim /etc/dovecot/conf.d/10-ssl.conf </source>
<source lang="bash">
ssl = yes
 
# PEM encoded X.509 SSL/TLS certificate and private key.
ssl_cert = </etc/pki/CA/ssl_mail.alteeve.ca.crt
ssl_key = </etc/pki/CA/private/mail.alteeve.ca.key
 
# PEM encoded trusted certificate authority. Otherwise your CA will be untrusted.
# This is the intermediary certificate.
ssl_ca = </etc/pki/CA/RapidSSL_CA_bundle_alteeve.ca.pem
</source>
 
Dovecot prefers the following permissions for SSL certs, so set them accordingly.
<source lang="bash">
chmod 0444 /etc/pki/CA/ssl_mail.alteeve.ca.crt
chmod 0400 /etc/pki/CA/private/mail.alteeve.ca.key
chmod 0400 /etc/pki/CA/RapidSSL_CA_bundle_alteeve.ca.pem
</source>
 
Restart Postfix and Dovecot, then change your Thunderbird server options to 'STARTTLS'. If you're still able to connect to the mail server and send mail, proceed to the next section.
 
== User Password Encryption ==
 
In addition to SSL/TSL, which only encrypts the transport of user credentials, we're also  going to encrypt the passwords themselves. This will avoid storing any plaintext passwords in the Postgres database.
 
<source lang="bash">vim /etc/dovecot/conf.d/10-auth.conf</source>
Remove the "plain" authentication, and replace with cram-md5.
<source lang="bash">
disable_plaintext_auth = yes
auth_mechanisms = cram-md5
</source>
 
Any user credentials that were previously stored in plaintext will no longer work. To encrypt your password in a way that Dovecot recognizes, use the following command:
<source lang="bash">doveadm -v pw -s CRAM-MD5 -p mypassword</source>
It will return a hash like this.
<source lang="bash">
{CRAM-MD5}de5924752ad74e36bc271a8dc7fad4b2d341f21f05382f20dedf1fdfbd5a1717</source>
 
Take the entire hash, including the '{CRAM-MD5}' portion, and use it to replace the password entry in the database for that user. This will allow Dovecot to authenticate the user using the CRAM-MD5 auth mechanism.
 
To automate this process for all users in the database, you can look at the number of userid's there are and loop through them, encrypting and replacing each password.
 
<source lang="bash">
#!/bin/bash
#
# a script to encrypt the users.usr_password values of the an_tools database
 
export PGUSER="alteeve"
export PGPASSWORD='secret'
 
for usrid in {1..219}; do
 
    # grab the user's password, removing whitespace
    usrpass=$(psql -d an_tools -c "SELECT users.usr_password FROM users WHERE users.usr_id=$usrid;"\
| sed -n 3p | sed -e 's/^[ ]*//')
 
    if [[ "$usrpass" == *CRAM* ]]; then
        echo "Password for user #$usrid is already encrypted; skipping."
    else
        # encrypt and surround in single quotes for psql
        encrypted=\'$(doveadm -v pw -s CRAM-MD5 -p "$usrpass")\'
        echo "old password: [$usrpass] ; encrypted: $encrypted"
 
        # set password to encrypted value
        psql -d an_tools -c "UPDATE users SET usr_password=$encrypted WHERE usr_id=$usrid;"
    fi
done
 
unset PGUSER
unset PGPASSWORD
</source>
 
== Postgrey Greylisting ==
 
Enabling postgrey for anti-spam greylisting.
 
First install the RPMForge repos. (See [http://dak1n1.com/blog/3-getting-more-from-yum-with-rpmforge-and-epel-repos Dakini's blog] for details.)
 
<source lang="bash">yum -y install postgrey</source>
 
Create the config file with the following options. This will delay mail from untrusted sources by 6 minutes. A legitimate mailserver will resend the request after that time, and be allowed through. But spam is generally sent out only once, so those messages will drop.
<source lang="bash">vim /etc/sysconfig/postgrey</source>
<source lang="bash">OPTIONS="--unix=/var/spool/postfix/postgrey/socket --delay=360"</source>
 
Ensure that Postgrey starts on boot.
<source lang="bash">chkconfig --levels 345 postgrey on</source>
 
<source lang="bash">/etc/postfix/main.cf</source>
 
Configure Postfix to check SMTP requests through Postgrey. Postgrey will decide if the mail should be blocked or accepted.
<source lang="bash">
smtpd_recipient_restrictions =
        permit_mynetworks
        permit_sasl_authenticated
        reject_unauth_destination
        check_policy_service unix:postgrey/socket</source>
 
Restart Postfix and Postgrey to take affect.
<source lang="bash">
service postgrey start
service postfix restart
</source>
 
== RoundCube Web Mail ==
 
Install the packages (these require the [[EPEL]] repo);
 
<source lang="bash">
yum install roundcubemail php-pear-MDB2-Driver-pgsql
</source>
 
You need to set the timezone in the <span class="code">/etc/php.ini</span> file.
 
<source lang="bash">
cp /etc/php.ini /etc/php.ini.orig
vim /etc/php.ini
</source>
 
Set <span class="code">date.timezone</span> value. If you aren't sure of the format or name of your timezone, run <span class="code">tzselect</span> and follow the prompts. We want <span class="code">America/Toronto</span>.
 
<source lang="bash">
diff -u /etc/php.ini.orig /etc/php.ini
</source>
<source lang="diff">
--- /etc/php.ini.orig 2012-08-18 22:27:05.244670258 -0400
+++ /etc/php.ini 2012-08-18 21:49:37.926938864 -0400
@@ -943,7 +943,7 @@
[Date]
; Defines the default timezone used by the date functions
; http://www.php.net/manual/en/datetime.configuration.php#ini.date.timezone
-;date.timezone =
+date.timezone = America/Toronto
; http://www.php.net/manual/en/datetime.configuration.php#ini.date.default-latitude
;date.default_latitude = 31.7667
</source>
 
Create the database for roundcube
 
<source lang="bash">
su - postgres
createdb -O alteeve -E UNICODE roundcubemail
psql -U alteeve -D roundcubemail
\i /usr/share/doc/roundcubemail-0.5.4/SQL/postgres.initial.sql
</source>
 
Edit main configuration file
 
<source lang="bash">
vim /etc/roundcubemail/main.inc.php
</source>
<source lang="bash">
$rcmail_config['default_host'] = 'localhost';
$rcmail_config['smtp_server'] = 'tls://mail.alteeve.ca';
$rcmail_config['smtp_user'] = '%u';
$rcmail_config['smtp_pass'] = '%p';
$rcmail_config['smtp_auth_type'] = 'CRAM-MD5';
$rcmail_config['force_https'] = true;
$rcmail_config['use_https'] = true;
$rcmail_config['login_autocomplete'] = 1;
</source>
 
Now setup roundcube for connecting to our DB;
 
<source lang="bash">
cp /etc/roundcubemail/db.inc.php /etc/roundcubemail/db.inc.php.orig
vim /etc/roundcubemail/db.inc.php
</source>
 
Now set the connection string. Note to switch the DB driver to <span class="code">pgsql</span>.
 
<source lang="bash">
diff -u /etc/roundcubemail/db.inc.php.orig /etc/roundcubemail/db.inc.php
</source>
<source lang="diff">
--- /etc/roundcubemail/db.inc.php.orig 2012-05-06 13:53:52.000000000 -0400
+++ /etc/roundcubemail/db.inc.php 2012-05-06 15:45:30.000000000 -0400
@@ -18,7 +18,7 @@
// format is db_provider://user:password@host/database
// For examples see http://pear.php.net/manual/en/package.database.mdb2.intro-dsn.php
-$rcmail_config['db_dsnw'] = 'mysql://roundcube:pass@localhost/roundcubemail';
+$rcmail_config['db_dsnw'] = 'pgsql://alteeve:secret@localhost/roundcubemail';
// postgres example: 'pgsql://roundcube:pass@localhost/roundcubemail';
// Warning: for SQLite use absolute path in DSN:
</source>
 
Now setup roundcube to communicate with the mail server.
 
<source lang="bash">
cp /etc/roundcubemail/main.inc.php /etc/roundcubemail/main.inc.php.orig
vim /etc/roundcubemail/main.inc.php
</source>
 
There are several variables to set. Our server will talk to <span class="code">localhost</span> using <span class="code">[[tls]]</span> on port <span class="code">587</span> using <span class="code">[[CRAM_MD5]]</span> encryption. We use, and require, <span class="code">[[https]]</span> connections. There are a couple special values for querying the user's name and password from the database. Finally, we want to enable the user's browser's auto-complete functions and set the name shown to the users. Once all set, the <span class="code">diff</span> should be similar to the one below.
 
<source lang="bash">
diff -u /etc/roundcubemail/main.inc.php.orig /etc/roundcubemail/main.inc.php
</source>
<source lang="diff">
--- /etc/roundcubemail/main.inc.php.orig 2012-05-06 13:53:59.000000000 -0400
+++ /etc/roundcubemail/main.inc.php 2012-07-06 14:59:07.000000000 -0400
@@ -65,7 +65,7 @@
// %n - http hostname ($_SERVER['SERVER_NAME'])
// %d - domain (http hostname without the first part)
// For example %n = mail.domain.tld, %d = domain.tld
-$rcmail_config['default_host'] = '';
+$rcmail_config['default_host'] = 'localhost';
// TCP port used for IMAP connections
$rcmail_config['default_port'] = 143;
@@ -121,22 +121,22 @@
// %d - domain (http hostname without the first part)
// %z - IMAP domain (IMAP hostname without the first part)
// For example %n = mail.domain.tld, %d = domain.tld
-$rcmail_config['smtp_server'] = '';
+$rcmail_config['smtp_server'] = 'tls://mail.alteeve.ca';
// SMTP port (default is 25; 465 for SSL)
-$rcmail_config['smtp_port'] = 25;
+$rcmail_config['smtp_port'] = 587;
// SMTP username (if required) if you use %u as the username Roundcube
// will use the current username for login
-$rcmail_config['smtp_user'] = '';
+$rcmail_config['smtp_user'] = '%u';
// SMTP password (if required) if you use %p as the password Roundcube
// will use the current user's password for login
-$rcmail_config['smtp_pass'] = '';
+$rcmail_config['smtp_pass'] = '%p';
// SMTP AUTH type (DIGEST-MD5, CRAM-MD5, LOGIN, PLAIN or empty to use
// best server supported one)
-$rcmail_config['smtp_auth_type'] = '';
+$rcmail_config['smtp_auth_type'] = 'CRAM-MD5';
// Optional SMTP authentication identifier to be used as authorization proxy
$rcmail_config['smtp_auth_cid'] = null;
@@ -179,16 +179,16 @@
// enforce connections over https
// with this option enabled, all non-secure connections will be redirected.
// set the port for the ssl connection as value of this option if it differs from the default 443
-$rcmail_config['force_https'] = false;
+$rcmail_config['force_https'] = true;
// tell PHP that it should work as under secure connection
// even if it doesn't recognize it as secure ($_SERVER['HTTPS'] is not set)
// e.g. when you're running Roundcube behind a https proxy
-$rcmail_config['use_https'] = false;
+$rcmail_config['use_https'] = true;
// Allow browser-autocompletion on login form.
// 0 - disabled, 1 - username and host only, 2 - username, host, password
-$rcmail_config['login_autocomplete'] = 0;
+$rcmail_config['login_autocomplete'] = 1;
// If users authentication is not case sensitive this must be enabled.
// You can also use it to force conversion of logins to lower case.
@@ -261,7 +261,7 @@
$rcmail_config['useragent'] = 'Roundcube Webmail/'.RCMAIL_VERSION;
// use this name to compose page titles
-$rcmail_config['product_name'] = 'Roundcube Webmail';
+$rcmail_config['product_name'] = 'AN!Mail';
// try to load host-specific configuration
// see http://trac.roundcube.net/wiki/Howto_Config for more details
</source>
 
That should be it.
 
==== Error No. [500] ====
 
After a recent OS update, 6.3 to 6.4, I started to get:
 
<source lang="text">
Error No. [500]
</source>
 
When trying to log into Round Cube. When I <span class="code">tail</span>'ed <span class="code">/var/www/ssl_alteeve.ca/logs/error.log</span>, there were two errors;
 
<source lang="text">
[Tue Sep 03 10:39:05 2013] [error] [client 108.168.16.38] PHP Warning:  Error writing to log file /var/log/roundcubemail/errors; Please check permissions in /usr/share/roundcubemail/program/include/main.inc on line 1965, referer: https://alteeve.ca/m/
[Tue Sep 03 10:39:05 2013] [error] [client 108.168.16.38] PHP Notice:  Could not perform encryption; make sure Mcrypt is installed or lib/des.inc is available in /usr/share/roundcubemail/program/include/main.inc on line 2120, referer: https://alteeve.ca/m/
</source>
 
Fixing the first was easy. The owner on <span class="code">/var/log/roundcubemail/errors</span> was <span class="code">root:apache</span> and the mode was <span class="code">644</span>, so a quick;
 
<source lang="bash">
chmod 664 /var/log/roundcubemail/errors
</source>
 
Resolved that issue. Then I <span class="code">tail</span>'ed the roundcube log and still saw the "Mcrypt" error. I found [https://www.centos.org/modules/newbb/viewtopic.php?topic_id=42045&forum=56 this post] which had the fix. The trick was to alter <span class="code">/etc/php.d/mcrypt.ini.orig</span>.
 
<source lang="bash">
cp /etc/php.d/mcrypt.ini /etc/php.d/mcrypt.ini.orig
vim /etc/php.d/mcrypt.ini
</source>
 
Change <span class="code">module.so</span> to <span class="code">mcrypt.so</span>, save and <span class="code">reload</span> apache.
 
<source lang="bash">
diff -u /etc/php.d/mcrypt.ini.orig /etc/php.d/mcrypt.ini
</source>
<source lang="diff">
--- /etc/php.d/mcrypt.ini.orig 2013-09-03 11:10:26.375001302 -0400
+++ /etc/php.d/mcrypt.ini 2013-09-03 10:46:52.340999323 -0400
@@ -1,2 +1,3 @@
; Enable mcrypt extension module
-extension=module.so
+;extension=module.so
+extension=mcrypt.so
</source>
 
Reload <span class="code">httpd</span>;
 
<source lang="bash">
/etc/init.d/httpd reload
</source>
<source lang="text">
Reloading httpd:
</source>
 
RoundCube should now work again.
 
==== Adding a password-reset link to the login page ====
 
Edit the login page template to insert the AN!Console password recovery link.
 
<source lang="bash">
vim /usr/share/roundcubemail/skins/default/templates/login.html</source>
 
(The part we're adding is the '<a href=""></a>'. Other parts of the template file are included here as a reference.)
<source lang="html4strict">
<div id="login-form">
<div class="boxtitle"><roundcube:label name="welcome" /></div>
<div class="boxcontent">
 
<form name="form" action="./" method="post">
<roundcube:object name="loginform" form="form" />
 
<p style="text-align:center;"><input type="submit" class="button mainaction" value="<roundcube:label name='login' />" /></p>
 
</form>
<a href="../../cgi-bin/t/password.cgi">Forgot your password?</a>
</div>
</div>
</source>
 
= Bugzilla =
 
This tutorial covers installing bugzilla 4.4 on [https://alteeve.ca/b/ AN!]'s bugzilla server.
 
== Installing Bugzilla ==
 
* Installed on a fresh minimal CentOS / RHEL 6.4 install.
* Installed at: <span class="code">/var/www/ssl_bugs.alteeve.ca/html/</span> on a dedicated server.
* Databases hosted on an external server running PostgreSQL.
 
Setup your webserver as above. Be sure to use SSL certificates! In this case, we will host our bugzilla at [https://bugs.alteeve.ca https://bugs.alteeve.ca].
 
Create the working directory, go to that directory, download the 4.4 install, extract it and switch into the created <span class="code">bugzilla-4.4</span> directory.
 
<source lang="bash">
mkdir -p /var/www/{bugs.alteeve.ca,ssl_bugs.alteeve.ca}/{html,logs,cgi-bin,temp}
cd /var/www/ssl_bugs.alteeve.ca/temp/
wget -c http://ftp.mozilla.org/pub/mozilla.org/webtools/bugzilla-4.4.tar.gz
tar -xvzf bugzilla-4.4.tar.gz
cd bugzilla-4.4
</source>
 
Install dependent RPMs;
 
<source lang="bash">
yum groupinstall development
yum install perl-ExtUtils-MakeMaker perl-GD perl-GDTextUtil perl-MIME-tools perl-XML-Twig perl-DBD-Pg openssl-devel mod_perl-devel \
            mod_perl patchutils perl-Authen-SASL perl-BSD-Resource perl-CPAN perl-Class-Singleton perl-Convert-ASN1 perl-DateTime \
            perl-Digest-HMAC perl-Digest-SHA1 vim rsync wget acpid gpm mlocate syslinux perl-GSSAPI perl-LDAP perl-List-MoreUtils \
            perl-Params-Validate perl-SOAP-Lite perl-Test-Simple perl-Text-Iconv perl-XML-Filter-BufferText perl-XML-NamespaceSupport \
            perl-XML-SAX-Writer httpd cvs postgresql
</source>
 
Remove RPMs with perl modules that are too old.
 
<source lang="bash">
yum remove perl-TimeDate perl-List-MoreUtils
</source>
 
Install from CPAN remaining needed perl modules.
 
<source lang="bash">
# Don't ask us questions
export PERL_MM_USE_DEFAULT=1
 
# Optional modules
perl -MCPAN -e 'install("YAML")'
perl -MCPAN -e 'install Chart::Lines'
perl -MCPAN -e 'install Template::Plugin::GD::Image'
perl -MCPAN -e 'install GD::Graph'
perl -MCPAN -e 'install MIME::Parser'
perl -MCPAN -e 'install PatchReader'
perl -MCPAN -e 'install Net::SMTP::SSL'
perl -MCPAN -e 'install Authen::Radius'
perl -MCPAN -e 'install SOAP::Lite'
perl -MCPAN -e 'install JSON::RPC'
perl -MCPAN -e 'install JSON::XS'
perl -MCPAN -e 'install Test::Taint'
perl -MCPAN -e 'install HTML::Scrubber'
perl -MCPAN -e 'install Encode::Detect'
perl -MCPAN -e 'install Email::Reply'
perl -MCPAN -e 'install HTML::FormatText::WithLinks'
perl -MCPAN -e 'install TheSchwartz'
perl -MCPAN -e 'install Daemon::Generic'
perl -MCPAN -e 'install Apache2::SizeLimit'
perl -MCPAN -e 'install File::MimeInfo::Magic'
 
# Required modules
perl -MCPAN -e 'install DateTime'
perl -MCPAN -e 'install Email::Send'
perl -MCPAN -e 'install Math::Random::ISAAC'
</source>
 
If the above completed successfully, you should be able to run bugzilla's <span class="code">checksetup.pl</span> script and have no missing modules, save for the DB drivers we're not going to use.
 
<source lang="bash">
./checksetup.pl --check-modules
</source>
<source lang="text">
* This is Bugzilla 4.4 on perl 5.10.1
* Running on Linux 2.6.32-358.18.1.el6.x86_64 #1 SMP Wed Aug 28 17:19:38 UTC 2013
 
Checking perl modules...
Checking for              CGI.pm (v3.51)    ok: found v3.63
Checking for          Digest-SHA (any)      ok: found v5.47
Checking for            TimeDate (v2.23)    ok: found v2.24
Checking for            DateTime (v0.28)    ok: found v1.03
Checking for    DateTime-TimeZone (v0.71)    ok: found v1.60
Checking for                  DBI (v1.54)    ok: found v1.609
Checking for    Template-Toolkit (v2.22)    ok: found v2.25
Checking for          Email-Send (v2.04)    ok: found v2.199
Checking for          Email-MIME (v1.904)    ok: found v1.924
Checking for                  URI (v1.37)    ok: found v1.60
Checking for      List-MoreUtils (v0.32)    ok: found v0.33
Checking for    Math-Random-ISAAC (v1.0.1)    ok: found v1.004
 
Checking available perl DBD modules...
Checking for              DBD-Pg (v2.7.0)    ok: found v2.15.1
Checking for            DBD-mysql (v4.001)    not found
Checking for          DBD-SQLite (v1.29)    not found
Checking for          DBD-Oracle (v1.19)    not found
 
The following Perl modules are optional:
Checking for                  GD (v1.20)    ok: found v2.44
Checking for                Chart (v2.1)      ok: found v2.4.6
Checking for          Template-GD (any)      ok: found v1.56
Checking for          GDTextUtil (any)      ok: found v0.86
Checking for              GDGraph (any)      ok: found v1.48
Checking for          MIME-tools (v5.406)    ok: found v5.504
Checking for          libwww-perl (any)      ok: found v6.05
Checking for            XML-Twig (any)      ok: found v3.34
Checking for          PatchReader (v0.9.6)    ok: found v0.9.6
Checking for            perl-ldap (any)      ok: found v0.40
Checking for          Authen-SASL (any)      ok: found v2.13
Checking for        Net-SMTP-SSL (v1.01)    ok: found v1.01
Checking for          RadiusPerl (any)      ok: found v0.23
Checking for            SOAP-Lite (v0.712)    ok: found v1.06
Checking for            JSON-RPC (any)      ok: found v1.03
Checking for              JSON-XS (v2.0)      ok: found v2.34
Checking for          Test-Taint (any)      ok: found v1.06
Checking for          HTML-Parser (v3.40)    ok: found v3.64
Checking for        HTML-Scrubber (any)      ok: found v0.09
Checking for              Encode (v2.21)    ok: found v2.35
Checking for        Encode-Detect (any)      ok: found v1.01
Checking for          Email-Reply (any)      ok: found v1.203
Checking for HTML-FormatText-WithLinks (v0.13)    ok: found v0.14
Checking for          TheSchwartz (any)      ok: found v1.10
Use of uninitialized value $ENV{"FLOCK_FORKING_USE"} in string eq at /usr/local/share/perl5/File/Flock/Forking.pm line 13, <DATA> line 522.
Checking for      Daemon-Generic (any)      ok: found v0.83
Checking for            mod_perl (v1.999022) ok: found v2.000004
Checking for    Apache-SizeLimit (v0.96)    ok: found v0.96
Checking for        File-MimeInfo (any)      ok: found v0.18
Checking for          IO-stringy (any)      ok: found v2.110
Checking for          mod_headers (any)      ok
Checking for          mod_expires (any)      ok
Checking for              mod_env (any)      ok
</source>
 
Excellent!
 
Now re-run <span class="code">checksetup.pl</span> by itself;
 
<source lang="bash">
./checksetup.pl
</source>
<source lang="text">
* This is Bugzilla 4.4 on perl 5.10.1
* Running on Linux 2.6.32-358.18.1.el6.x86_64 #1 SMP Wed Aug 28 17:19:38 UTC 2013
 
Checking perl modules...
Checking for              CGI.pm (v3.51)    ok: found v3.63
Checking for          Digest-SHA (any)      ok: found v5.47
Checking for            TimeDate (v2.23)    ok: found v2.24
Checking for            DateTime (v0.28)    ok: found v1.03
Checking for    DateTime-TimeZone (v0.71)    ok: found v1.60
Checking for                  DBI (v1.54)    ok: found v1.609
Checking for    Template-Toolkit (v2.22)    ok: found v2.25
Checking for          Email-Send (v2.04)    ok: found v2.199
Checking for          Email-MIME (v1.904)    ok: found v1.924
Checking for                  URI (v1.37)    ok: found v1.60
Checking for      List-MoreUtils (v0.32)    ok: found v0.33
Checking for    Math-Random-ISAAC (v1.0.1)    ok: found v1.004
 
Checking available perl DBD modules...
Checking for              DBD-Pg (v2.7.0)    ok: found v2.15.1
Checking for            DBD-mysql (v4.001)    not found
Checking for          DBD-SQLite (v1.29)    not found
Checking for          DBD-Oracle (v1.19)    not found
 
The following Perl modules are optional:
Checking for                  GD (v1.20)    ok: found v2.44
Checking for                Chart (v2.1)      ok: found v2.4.6
Checking for          Template-GD (any)      ok: found v1.56
Checking for          GDTextUtil (any)      ok: found v0.86
Checking for              GDGraph (any)      ok: found v1.48
Checking for          MIME-tools (v5.406)    ok: found v5.504
Checking for          libwww-perl (any)      ok: found v6.05
Checking for            XML-Twig (any)      ok: found v3.34
Checking for          PatchReader (v0.9.6)    ok: found v0.9.6
Checking for            perl-ldap (any)      ok: found v0.40
Checking for          Authen-SASL (any)      ok: found v2.13
Checking for        Net-SMTP-SSL (v1.01)    ok: found v1.01
Checking for          RadiusPerl (any)      ok: found v0.23
Checking for            SOAP-Lite (v0.712)    ok: found v1.06
Checking for            JSON-RPC (any)      ok: found v1.03
Checking for              JSON-XS (v2.0)      ok: found v2.34
Checking for          Test-Taint (any)      ok: found v1.06
Checking for          HTML-Parser (v3.40)    ok: found v3.64
Checking for        HTML-Scrubber (any)      ok: found v0.09
Checking for              Encode (v2.21)    ok: found v2.35
Checking for        Encode-Detect (any)      ok: found v1.01
Checking for          Email-Reply (any)      ok: found v1.203
Checking for HTML-FormatText-WithLinks (v0.13)    ok: found v0.14
Checking for          TheSchwartz (any)      ok: found v1.10
Use of uninitialized value $ENV{"FLOCK_FORKING_USE"} in string eq at /usr/local/share/perl5/File/Flock/Forking.pm line 13, <DATA> line 522.
Checking for      Daemon-Generic (any)      ok: found v0.83
Checking for            mod_perl (v1.999022) ok: found v2.000004
Checking for    Apache-SizeLimit (v0.96)    ok: found v0.96
Checking for        File-MimeInfo (any)      ok: found v0.18
Checking for          IO-stringy (any)      ok: found v2.110
Checking for          mod_headers (any)      ok
Checking for          mod_expires (any)      ok
Checking for              mod_env (any)      ok
Reading ./localconfig...
 
This version of Bugzilla contains some variables that you may want to
change and adapt to your local settings. The following variables are
new to ./localconfig since you last ran checksetup.pl:
 
create_htaccess, webservergroup, use_suexec, db_driver, db_host,
db_name, db_user, db_pass, db_port, db_sock, db_check, index_html,
cvsbin, interdiffbin, diffpath, site_wide_secret
 
Please edit the file ./localconfig and then re-run checksetup.pl
to complete your installation.
</source>
 
This will generate a file called <span class="code">localconfig</span> with initial values. Make a backup of this and then edit it.
 
<source lang="bash">
cp localconfig localconfig.orig
vim localconfig
</source>
 
Change the values as needed. Below is the <span class="code">diff</span> of the configuration use by AN!.
 
<source lang="bash">
diff -u localconfig.orig localconfig
</source>
<source lang="diff">
--- localconfig.orig 2013-09-03 18:21:10.265003147 -0400
+++ localconfig 2013-09-03 18:38:00.231000167 -0400
@@ -47,30 +47,30 @@
# can be obtained by listing Bugzilla/DB directory - every module corresponds
# to one supported database and the name of the module (before ".pm")
# corresponds to a valid value for this variable.
-$db_driver = 'mysql';
+$db_driver = 'Pg';
# The DNS name or IP address of the host that the database server runs on.
-$db_host = 'localhost';
+$db_host = 'vm09-db01.alteeve.ca';
# The name of the database. For Oracle, this is the database's SID. For
# SQLite, this is a name (or path) for the DB file.
-$db_name = 'bugs';
+$db_name = 'an_bugs';
# Who we connect to the database as.
-$db_user = 'bugs';
+$db_user = 'alteeve';
# Enter your database password here. It's normally advisable to specify
# a password for your bugzilla database user.
# If you use apostrophe (') or a backslash (\) in your password, you'll
# need to escape it by preceding it with a '\' character. (\') or (\)
# (It is far simpler to just not use those characters.)
-$db_pass = '';
+$db_pass = 'secret';
# Sometimes the database server is running on a non-standard port. If that's
# the case for your database server, set this to the port number that your
# database server is running on. Setting this to 0 means "use the default
# port for my database server."
-$db_port = 0;
+$db_port = 5432;
# MySQL Only: Enter a path to the unix socket for MySQL. If this is
# blank, then MySQL's compiled-in default will be used. You probably
</source>
 
Create the <span class="code">an_bugs</span> database.
 
<source lang="bash">
createdb an_bugs -h vm09-db01.alteeve.ca -U alteeve
</source>
<source lang="text">
Password:
</source>
 
Rerun <span class="code">checksetup.pl</span> again to verify your new configuration is sensible.
 
<source lang="bash">
./checksetup.pl
</source>
<source lang="text">
* This is Bugzilla 4.4 on perl 5.10.1
* Running on Linux 2.6.32-358.18.1.el6.x86_64 #1 SMP Wed Aug 28 17:19:38 UTC 2013
 
Checking perl modules...
Checking for              CGI.pm (v3.51)    ok: found v3.63
Checking for          Digest-SHA (any)      ok: found v5.47
Checking for            TimeDate (v2.23)    ok: found v2.24
Checking for            DateTime (v0.28)    ok: found v1.03
Checking for    DateTime-TimeZone (v0.71)    ok: found v1.60
Checking for                  DBI (v1.54)    ok: found v1.609
Checking for    Template-Toolkit (v2.22)    ok: found v2.25
Checking for          Email-Send (v2.04)    ok: found v2.199
Checking for          Email-MIME (v1.904)    ok: found v1.924
Checking for                  URI (v1.37)    ok: found v1.60
Checking for      List-MoreUtils (v0.32)    ok: found v0.33
Checking for    Math-Random-ISAAC (v1.0.1)    ok: found v1.004
 
Checking available perl DBD modules...
Checking for              DBD-Pg (v2.7.0)    ok: found v2.15.1
Checking for            DBD-mysql (v4.001)    not found
Checking for          DBD-SQLite (v1.29)    not found
Checking for          DBD-Oracle (v1.19)    not found
 
The following Perl modules are optional:
Checking for                  GD (v1.20)    ok: found v2.44
Checking for                Chart (v2.1)      ok: found v2.4.6
Checking for          Template-GD (any)      ok: found v1.56
Checking for          GDTextUtil (any)      ok: found v0.86
Checking for              GDGraph (any)      ok: found v1.48
Checking for          MIME-tools (v5.406)    ok: found v5.504
Checking for          libwww-perl (any)      ok: found v6.05
Checking for            XML-Twig (any)      ok: found v3.34
Checking for          PatchReader (v0.9.6)    ok: found v0.9.6
Checking for            perl-ldap (any)      ok: found v0.40
Checking for          Authen-SASL (any)      ok: found v2.13
Checking for        Net-SMTP-SSL (v1.01)    ok: found v1.01
Checking for          RadiusPerl (any)      ok: found v0.23
Checking for            SOAP-Lite (v0.712)    ok: found v1.06
Checking for            JSON-RPC (any)      ok: found v1.03
Checking for              JSON-XS (v2.0)      ok: found v2.34
Checking for          Test-Taint (any)      ok: found v1.06
Checking for          HTML-Parser (v3.40)    ok: found v3.64
Checking for        HTML-Scrubber (any)      ok: found v0.09
Checking for              Encode (v2.21)    ok: found v2.35
Checking for        Encode-Detect (any)      ok: found v1.01
Checking for          Email-Reply (any)      ok: found v1.203
Checking for HTML-FormatText-WithLinks (v0.13)    ok: found v0.14
Checking for          TheSchwartz (any)      ok: found v1.10
Use of uninitialized value $ENV{"FLOCK_FORKING_USE"} in string eq at /usr/local/share/perl5/File/Flock/Forking.pm line 13, <DATA> line 522.
Checking for      Daemon-Generic (any)      ok: found v0.83
Checking for            mod_perl (v1.999022) ok: found v2.000004
Checking for    Apache-SizeLimit (v0.96)    ok: found v0.96
Checking for        File-MimeInfo (any)      ok: found v0.18
Checking for          IO-stringy (any)      ok: found v2.110
Checking for          mod_headers (any)      ok
Checking for          mod_expires (any)      ok
Checking for              mod_env (any)      ok
Reading ./localconfig...
Checking for              DBD-Pg (v2.7.0)    ok: found v2.15.1
Checking for          PostgreSQL (v8.03.0000) ok: found v08.04.1300
 
Adding new table bz_schema...
Initializing bz_schema...
Creating tables...
Creating function array_accum...
Removing index 'bugs_fulltext_comments_idx' from the bugs_fulltext table...
Removing index 'bugs_fulltext_comments_noprivate_idx' from the bugs_fulltext table...
Adding new index 'profiles_login_name_lower_idx' to the profiles table ...
Adding new index 'fielddefs_name_lower_idx' to the fielddefs table ...
Adding new index 'keyworddefs_name_lower_idx' to the keyworddefs table ...
Adding new index 'products_name_lower_idx' to the products table ...
Setting up choices for standard drop-down fields:
  bug_status priority rep_platform resolution op_sys bug_severity
Creating ./data directory...
Creating ./data/attachments directory...
Creating ./data/db directory...
Creating ./data/extensions directory...
Creating ./data/mining directory...
Creating ./data/webdot directory...
Creating ./graphs directory...
Creating ./skins/custom directory...
Creating ./data/extensions/additional...
Creating ./data/mailer.testfile...
Creating ./Bugzilla/.htaccess...
Creating ./data/.htaccess...
Creating ./data/attachments/.htaccess...
Creating ./data/webdot/.htaccess...
Creating ./graphs/.htaccess...
Creating ./lib/.htaccess...
Creating ./template/.htaccess...
Creating contrib/.htaccess...
Creating t/.htaccess...
Creating xt/.htaccess...
Precompiling templates...done.
Fixing file permissions...
Initializing "Dependency Tree Changes" email_setting ...
Initializing "Product/Component Changes" email_setting ...
Marking closed bug statuses as such...
Creating default classification 'Unclassified'...
Setting up foreign keys...
Setting up the default status workflow...
Creating default groups...
Setting up user preferences...
 
Looks like we don't have an administrator set up yet. Either this is
your first time using Bugzilla, or your administrator's privileges
might have accidentally been deleted.
 
</source>
<source lang="text">
Enter the e-mail address of the administrator: admin@alteeve.ca
</source>
<source lang="text">
Enter the real name of the administrator: Alteeve Admin
</source>
<source lang="text">
Enter a password for the administrator account:
Please retype the password to verify:
</source>
<source lang="text">
admin@alteeve.ca is now set up as an administrator.
Creating initial dummy product 'TestProduct'...
 
Now that you have installed Bugzilla, you should visit the 'Parameters'
page (linked in the footer of the Administrator account) to ensure it
is set up as you wish - this includes setting the 'urlbase' option to
the correct URL.
checksetup.pl complete.
</source>
 
== Configure Apache for Bugzilla ==
 
Now move the files into the web root, switch to the web root document
 
<source lang="bash">
rsync -av /var/www/ssl_bugs.alteeve.ca/temp/bugzilla-4.4/* /var/www/ssl_bugs.alteeve.ca/html/
chown -R apache:apache /var/www/ssl_bugs.alteeve.ca
cd /var/www/ssl_bugs.alteeve.ca/html
</source>
 
Next, setup the apache configuration files. We'll need two;
* <span class="code">bugs.alteeve.ca.conf</span>; rewrite all non-SSL requests to their SSL version.
* <span class="code">ssl_bugs.alteeve.ca.conf</span>; The actual configuration file.
 
The configuration to rewrite any incoming <span class="code">http://</span> requests to <span class="code">https://</span> requests.
 
<syntaxhighlight lang="bash">
vim /etc/httpd/conf.d/bugs.alteeve.ca.conf
</syntaxhighlight>
<syntaxhighlight lang="text">
<VirtualHost *:80>
ServerAdmin admin@alteeve.ca
 
ServerName bugs.alteeve.ca
 
RedirectMatch permanent (.*) https://bugs.alteeve.ca$1
 
ErrorLog /var/www/bugs.alteeve.ca/logs/error.log
 
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel debug
 
CustomLog /var/www/bugs.alteeve.ca/logs/access.log combined
ServerSignature On
</VirtualHost>
</syntaxhighlight>
 
Now write the actual [[SSL]]-enabled configuration for bugzilla.
 
<syntaxhighlight lang="bash">
vim /etc/httpd/conf.d/ssl_bugs.alteeve.ca.conf
</syntaxhighlight>
<syntaxhighlight lang="text">
<VirtualHost *:443>
ServerAdmin admin@alteeve.ca
 
ServerName bugs.alteeve.ca
 
#DirectoryIndex index.cgi
# We can haz security?
SSLEngine on
SSLProtocol all
SSLCACertificateFile /etc/pki/CA/RapidSSL_CA_bundle.pem
SSLCertificateFile /etc/pki/CA/ssl_bugs.alteeve.ca.crt
SSLCertificateKeyFile /etc/pki/CA/private/bugs.alteeve.ca.key
   
DocumentRoot /var/www/ssl_bugs.alteeve.ca/html/
Alias /w /var/www/ssl_bugs.alteeve.ca/html/index.php
<Directory /var/www/ssl_bugs.alteeve.ca/html>
AddHandler cgi-script .cgi
Options +ExecCGI
DirectoryIndex index.cgi index.html
AllowOverride Limit FileInfo Indexes Options
#Options +Includes Indexes FollowSymLinks MultiViews
#AllowOverride All
#Order allow,deny
#allow from all
</Directory>
 
ErrorLog /var/www/ssl_bugs.alteeve.ca/logs/error.log
TransferLog /var/www/ssl_bugs.alteeve.ca/logs/transfer.log
 
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel info
 
CustomLog /var/www/ssl_bugs.alteeve.ca/logs/access.log combined
ServerSignature On
</VirtualHost>
</syntaxhighlight>
 
Verify the syntax;
 
<syntaxhighlight lang="bash">
apachectl -t
</syntaxhighlight>
<syntaxhighlight lang="text">
Syntax OK
</syntaxhighlight>
<syntaxhighlight lang="bash">
apachectl -S
</syntaxhighlight>
<syntaxhighlight lang="text">
VirtualHost configuration:
wildcard NameVirtualHosts and _default_ servers:
*:443                  bugs.alteeve.ca (/etc/httpd/conf.d/ssl_bugs.alteeve.ca.conf:1)
*:80                  is a NameVirtualHost
        default server unknown.alteeve.ca (/etc/httpd/conf.d/00_default.conf:1)
        port 80 namevhost unknown.alteeve.ca (/etc/httpd/conf.d/00_default.conf:1)
        port 80 namevhost bugs.alteeve.ca (/etc/httpd/conf.d/bugs.alteeve.ca.conf:1)
        port 80 namevhost bugs.alteeve.ca (/etc/httpd/conf.d/ssl.conf:74)
Syntax OK
</syntaxhighlight>
 
Run a final check of the bugzilla configuration;
 
<syntaxhighlight lang="bash">
cd /var/www/ssl_bugs.alteeve.ca/html
./checksetup.pl
</syntaxhighlight>
<syntaxhighlight lang="text">
* This is Bugzilla 4.4 on perl 5.10.1
* Running on Linux 2.6.32-358.18.1.el6.x86_64 #1 SMP Wed Aug 28 17:19:38 UTC 2013
 
Checking perl modules...
Checking for              CGI.pm (v3.51)    ok: found v3.63
Checking for          Digest-SHA (any)      ok: found v5.47
Checking for            TimeDate (v2.23)    ok: found v2.24
Checking for            DateTime (v0.28)    ok: found v1.03
Checking for    DateTime-TimeZone (v0.71)    ok: found v1.60
Checking for                  DBI (v1.54)    ok: found v1.609
Checking for    Template-Toolkit (v2.22)    ok: found v2.25
Checking for          Email-Send (v2.04)    ok: found v2.199
Checking for          Email-MIME (v1.904)    ok: found v1.924
Checking for                  URI (v1.37)    ok: found v1.60
Checking for      List-MoreUtils (v0.32)    ok: found v0.33
Checking for    Math-Random-ISAAC (v1.0.1)    ok: found v1.004
 
Checking available perl DBD modules...
Checking for              DBD-Pg (v2.7.0)    ok: found v2.15.1
Checking for            DBD-mysql (v4.001)    not found
Checking for          DBD-SQLite (v1.29)    not found
Checking for          DBD-Oracle (v1.19)    not found
 
The following Perl modules are optional:
Checking for                  GD (v1.20)    ok: found v2.44
Checking for                Chart (v2.1)      ok: found v2.4.6
Checking for          Template-GD (any)      ok: found v1.56
Checking for          GDTextUtil (any)      ok: found v0.86
Checking for              GDGraph (any)      ok: found v1.48
Checking for          MIME-tools (v5.406)    ok: found v5.504
Checking for          libwww-perl (any)      ok: found v6.05
Checking for            XML-Twig (any)      ok: found v3.34
Checking for          PatchReader (v0.9.6)    ok: found v0.9.6
Checking for            perl-ldap (any)      ok: found v0.40
Checking for          Authen-SASL (any)      ok: found v2.13
Checking for        Net-SMTP-SSL (v1.01)    ok: found v1.01
Checking for          RadiusPerl (any)      ok: found v0.23
Checking for            SOAP-Lite (v0.712)    ok: found v1.06
Checking for            JSON-RPC (any)      ok: found v1.03
Checking for              JSON-XS (v2.0)      ok: found v2.34
Checking for          Test-Taint (any)      ok: found v1.06
Checking for          HTML-Parser (v3.40)    ok: found v3.64
Checking for        HTML-Scrubber (any)      ok: found v0.09
Checking for              Encode (v2.21)    ok: found v2.35
Checking for        Encode-Detect (any)      ok: found v1.01
Checking for          Email-Reply (any)      ok: found v1.203
Checking for HTML-FormatText-WithLinks (v0.13)    ok: found v0.14
Checking for          TheSchwartz (any)      ok: found v1.10
Use of uninitialized value $ENV{"FLOCK_FORKING_USE"} in string eq at /usr/local/share/perl5/File/Flock/Forking.pm line 13, <DATA> line 522.
Checking for      Daemon-Generic (any)      ok: found v0.83
Checking for            mod_perl (v1.999022) ok: found v2.000004
Checking for    Apache-SizeLimit (v0.96)    ok: found v0.96
Checking for        File-MimeInfo (any)      ok: found v0.18
Checking for          IO-stringy (any)      ok: found v2.110
Checking for          mod_headers (any)      ok
Checking for          mod_expires (any)      ok
Checking for              mod_env (any)      ok
Reading ./localconfig...
Checking for              DBD-Pg (v2.7.0)    ok: found v2.15.1
Checking for          PostgreSQL (v8.03.0000) ok: found v08.04.1300
 
Removing existing compiled templates...
Precompiling templates...done.
Fixing file permissions...
 
Now that you have installed Bugzilla, you should visit the 'Parameters'
page (linked in the footer of the Administrator account) to ensure it
is set up as you wish - this includes setting the 'urlbase' option to
the correct URL.
checksetup.pl complete.
</syntaxhighlight>
 
Start up the server!
 
<syntaxhighlight lang="bash">
/etc/init.d/httpd start
</syntaxhighlight>
<syntaxhighlight lang="text">
Starting httpd: Apache/2.2.15 mod_ssl/2.2.15 (Pass Phrase Dialog)
Some of your private key files are encrypted for security reasons.
In order to read them you have to provide the pass phrases.
 
Server bugs.alteeve.ca:443 (RSA)
Enter pass phrase:
 
OK: Pass Phrase Dialog successful.
                                                          [  OK  ]
</syntaxhighlight>
 
If everything is working, you should be able to browse to your bugzilla install!
 
== Configure Bugzilla Itself ==
 
Log in as the adminitrator (user name is the email address you entered earlier with <span class="code">./checksetup.pl</span>) and go to <span class="code">https://<domain>/editparams.cgi</span>.
 
* General
 
{|class="wikitable"
!Variab!!Value
|-
|<span class="code">urlbase</span>||<span class="code">https://bugs.alteeve.ca</span>
|-
|<span class="code">ssl_redirect</span>||Click to check <span class="code">On</span>
|-
|<span class="code">sslbase</span>||<span class="code">https://bugs.alteeve.ca</span>
|}
 
* Email
 
{|class="wikitable"
!Variab!!Value
|-
|<span class="code">mail_delivery_method</span>||<span class="code">SMTP</span>
|-
|<span class="code">mailfrom</span>||<span class="code">bugs@alteeve.ca</span>
|-
|<span class="code">use_mailer_queue</span>||Click to check <span class="code">On</span>
|-
|<span class="code">smtpserver</span>||<span class="code">mail.alteeve.ca</span>
|-
|<span class="code">smtp_username</span>||<span class="code">bugs@alteeve.ca</span>
|-
|<span class="code">smtp_password</span>||<span class="code">secret</span>
|-
|<span class="code">smtp_ssl</span>||Click to check <span class="code">On</span>
|-
|<span class="code">globalwatchers</span>||<span class="code">admin@alteeve.ca</span>
|}
 
= Mailman =
 
Mailing list software!
 
== Install Mailman ==
 
We need mailman 3 in order to get encrypted passwords. So we'll not be using <span class="code">mailman</span> as shipped with [[RHEL6]].
 
=== Install Prerequisite RPMs ===
 
<syntaxhighlight lang="bash">
yum -y install postfix mailx httpd gcc mod_ssl
chkconfig postfix on
chkconfig httpd on
</syntaxhighlight>
 
=== Install Python 2.7 ===
 
From [https://www.digitalocean.com/community/articles/how-to-set-up-python-2-7-6-and-3-3-3-on-centos-6-4 here].
 
<syntaxhighlight lang="bash">
wget -qO- http://people.redhat.com/bkabrda/scl_python27.repo >> /etc/yum.repos.d/scl.repo
yum update
yum -y install python27
scl enable python27 bash
python -V
</syntaxhighlight>
 
You should get:
 
<syntaxhighlight lang="text">
Python 2.7.5
</syntaxhighlight>
 
=== Configure Local Postfix ===
 
<syntaxhighlight lang="bash">
vim /etc/postfix/main.cf
</syntaxhighlight>
 
Add:
 
<syntaxhighlight lang="text">
queue_directory = /var/spool/postfix
command_directory = /usr/sbin
daemon_directory = /usr/libexec/postfix
data_directory = /var/lib/postfix
mail_owner = postfix
mydomain = lists.alteeve.ca
inet_interfaces = all
inet_protocols = all
mydestination = lists.alteeve.ca
unknown_local_recipient_reject_code = 550
mynetworks_style = subnet
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
debug_peer_level = 2
debugger_command =
PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
ddd $daemon_directory/$process_name $process_id & sleep 5
sendmail_path = /usr/sbin/sendmail.postfix
newaliases_path = /usr/bin/newaliases.postfix
mailq_path = /usr/bin/mailq.postfix
setgid_group = postdrop
html_directory = no
manpage_directory = /usr/share/man
sample_directory = /usr/share/doc/postfix-2.6.6/samples
readme_directory = /usr/share/doc/postfix-2.6.6/README_FILES
</syntaxhighlight>
 
(Re)start postfix:
 
<syntaxhighlight lang="bash">
/etc/init.d/postfix restart
</syntaxhighlight>
 
Test local mail delivery:
 
<syntaxhighlight lang="bash">
echo hi | mailx -s test admin@alteeve.ca
</syntaxhighlight>
 
If you got an email, local mail delivery is working.
 
=== Configure Apache for Mailman ===
 
Follow the [[#Apache|Apache]] install above. Come back here
 
We will configure <span class="code"><nowiki>http://lists.alteeve.ca</nowiki></span> to redirect all calls to <span class="code"><nowiki>https://lists.alteeve.ca</nowiki></span>.
 
Specific configs:
 
Base apache:
 
<syntaxhighlight lang="bash">
diff -U0 /etc/httpd/conf/httpd.conf.orig /etc/httpd/conf/httpd.conf
</syntaxhighlight>
<syntaxhighlight lang="diff">
--- /etc/httpd/conf/httpd.conf.orig 2013-02-25 18:26:51.000000000 -0500
+++ /etc/httpd/conf/httpd.conf 2014-04-03 21:00:51.952003006 -0400
@@ -103,6 +103,6 @@
-StartServers      8
-MinSpareServers    5
-MaxSpareServers  20
-ServerLimit      256
-MaxClients      256
-MaxRequestsPerChild  4000
+StartServers      16
+MinSpareServers  10
+MaxSpareServers  40
+ServerLimit      512
+MaxClients      512
+MaxRequestsPerChild  8000
@@ -119,5 +119,5 @@
-StartServers        4
-MaxClients        300
-MinSpareThreads    25
-MaxSpareThreads    75
-ThreadsPerChild    25
+StartServers        8
+MaxClients        600
+MinSpareThreads    50
+MaxSpareThreads    150
+ThreadsPerChild    50
@@ -262 +262 @@
-ServerAdmin root@localhost
+ServerAdmin admin@alteeve.ca
@@ -276 +276 @@
-#ServerName www.example.com:80
+ServerName lists.alteeve.ca:80
@@ -292 +292 @@
-DocumentRoot "/var/www/html"
+DocumentRoot "/var/www/default/html"
@@ -317 +317 @@
-<Directory "/var/www/html">
+<Directory "/var/www/default/html">
@@ -551 +551 @@
-Alias /icons/ "/var/www/icons/"
+Alias /icons/ "/var/www/default/icons/"
@@ -553 +553 @@
-<Directory "/var/www/icons">
+<Directory "/var/www/default/icons">
@@ -576 +576 @@
-ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
+ScriptAlias /cgi-bin/ "/var/www/default/cgi-bin/"
@@ -579 +579 @@
-# "/var/www/cgi-bin" should be changed to whatever your ScriptAliased
+# "/var/www/default/cgi-bin" should be changed to whatever your ScriptAliased
@@ -582 +582 @@
-<Directory "/var/www/cgi-bin">
+<Directory "/var/www/default/cgi-bin">
@@ -851 +851 @@
-# /var/www/error/include/ files and
+# /var/www/default/error/include/ files and
@@ -855 +855 @@
-Alias /error/ "/var/www/error/"
+Alias /error/ "/var/www/default/error/"
@@ -859 +859 @@
-    <Directory "/var/www/error">
+    <Directory "/var/www/default/error">
@@ -990 +990 @@
-#NameVirtualHost *:80
+NameVirtualHost *:80
</syntaxhighlight>
 
SSL setup:
 
<syntaxhighlight lang="bash">
diff -U0 /etc/httpd/conf.d/ssl.conf.orig /etc/httpd/conf.d/ssl.conf
</syntaxhighlight>
<syntaxhighlight lang="diff">
--- /etc/httpd/conf.d/ssl.conf.orig 2014-04-03 21:37:26.431005814 -0400
+++ /etc/httpd/conf.d/ssl.conf 2014-04-03 21:10:16.558004490 -0400
@@ -74 +74 @@
-<VirtualHost _default_:443>
+<VirtualHost _default_:80>
</syntaxhighlight>
 
Configure the http redirect to https:
 
<syntaxhighlight lang="bash">
vim /etc/httpd/conf.d/lists.alteeve.ca.conf
</syntaxhighlight>
<syntaxhighlight lang="apache">
<VirtualHost *:80>
ServerAdmin admin@alteeve.ca
 
ServerName lists.alteeve.ca
 
RedirectMatch permanent (.*) https://lists.alteeve.ca$1
 
ErrorLog /var/www/lists.alteeve.ca/logs/error.log
LogLevel debug
 
CustomLog /var/www/lists.alteeve.ca/logs/access.log combined
ServerSignature On
</VirtualHost>
</syntaxhighlight>
 
Setup the main https page:
 
<syntaxhighlight lang="bash">
vim /etc/httpd/conf.d/ssl_lists.alteeve.ca.conf
</syntaxhighlight>
<syntaxhighlight lang="apache">
<VirtualHost *:443>
        ServerAdmin admin@alteeve.ca
        ServerName lists.alteeve.ca
        DirectoryIndex index.php index.html
        # We can haz security?
        SSLEngine on
        SSLProtocol all
        SSLCACertificateFile /etc/pki/CA/RapidSSL_CA_bundle.pem
        SSLCertificateFile /etc/pki/CA/wildcard_ssl_alteeve.ca.crt
        SSLCertificateKeyFile /etc/pki/CA/private/wildcard_alteeve.ca.key
        DocumentRoot /var/www/ssl_lists.alteeve.ca/html/
        Alias /w /var/www/ssl_lists.alteeve.ca/html/index.php
        <Directory /var/www/ssl_lists.alteeve.ca/html>
                Options +Includes Indexes FollowSymLinks MultiViews
                AllowOverride All
                Order allow,deny
                allow from all
        </Directory>
        ScriptAlias /cgi-bin/ /var/www/ssl_lists.alteeve.ca/cgi-bin/
        <Directory "/var/www/ssl_lists.alteeve.ca/cgi-bin">
                AllowOverride None
                Options ExecCGI -MultiViews +SymLinksIfOwnerMatch
                Order allow,deny
                Allow from all
        </Directory>
        ErrorLog /var/www/ssl_lists.alteeve.ca/logs/error.log
        TransferLog /var/www/ssl_lists.alteeve.ca/logs/transfer.log
        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel debug
        CustomLog /var/www/ssl_lists.alteeve.ca/logs/access.log combined
        ServerSignature On
</VirtualHost>
</syntaxhighlight>
 
[[#Copying_Wildcard_to_a_new_Server|Copy the wildcard]] SSL certs into place.
 
Create a redirect page:
 
<syntaxhighlight lang="bash">
mkdir -p /var/www/ssl_lists.alteeve.ca/{cgi-bin,html,logs}
touch /var/www/ssl_lists.alteeve.ca/html/index.html
chown -R apache:apache /var/www
vim /var/www/ssl_lists.alteeve.ca/html/index.html
</syntaxhighlight>
<syntaxhighlight lang="html4strict">
<head>
        <title>Alteeve's Niche! - Mailing Lists</title>
</head>
<body>
        <meta http-equiv="refresh" content="0; url=mailman/listinfo/" />
</body>
</syntaxhighlight>
 
Connect to [http://lists.alteeve.ca http://lists.alteeve.ca] and it should automatically redirect to: <span class="code">http://lists.alteeve.ca/mailman/listinfo/</span>.
 
=== Add an MX Record to Bind For lists.alteeve.ca ===
 
Add an entry in bind so that there is an MX record for <span class="code">lists.alteeve.ca</span>:
 
<syntaxhighlight lang="bash">
/etc/named/db.alteeve.ca
</syntaxhighlight>
 
Add:
 
<syntaxhighlight lang="text">
lists.alteeve.ca. MX 10 lists.alteeve.ca.
</syntaxhighlight>
 
Save and reload <span class="code">named</span>.
 
<syntaxhighlight lang="bash">
/etc/init.d/named reload
</syntaxhighlight>
 
=== Install Mailman v3 from Source ===
 
At this time, the only v3 install is beta.
 
<syntaxhighlight lang="bash">
mkdir ~/temp
cd ~/temp/
wget https://launchpad.net/mailman/3.0/3.0.0b3/+download/mailman-3.0.0b3.tar.gz
tar -xvzf mailman-3.0.0b3.tar.gz
cd mailman-3.0.0b3
python setup.py build
python setup.py install
</syntaxhighlight>
 
And here, the best laid plans fell to pieces... Back to mailman 2.
 
<span class="code"></span>
<syntaxhighlight lang="bash">
</syntaxhighlight>
<syntaxhighlight lang="text">
</syntaxhighlight>
 
== Configure Mailmain ==
 
Create the initial <span class="code">mailman</span> list.
 
<syntaxhighlight lang="bash">
/usr/lib/mailman/bin/newlist anvil-users
</syntaxhighlight>
<syntaxhighlight lang="text">
Enter the email of the person running the list: admin@alteeve.ca
Initial anvil-users password:
</syntaxhighlight>
<syntaxhighlight lang="text">
To finish creating your mailing list, you must edit your /etc/aliases (or
equivalent) file by adding the following lines, and possibly running the
`newaliases' program:
 
## anvil-users mailing list
anvil-users:              "|/usr/lib/mailman/mail/mailman post anvil-users"
anvil-users-admin:        "|/usr/lib/mailman/mail/mailman admin anvil-users"
anvil-users-bounces:      "|/usr/lib/mailman/mail/mailman bounces anvil-users"
anvil-users-confirm:      "|/usr/lib/mailman/mail/mailman confirm anvil-users"
anvil-users-join:        "|/usr/lib/mailman/mail/mailman join anvil-users"
anvil-users-leave:        "|/usr/lib/mailman/mail/mailman leave anvil-users"
anvil-users-owner:        "|/usr/lib/mailman/mail/mailman owner anvil-users"
anvil-users-request:      "|/usr/lib/mailman/mail/mailman request anvil-users"
anvil-users-subscribe:    "|/usr/lib/mailman/mail/mailman subscribe anvil-users"
anvil-users-unsubscribe:  "|/usr/lib/mailman/mail/mailman unsubscribe anvil-users"
 
Hit enter to notify anvil-users owner...
</syntaxhighlight>
 
Edit the alias file:
 
<syntaxhighlight lang="bash">
vim /etc/aliases
</syntaxhighlight>
 
Append:
 
<syntaxhighlight lang="text">
## anvil-users mailing list
anvil-users:              "|/usr/lib/mailman/mail/mailman post anvil-users"
anvil-users-admin:        "|/usr/lib/mailman/mail/mailman admin anvil-users"
anvil-users-bounces:      "|/usr/lib/mailman/mail/mailman bounces anvil-users"
anvil-users-confirm:      "|/usr/lib/mailman/mail/mailman confirm anvil-users"
anvil-users-join:        "|/usr/lib/mailman/mail/mailman join anvil-users"
anvil-users-leave:        "|/usr/lib/mailman/mail/mailman leave anvil-users"
anvil-users-owner:        "|/usr/lib/mailman/mail/mailman owner anvil-users"
anvil-users-request:      "|/usr/lib/mailman/mail/mailman request anvil-users"
anvil-users-subscribe:    "|/usr/lib/mailman/mail/mailman subscribe anvil-users"
anvil-users-unsubscribe:  "|/usr/lib/mailman/mail/mailman unsubscribe anvil-users"
</syntaxhighlight>
 
And load:
 
<syntaxhighlight lang="bash">
newaliases
</syntaxhighlight>
 
=== WebUI Config ===
 
# https://lists.alteeve.ca/mailman/admin/anvil-users/general
## Hide the sender of a message, replacing it with the list address (Removes From, Sender and Reply-To fields) -> Yes.
 
<span class="code"></span>
<syntaxhighlight lang="bash">
</syntaxhighlight>
<syntaxhighlight lang="text">
</syntaxhighlight>


<source lang="text">
== Deleting Mail from the Archive ==
password_query = SELECT email, password FROM email_password WHERE email='%u'
</source>


The last thing to setup is the user query. The query needs to return the [[UID]] and [[GID]] of the <span class="code">vmail</span> user we setup earlier. To get it, you can use the <span class="code">id</span> command.
Go to the list directory:


<source lang="bash">
<syntaxhighlight lang="bash">
id vmail
cd /var/lib/mailman/archives/private
</source>
</syntaxhighlight>
<source lang="text">
uid=503(vmail) gid=503(vmail) groups=503(vmail)
</source>
 
The numbers we want are <span class="code">503</span> and <span class="code">503</span> for the UID and GID, respectively. Knowing this, we can set the userdb SQL string.
 
<source lang="text">
user_query = SELECT '/email/'||file AS email_dir, '503' AS uid, '503' AS gid FROM email_file WHERE email='%u'
</source>


Disable [[PAM]] lookup.
Edit the <span class="code">.mbox</span> file for the list.


<source lang="bash">
<syntaxhighlight lang="bash">
cp /etc/dovecot/conf.d/auth-system.conf.ext /etc/dovecot/conf.d/auth-system.conf.ext.orig
vim anvil-users.mbox/anvil-users.mbox
vim /etc/dovecot/conf.d/auth-system.conf.ext
</syntaxhighlight>
</source>


Comment-out <span class="code">driver = pam</span>.
Find the message you want to delete and then delete everything from <span class="code">From <sender email>  <date> <time> <year></span> until the same line from the next message (or end of the file if it's the last message in the list).  


<source lang="text">
Example:
passdb {
  #driver = pam
  # [session=yes] [setcred=yes] [failure_show_msg=yes] [max_requests=<n>]
  # [cache_key=<key>] [<service name>]
  #args = dovecot
}
</source>


<syntaxhighlight lang="email">
From lists@alteeve.ca  Thu Apr  3 23:35:27 2014
Return-Path: <lists@alteeve.ca>
X-Original-To: anvil-users@lists.alteeve.ca
Delivered-To: anvil-users@lists.alteeve.ca
Received: from vm08-mail01.alteeve.ca (unknown [65.39.153.71])
        by vm17-lists.alteeve.ca (Postfix) with ESMTP id DD83313FB13
        for <anvil-users@lists.alteeve.ca>;
        Thu,  3 Apr 2014 23:35:27 -0400 (EDT)
Received: from lemass.alteeve.ca (dhcp-108-168-20-202.cable.user.start.ca
        [108.168.20.202])
        by vm08-mail01.alteeve.ca (Postfix) with ESMTPSA id 80EC720171
        for <anvil-users@lists.alteeve.ca>;
        Thu,  3 Apr 2014 23:00:07 -0400 (EDT)
Message-ID: <533E2037.1020302@alteeve.ca>
Date: Thu, 03 Apr 2014 23:00:07 -0400
From: Digimer <lists@alteeve.ca>
User-Agent: Mozilla/5.0 (X11; Linux x86_64;
        rv:24.0) Gecko/20100101 Thunderbird/24.4.0
MIME-Version: 1.0
To: anvil-users@lists.alteeve.ca
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Subject: [Anvil-users] Test
X-BeenThere: anvil-users@lists.alteeve.ca
X-Mailman-Version: 2.1.12
Precedence: list
List-Id: <anvil-users.lists.alteeve.ca>
List-Unsubscribe: <https://lists.alteeve.ca/mailman/options/anvil-users>,
        <mailto:anvil-users-request@lists.alteeve.ca?subject=unsubscribe>
List-Archive: <http://lists.alteeve.ca/pipermail/anvil-users/>
List-Post: <mailto:anvil-users@lists.alteeve.ca>
List-Help: <mailto:anvil-users-request@lists.alteeve.ca?subject=help>
List-Subscribe: <https://lists.alteeve.ca/mailman/listinfo/anvil-users>,
        <mailto:anvil-users-request@lists.alteeve.ca?subject=subscribe>
X-List-Received-Date: Fri, 04 Apr 2014 03:35:27 -0000


Now (re)start the <span class="code">dovecot</span> daemon.
Please ignore.


<source lang="bash">
--
</source>
Digimer
<source lang="text">
Papers and Projects: https://alteeve.ca/w/
</source>
What if the cure for cancer is trapped in the mind of a person without
access to education?
</syntaxhighlight>


Once deleted, move the list directory out of the way and then regenerate the list archives.


<span class="code"></span>
<syntaxhighlight lang="bash">
<source lang="bash">
mv /var/lib/mailman/archives/private/anvil-users /var/lib/mailman/archives/private/anvil-users.1
</source>
/usr/lib/mailman/bin/arch anvil-users
<source lang="text">
</syntaxhighlight>
</source>
<syntaxhighlight lang="text">
#00000 <CA+scbRK1dZAY6Jv5UqBM7-cG_L385QCtFY5UFx3RWRABN7sG1g@mail.gmail.com>
figuring article archives
2014-April
#00001 <CA+scbRJ96jXnx=0iFk220FsoEFghNoR2gwLg-DmTQ3rL2qDw+w@mail.gmail.com>
figuring article archives
2014-April
#00002 <533E2CF6.7080909@alteeve.ca>
figuring article archives
2014-April
Updating index files for archive [2014-April]
  Date
  Subject
  Author
  Thread
Computing threaded index
Updating HTML for article 0
Updating HTML for article 1
Updating HTML for article 2
Pickling archive state into /var/lib/mailman/archives/private/anvil-users/pipermail.pck
</syntaxhighlight>


== Ooooold Notes ==
Reload the archive page and verify that the email is gone.


When prompted;
If so, delete the backup directory.
For 'Create directories for web-based administration ?' Choose 'Yes'.
For 'General type of configuration?', choose 'Local Only'.
For 'Mail Name', enter 'alteeve.com'.
For 'SSL certificate required', hit 'Ok'.
Create the database that we will use:
# su alteeve
$ createdb an_console
$ psql an_console
Now that we are in the new database we will need to load the AN!Console schema file.
# su postgres -c psql an_console -f /var/www/ssl_alteeve.com/cgi-bin/t/anc.pgsql.schema
On the Master node, we will create the directory where email will be stored.
# mkdir /ha/email
On the both nodes, we will create a link to the '/ha/email' directory off of root.
# ln -s /ha/email /email
Under this directory create another directory that is the domain name for the domains we will host mail for. Ie (no longer needed to be done manually, AN!Console will create directories for email as needed):
# mkdir /email/45years.ca
# mkdir /email/alteeve.com
And so on.
Go to the '/etc/postfix' directory and create these four files:
# vim /etc/postfix/psql-virtual_domains.cf
In it enter the lines:
user = alteeve
password = secret
dbname = an_console
table = domains
select_field = 'virtual'
where_field = dom_name
hosts = 127.0.0.1
# vim /etc/postfix/psql-virtual_forwardings.cf
In it enter the lines:
user = alteeve
password = secret
dbname = an_console
table = forwards
select_field = fwd_destination
where_field = fwd_source
hosts = 127.0.0.1
# vim /etc/postfix/psql-virtual_mailboxes.cf
In it enter the lines:
user = alteeve
password = secret
dbname = an_console
table = email_file
select_field = file
where_field = email
hosts = 127.0.0.1
Note: The table 'email_file' is actually a view that takes the email passed by postfix and splits it to generate a joined SELECT.
# vim /etc/postfix/psql-virtual_email2email.cf
In it enter the lines:
user = alteeve
password = secret
dbname = an_console
table = email_email
select_field = email
where_field = email
hosts = 127.0.0.1
Note: The table 'email_email' is actually a view that takes the email passed by postfix and returns the same email based on the DB entry. This is needed as a work-around for Postfix's habit of matching global forwards like '@domain -> user@domain' for all email to that domain, even what a given email address matches a user.
Now change the owner and permissions of those four files to NOT allow global reading as they contain our password.
# chown root:postfix /etc/postfix/psql-virtual_*
# chmod 640 /etc/postfix/psql-virtual_*
Now we will create a user account that will, in turn, own all the mail on the system. This user will not have shell access.
# adduser vmail
Enter a password, preferably one treated with the same care as the root password. You can leave all other options blank.
Now change the ownership of the mail store.
# chown -R vmail:vmail /email
# chmod -R 775 /email
Now we edit the main '/etc/postfix/main.cf' configuration file.
Make a backup of the original file “just in case”.
# cp /etc/postfix/main.cf /etc/postfix/main.cf.original
Now edit it:
# vim /etc/postfix/main.cf
There are several options to edit:
Please see 'Step 6' at: http://workaround.org/articles/ispmail-sarge/index.shtml.en for details on the options to set.
For 'inet_interface' enter 'all'.
For 'myhostname' use the cluster FQDN. Ie;
myhostname = nikko.alteeve.com
For 'mydestination' use only local names, NOT real domains we will host email for. Any mail sent to the domains specified here will go to local (shell) users.
mydestination = nikko.alteeve.com, localhost.alteeve.com, localhost
For 'mynetworks' set all the IP subnets we trust. Ie;
mynetworks = 192.139.81.0/24 192.168.1.0/24 192.168.2.0/24 10.0.0.0/24 127.0.0.0/8
We can ignore 'virtual_alias_domains' if it exists.
For 'virtual_alias_maps' we will set:
virtual_alias_maps = pgsql:/etc/postfix/psql-virtual_forwardings.cf pgsql:/etc/postfix/psql-virtual_email2email.cf
For 'virtual_mailbox_domains' we will set:
virtual_mailbox_domains = pgsql:/etc/postfix/psql-virtual_domains.cf
For 'virtual_mailbox_maps' we will set:
virtual_mailbox_maps = pgsql:/etc/postfix/psql-virtual_mailboxes.cf
For 'virtual_mailbox_base' (where the email will be stored on disk) we will set:
virtual_mailbox_base = /ha/email
For 'virtual_uid_maps' and 'virtual_gid_maps' we will enter the numerical UID and GID for the 'vmail' shell user we created earlier. To find what it's UID and GID is run:
# cat /etc/passwd | grep vmail
vmail:x:1001:1001:,,,:/home/vmail:/bin/bash
The first number is the UID, the second is the GID;
virtual_uid_maps = static:1001
virtual_gid_maps = static:1001
Set 'smtpd_sasl_auth_enable' to 'yes'.
Set 'broken_sasl_auth_clients' to 'yes'.
To enable relaying of local mail, trusted domains and SASL authenticated users and reject the rest set;
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
For 'smtpd_use_tls' the value should already be 'yes', but set it to such if not.
Lastly we'll set our certificate paths;
smtpd_tls_cert_file = /etc/postfix/smtpd.cert
smtpd_tls_key_file = /etc/postfix/smtpd.key
At this point we should be good to go. Restart postfix;
# /etc/init.d/postfix restart
If there were no errors in the restart, test the config by running;
# postfix check
If you get errors, fix 'em. Otherwise, so far so good!
Now to setup postfix to allow authentication of SMTP connections to allow relaying of messages from people (we trust) outside on the 'mynetworks' scope.
Create or edit the file '/etc/postfix/sasl/smtpd.conf'
# vim /etc/postfix/sasl/smtpd.conf
In it enter the lines:
pwcheck_method: auxprop
auxprop_plugin: sql
mech_list: plain login cram-md5 digest-md5
sql_engine: pgsql
sql_hostnames: 127.0.0.1
sql_user: alteeve
sql_passwd: secret
sql_database: an_console
sql_select: SELECT passwd FROM email_passwd WHERE email='%u@%r'
log_level: 7
Now secure the file (it's got our DB password)
# chown root:postfix /etc/postfix/sasl/smtpd.conf
# chmod 640 /etc/postfix/sasl/smtpd.conf
Now we want to setup TLS to encrypt SMTP traffic. Be sure you are still in '/etc/postfix' as this is where you want the certificate files.
To create a 10-year certificate for our SMTP domain 'smtp.alteeve.com':
# openssl req -new -outform PEM -out /etc/postfix/smtpd.cert -newkey rsa:2048 -nodes -keyout /etc/postfix/smtpd.key -keyform PEM -days 3650 -x509
This will bring up a bunch of questions:
Country Name (2 letter code) [AU]: CA
State or Province Name (full name) [Some-State]:Ontario
Locality Name (eg, city) []:Toronto
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Alteeve's Niche!
Organizational Unit Name (eg, section) []:Hosting
Common Name (eg, YOUR name) []:smtp.alteeve.com
Email Address []:admin@alteeve.com
This will create two files in your current directory; 'smtpd.key' and 'smtpd.cert'. You'll want to protect them.
# chown root:postfix smtpd.*
# chmod 640 smtpd.*
Now we need to setup POP3 and IMAP access so users can actually check their email.
Backup then edit '/etc/dovecot/dovecot.conf' to have:
protocols = pop3 imap
mail_location = mbox:/email/%d/%n
#  passdb pam {
#  }
passdb sql {
args = /etc/dovecot/dovecot-sql.conf
}
#  userdb passwd {
#  }
userdb sql {
args = /etc/dovecot/dovecot-sql.conf
}


# The default location for 'dovecot-sql.conf' is under '/usr/local/etc', be sure to
<syntaxhighlight lang="bash">
# change it!
rm -rf /var/lib/mailman/archives/private/anvil-users.1
auth default {
</syntaxhighlight>
mechanisms = plain
passdb sql {
args = /etc/dovecot/dovecot-sql.conf
}
userdb sql {
args = /etc/dovecot/dovecot-sql.conf
}
user = root
}
Then create/edit '/etc/dovecot/dovecot-sql.conf':
driver = pgsql
connect = host=localhost dbname=an_console user=alteeve password=secret
default_pass_scheme = PLAIN
password_query = SELECT email, password FROM email_password WHERE email='%u'
user_query = SELECT '/email/'||file AS email_dir, '1001' AS uid, '1001' AS gid FROM email_file WHERE email='%u'
Now restart Dovecot:
# /etc/init.d/dovecot restart


= Thanks =
= Thanks =


* To [http://planet-geek.com Dave Shevett] (aka: eidolon) and [http://codex.grimoire.ca/ Owen Jacobson] for answering my n00b SSL questions.
* To [http://planet-geek.com Dave Shevett] (aka: eidolon) and [http://codex.grimoire.ca/ Owen Jacobson] for answering my n00b SSL questions.
<span class="code"></span>
<source lang="bash">
</source>
<source lang="text">
</source>


{{footer}}
{{footer}}

Latest revision as of 22:51, 23 July 2015

 AN!Wiki :: How To :: PPPower Server

With tongue firmly in cheek, this is a tutorial on building an EL6 server for hosting website and email using PostgreSQL, Postfix and Postgrey for mail and Apache for web. There are many canned and arguably superior was of accomplishing the same, but this is what I user for this server.

Post OS Install

First, some post-install preparation. We'll need to set up some basic security, a program to report server statistics, and some 3rd-party yum repositories for additional software.

Yum repo install.

yum -y install yum-protectbase
rpm -Uvh https://alteeve.ca/an-repo/el6/RPMS/noarch/alteeve-repo-0.1-3.noarch.rpm
yum clean expire-cache
yum -y update

The yum-protectbase plugin will ensure that the 3rd-party repos play nicely and never overwrite the Base repos. To use this plugin with a specific repo, add protect=0 or protect=1 to the repo's config file.

cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.orig
vim /etc/yum.repos.d/CentOS-Base.repo
# add protect=1 to each paragraph
diff -U 0 /etc/yum.repos.d/CentOS-Base.repo.orig /etc/yum.repos.d/CentOS-Base.repo
--- /etc/yum.repos.d/CentOS-Base.repo.orig	2012-05-07 01:07:47.688145406 -0400
+++ /etc/yum.repos.d/CentOS-Base.repo	2012-05-07 01:08:15.915322496 -0400
@@ -18,0 +19 @@
+protect=1
@@ -26,0 +28 @@
+protect=1
@@ -34,0 +37 @@
+protect=1
@@ -43,0 +47 @@
+protect=1
@@ -52,0 +57 @@
+protect=1

Protecting against malicious users with Denyhosts.

Denyhosts is a daemon that watches for too many failed logins via ssh. It uses TCP-wrappers to deny the user access to ssh (or any service) on the server after X failed logins. It has the option to download a list of known malicious IPs and add them to /hosts.deny, making possible to block attackers before they attack the server.

Install denyhosts

yum -y install denyhosts

Edit the config to your preferences.

cp /etc/denyhosts.conf /etc/denyhosts.conf.orig
vim /etc/denyhosts.conf
BLOCK_SERVICE = ALL
SYNC_SERVER = http://xmlrpc.denyhosts.net:9911
SYNC_DOWNLOAD = yes
diff -U 0 /etc/denyhosts.conf.orig /etc/denyhosts.conf
--- /etc/denyhosts.conf.orig	2012-05-13 02:33:05.584566483 -0400
+++ /etc/denyhosts.conf	2012-05-13 02:34:19.386558503 -0400
@@ -96 +96 @@
-#BLOCK_SERVICE = ALL
+BLOCK_SERVICE = ALL
@@ -98 +98 @@
-BLOCK_SERVICE  = sshd
+#BLOCK_SERVICE  = sshd
@@ -547 +547 @@
-#SYNC_SERVER = http://xmlrpc.denyhosts.net:9911
+SYNC_SERVER = http://xmlrpc.denyhosts.net:9911
@@ -582 +582 @@
-#SYNC_DOWNLOAD = yes
+SYNC_DOWNLOAD = yes

White-list any trusted machines, including localhost.

cp /etc/hosts.allow /etc/hosts.allow.orig
vim /etc/hosts.allow
127.0.0.1
206.108.5.162
diff -U 0 /etc/hosts.allow.orig /etc/hosts.allow
--- /etc/hosts.allow.orig	2012-05-13 02:36:02.613767847 -0400
+++ /etc/hosts.allow	2012-05-13 02:40:37.473523845 -0400
@@ -10,0 +11,2 @@
+127.0.0.1
+206.108.5.162

Start the service.

chkconfig denyhosts on
/etc/init.d/denyhosts start
Starting denyhosts:                                        [  OK  ]

Additional software to install

To view neatly-summarized daily logs, and system resource usage.

yum -y install logwatch htop

Packages for web server and wiki install.

yum install httpd httpd-tools postgresql94-server postgresql94-plperl postgresql94-contrib postgresql94 mysql-server telnet mod_ssl mysql-server php-mysql gcc jwhois bind \
            acpid bind-utils syslinux screen man bzip2 zip unzip php-pgsql php yum-utils policycoreutils-python rsync
chkconfig acpid on

Packages that are currently needed for personal stuff.

yum install perl-XML-Simple perl-MIME-Lite perl-DBD-MySQL perl-DBD-Pg perl-Digest-Perl-MD5 mod_auth_pgsql perl-Digest-SHA perl-CGI perl-Time-HiRes

Apache

Apache is configured first with a global configuration, which also defines the "default" website which is shown when the server is called by it's IP address (or by a domain that is not configured). Then with per-domain configurations known as "virtual host containers".

First, the global configuration and default domain. We will put our default website in /var/www/default/. So the first step is to create the needed directories.

mkdir -p /var/www/default/{html,cgi-bin,logs}
chown -R apache:apache /var/www

Now to edit the configuration file.

cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.orig
vim /etc/httpd/conf/httpd.conf
Note: This needs to be explained.

Make the following changes.

diff -U 0 /etc/httpd/conf/httpd.conf.orig /etc/httpd/conf/httpd.conf
--- /etc/httpd/conf/httpd.conf.orig	2012-05-13 19:32:07.718570148 -0400
+++ /etc/httpd/conf/httpd.conf	2012-05-13 21:48:18.439736244 -0400
@@ -103,6 +103,6 @@
-StartServers       8
-MinSpareServers    5
-MaxSpareServers   20
-ServerLimit      256
-MaxClients       256
-MaxRequestsPerChild  4000
+StartServers      16
+MinSpareServers   10
+MaxSpareServers   40
+ServerLimit      512
+MaxClients       512
+MaxRequestsPerChild  8000
@@ -119,5 +119,5 @@
-StartServers         4
-MaxClients         300
-MinSpareThreads     25
-MaxSpareThreads     75 
-ThreadsPerChild     25
+StartServers         8
+MaxClients         600
+MinSpareThreads     50
+MaxSpareThreads    150 
+ThreadsPerChild     50
@@ -262 +262 @@
-ServerAdmin root@localhost
+ServerAdmin admin@alteeve.ca
@@ -276,0 +277 @@
+ServerName omiya.alteeve.ca:80
@@ -292 +293 @@
-DocumentRoot "/var/www/html"
+DocumentRoot "/var/www/default/html"
@@ -317 +318 @@
-<Directory "/var/www/html">
+<Directory "/var/www/default/html">
@@ -551 +552 @@
-Alias /icons/ "/var/www/icons/"
+Alias /icons/ "/var/www/default/icons/"
@@ -553 +554 @@
-<Directory "/var/www/icons">
+<Directory "/var/www/default/icons">
@@ -576 +577 @@
-ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
+ScriptAlias /cgi-bin/ "/var/www/default/cgi-bin/"
@@ -582 +583 @@
-<Directory "/var/www/cgi-bin">
+<Directory "/var/www/default/cgi-bin">
@@ -855 +856 @@
-Alias /error/ "/var/www/error/"
+Alias /error/ "/var/www/default/error/"
@@ -859 +860 @@
-    <Directory "/var/www/error">
+    <Directory "/var/www/default/error">
@@ -990 +991 @@
-#NameVirtualHost *:80
+NameVirtualHost *:80
@@ -1004,5 +1005,5 @@
-#    ServerAdmin webmaster@dummy-host.example.com
-#    DocumentRoot /www/docs/dummy-host.example.com
-#    ServerName dummy-host.example.com
-#    ErrorLog logs/dummy-host.example.com-error_log
-#    CustomLog logs/dummy-host.example.com-access_log common
+#    ServerAdmin admin@alteeve.ca
+#    DocumentRoot /var/www/default/html
+#    ServerName unknown.alteeve.ca
+#    ErrorLog /var/www/default/logs/error.log
+#    CustomLog /var/www/default/logs/access.log common
@@ -1009,0 +1011 @@
+

After all changes, use this to make sure there are no syntax errors.

apachectl -t
[Sun May 13 21:48:11 2012] [warn] NameVirtualHost *:80 has no VirtualHosts
Syntax OK

Note that the [Sun May 13 21:48:11 2012] [warn] NameVirtualHost *:80 has no VirtualHosts is expected at this stage as we've not yet configured any virtual hosts.

All virtual host configuration files need to be created in the /etc/httpd/conf.d directory and the file must have the .conf suffix in order to be read by apache. These files will be read in order, so if you want to ensure that one file is read before another, as we will do shortly, you can prefix the configuration file with an integer to ensure read order.

I like to redirect all unknown server requests to http://unknown.alteeve.ca. For this, I will create an initial configuration file called 00_default.conf.

vim /etc/httpd/conf.d/00_default.conf
<VirtualHost *:80>
        ServerAdmin admin@alteeve.ca
        DocumentRoot /var/www/default/html
        ServerName unknown.alteeve.ca
        ErrorLog /var/www/default/logs/error.log
        CustomLog /var/www/default/logs/access.log common
</VirtualHost>

Now we will do two kinds of checks; One for syntax and one to check the configuration of virtual host containers.

apachectl -t
Syntax OK

We no longer see the warning from before as we now have our first virtual host configured.

apachectl -S
VirtualHost configuration:
wildcard NameVirtualHosts and _default_ servers:
_default_:443          omiya.alteeve.ca (/etc/httpd/conf.d/ssl.conf:74)
*:80                   is a NameVirtualHost
         default server unknown.alteeve.ca (/etc/httpd/conf.d/00_default.conf:1)
         port 80 namevhost unknown.alteeve.ca (/etc/httpd/conf.d/00_default.conf:1)
Syntax OK

We can now start the web server for the first time.

/etc/init.d/httpd start
Starting httpd:                                            [  OK  ]

Perfect! Time to configure some real domains.

Common Virtual Host Configurations

All domains on this server will be housed under either:

  • /var/www/domain.tld/{cgi-bin,html,logs,temp}

Or, for SSL encrypted domains;

  • /var/www/ssl_domain.tld/{cgi-bin,html,logs,temp}

The four directories found under the domain are used for hosting executable scripts (cgi-bin), standard HTML websites or websites with in-line code like PHP (html), log files (logs) and an optional temporary directory used for staging files (temp).

Standard Virtual Hosts

This section covers the configuration on standard virtual host containers (using TCP port 80).

In this example, we will setup the domain http://mizu-bu.org.

First, create the directories for the domain's files.

mkdir -p /var/www/mizu-bu.org/{cgi-bin,html,logs,temp}

Now create the virtual host container's configuration file. Note that in this example, it is a MediaWiki website, so we will tell apache to look for index.php files by default.

vim /etc/httpd/conf.d/mizu-bu.org.conf
<VirtualHost *:80>
	ServerAdmin digimer@alteeve.ca

	ServerName mizu-bu.org
        ServerAlias www.mizu-bu.org

	DirectoryIndex index.html
    	
	DocumentRoot /var/www/mizu-bu.org/html/
	<Directory /var/www/mizu-bu.org/html>
		Options +Includes Indexes FollowSymLinks MultiViews
		AllowOverride Options
		Order allow,deny
		allow from all
	</Directory>

	ScriptAlias /cgi-bin/ /var/www/mizu-bu.org/cgi-bin/
	<Directory "/var/www/mizu-bu.org/cgi-bin">
		AllowOverride None
		Options ExecCGI -MultiViews +SymLinksIfOwnerMatch
		Order allow,deny
		Allow from all
	</Directory>

	ErrorLog /var/www/mizu-bu.org/logs/error.log

	# Possible values include: debug, info, notice, warn, error, crit,
	# alert, emerg.
	LogLevel debug

	CustomLog /var/www/mizu-bu.org/logs/access.log combined
	ServerSignature On
</VirtualHost>

As before, test the syntax and virtual host configurations.

apachectl -S
VirtualHost configuration:
wildcard NameVirtualHosts and _default_ servers:
_default_:443          omiya.alteeve.ca (/etc/httpd/conf.d/ssl.conf:74)
*:80                   is a NameVirtualHost
         default server unknown.alteeve.ca (/etc/httpd/conf.d/00_default.conf:1)
         port 80 namevhost unknown.alteeve.ca (/etc/httpd/conf.d/00_default.conf:1)
         port 80 namevhost mizu-bu.org (/etc/httpd/conf.d/mizu-bu.org.conf:1)
Syntax OK


SSL Virtual Hosts

SSL provides for secure client to server communications.

Per-Domain SSL Cert

This covers setting up an SSL certificate for one domain only.

Per-Domain SS - Creating The Signed Certificate

This section assumes you are using a 3rd party signing authority. Specifically, I use http://www.trustico.ca/ (resellers of http://RapidSSL.com and others). This is also for a domain-specific certificate. Wildcard certificates will differ.

First, create 2048bit private key. Note that this will require a pass-phrase, which you will need to enter whenever the Apache daemon httpd daemon starts. If you do not want this, remove the -des3 switch.

cd /etc/pki/CA/private/
openssl genrsa -des3 -out /etc/pki/CA/private/alteeve.ca.key 2048
Generating RSA private key, 2048 bit long modulus
..................................+++
.............................................................+++
e is 65537 (0x10001)
Enter pass phrase for /etc/pki/CA/private/alteeve.ca.key:
Verifying - Enter pass phrase for /etc/pki/CA/private/alteeve.ca.key:

Now create a CSR (Certificate signing request) which we will send to the signing authority. Do not enter anything in the extra section below.

Note: The Common Name must be the fully qualified domain name. In this example, I want to create a certificate for the domain https://alteeve.ca, so I will enter alteeve.ca. If you prefer to use a www. prefix, include it. I will rewrite requests using the www. prefix to not use it.
openssl req -new -key /etc/pki/CA/private/alteeve.ca.key -out alteeve.ca.csr
Enter pass phrase for /etc/pki/CA/private/alteeve.ca.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CA
State or Province Name (full name) []:Ontario
Locality Name (eg, city) [Default City]:Oakville
Organization Name (eg, company) [Default Company Ltd]:Alteeve's Niche
Organizational Unit Name (eg, section) []:IT
Common Name (eg, your name or your server's hostname) []:alteeve.ca
Email Address []:admin@alteeve.ca     

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Test that the CSR file is ok.

openssl req -noout -text -in /etc/pki/CA/alteeve.ca.csr
Certificate Request:
    Data:
        Version: 0 (0x0)
        Subject: C=CA, ST=Ontario, L=Oakville, O=Alteeve's Niche, OU=IT, CN=alteeve.ca/emailAddress=admin@alteeve.ca
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    ...
                Exponent: 65537 (0x10001)
        Attributes:
            a0:00
    Signature Algorithm: sha1WithRSAEncryption
        ...

Copy the exact contents of the alteeve.ca.csr file and provide it to your signing authority as per their instructions. Once you complete their CSR form, they should email you a signed certificate and an intermediary certificate. At this point, the CSR file is no longer needed.

Save the signed certificate:

vim /etc/pki/CA/ssl_alteeve.ca.crt
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----

Save the intermediary certificate. Change the certificate name to that of your provider. If they provide you with this file, simply save it in the /etc/pki/CA/ directory.

vim /etc/pki/CA/RapidSSL_CA_bundle.pem
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----

Wildcard SSL Certificate

These certs work for any *.example.com domain.

Wildcard SSL - Creating The Signed Certificate

This section assumes you are using a 3rd party signing authority. Specifically, I use http://www.trustico.ca/ (resellers of http://RapidSSL.com and others). This is also for a domain-specific certificate. Wildcard certificates will differ.

Unlike the per-domain SSL certificate, this one will not require a pass-phrase to decrypt.

First, create 2048bit private key.

cd /etc/pki/CA/private/
openssl genrsa -out /etc/pki/CA/private/wildcard_alteeve.ca.key 2048
Generating RSA private key, 2048 bit long modulus
..<snip>..+++
..<snip>..+++
e is 65537 (0x10001)

Verify it was created:

ls -lah /etc/pki/CA/private/wildcard_alteeve.ca.key
-rw-r--r-- 1 root root 1.7K Feb 26 15:40 /etc/pki/CA/private/wildcard_alteeve.ca.key

Now create a CSR (Certificate signing request) which we will send to the signing authority. Do not enter anything in the extra section below.

Note: The Common Name must be the short, fully qualified domain name with a leading *. to make it a wildcard. In this example, I want to create a certificate domains under alteeve.ca, so I will enter *.alteeve.ca.
openssl req -new -key /etc/pki/CA/private/wildcard_alteeve.ca.key -out wildcard_alteeve.ca.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CA
State or Province Name (full name) []:Ontario
Locality Name (eg, city) [Default City]:Toronto
Organization Name (eg, company) [Default Company Ltd]:Alteeve's Niche! Inc.
Organizational Unit Name (eg, section) []:IT
Common Name (eg, your name or your server's hostname) []:*.alteeve.ca
Email Address []:admin@alteeve.ca

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Check that it was generated.

ls -lah /etc/pki/CA/private/wildcard_alteeve.ca.csr
-rw-r--r-- 1 root root 1.1K Feb 26 16:19 /etc/pki/CA/private/wildcard_alteeve.ca.csr

Test that the CSR file is ok.

openssl req -noout -text -in /etc/pki/CA/private/wildcard_alteeve.ca.csr
Certificate Request:
    Data:
        Version: 0 (0x0)
        Subject: C=CA, ST=Ontario, L=Toronto, O=Alteeve's Niche! Inc., OU=IT, CN=*.alteeve.ca/emailAddress=admin@alteeve.ca
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    ...
                Exponent: 65537 (0x10001)
        Attributes:
            a0:00
    Signature Algorithm: sha1WithRSAEncryption
         ...

Copy the exact contents of the wildcard_alteeve.ca.csr file and provide it to your signing authority as per their instructions. Once you complete their CSR form, they should email you a signed certificate and an intermediary certificate. At this point, the CSR file is no longer needed.

Save the signed certificate:

vim /etc/pki/CA/wildcard_ssl_alteeve.ca.crt
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----

Save the intermediary certificate. Change the certificate name to that of your provider. If they provide you with this file, simply save it in the /etc/pki/CA/ directory.

vim /etc/pki/CA/RapidSSL_CA_bundle.pem
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----

Copying Wildcard to a new Server

When you are setting up a new server to use an existing wildcard cert, you simply need to copy over four files:

rsync -av root@alteeve.ca:/etc/pki/CA/wildcard_ssl_alteeve.ca.crt /etc/pki/CA/
rsync -av root@alteeve.ca:/etc/pki/CA/private/wildcard_alteeve.ca* /etc/pki/CA/private/
rsync -av root@alteeve.ca:/etc/pki/CA/RapidSSL_CA_bundle.pem /etc/pki/CA/

Once copied, setup the SSL virtual host the same as always.

Change ssl.conf

If you forget to update /etc/httpd/conf.d/ssl.conf, you will get an error like this;

apachectl -t
[Mon Feb 25 19:50:32 2013] [warn] _default_ VirtualHost overlap on port 443, the first has precedence
Syntax OK

To avoid this, edit /etc/httpd/conf.d/ssl.conf and change <VirtualHost _default_:443> to <VirtualHost _default_:80>.

Creating An SSL Virtual Host

Create a new virtual host container for the new SSL protected virtual host. We will leave the normal unencrypted virtual-host alone for now. Once we're done, we'll use it to capture and redirect http:// requests to their https:// equivalents. I make my virtual host directories writeable by my normal user account. Feel free to adapt this to your preferences.

Setup the directories and then create a trivial index.html file.

mkdir ssl_alteeve.ca/{cgi-bin,html,logs,temp} -p
chown apache:digimer ssl_alteeve.ca -R
chmod g+w ssl_alteeve.ca -R
vim /var/www/ssl_alteeve.ca/html/index.html
<head>
        <title>AN!Wiki - SSL Test Server</title>
</head>
<body>
        <h1>SSL Test</h1>
</body>

Now setup the Apache2 config. I like to use the ssl_ prefix for encrypted domains.

Note: This example is for a MediaWiki virtual host with short URLs configured. You will want to adapt the values to suit your needs.
vim /etc/httpd/conf.d/ssl_alteeve.ca.conf
<VirtualHost *:443>
        ServerAdmin digimer@alteeve.ca

        ServerName alteeve.ca

        DirectoryIndex index.php index.html

        # We can haz security?
        SSLEngine on
        SSLProtocol all
        SSLCACertificateFile /etc/pki/CA/RapidSSL_CA_bundle.pem
        SSLCertificateFile /etc/pki/CA/wildcard_ssl_alteeve.ca.crt
        SSLCertificateKeyFile /etc/pki/CA/private/wildcard_alteeve.ca.key

        DocumentRoot /var/www/ssl_alteeve.ca/html/
        Alias /w /var/www/ssl_alteeve.ca/html/index.php
        <Directory /var/www/ssl_alteeve.ca/html>
                Options +Includes Indexes FollowSymLinks MultiViews
                AllowOverride All
                Order allow,deny
                allow from all
        </Directory>

        ScriptAlias /cgi-bin/ /var/www/ssl_alteeve.ca/cgi-bin/
        <Directory "/var/www/ssl_alteeve.ca/cgi-bin">
                AllowOverride None
                Options ExecCGI -MultiViews +SymLinksIfOwnerMatch
                Order allow,deny
                Allow from all
        </Directory>

        ErrorLog /var/www/ssl_alteeve.ca/logs/error.log
        TransferLog /var/www/ssl_alteeve.ca/logs/transfer.log

        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel debug

        CustomLog /var/www/ssl_alteeve.ca/logs/access.log combined
        ServerSignature On
</VirtualHost>

Bad Identity Error

If you get an error about the server not providing identity information, you may have be loading images, CSS, javascript or similar using a URL from a remote domain with no SSL or badly configured SSL.

For example, on Firefox 4, you may see:

This web site does not supply identity information.

Your connection to this site is only partially encrypted, and does not prevent eavesdropping.
                                                                        [ More Information ]

In my case, this turned out to be a problem where mediawiki was loading a Creative Commons logo from their server using http:// link to the icon. Once this was changed to https:// (in LocalSettings.php), the error went away.

Testing and Using the New Configuration

Test your new Apache configuration.

apachectl -t
Syntax OK

Now restart Apache. Note that you will be asked to enter the pass-phrase you used when you created your private key.

/etc/init.d/httpd restart
Stopping httpd:                                            [  OK  ]
Starting httpd: Apache/2.2.15 mod_ssl/2.2.15 (Pass Phrase Dialog)
Some of your private key files are encrypted for security reasons.
In order to read them you have to provide the pass phrases.

Server alteeve.ca:443 (RSA)
Enter pass phrase:

OK: Pass Phrase Dialog successful.
                                                           [  OK  ]
Warning: From now on, you will need to enter the pass-phrase to start Apache. Consider this when restarting your server and when deciding if you want the Apache server to start with your server. As my server is in a VM and it's underlying disk is also encrypted, I will enable it at boot time. I'll need to be watching the boot process anyway. This may not apply to you.

Now make sure that you can still connect to your server on TCP port 80 (normal http port). The contents after the GET request will obviously vary depending on your configuration:

telnet localhost 80
Trying ::1...
Connected to localhost.
Escape character is '^]'.
GET
<head>
	<title>Asakusa.alteeve.ca</title>
</head>
<body>
	Default - Requested domain not found
</body>
Connection closed by foreign host.

Now to check that the SSL port is listening properly. We can't use telnet because of the SSL encryption. Instead we will use openssl.

openssl s_client -connect localhost:443 -state -debug
CONNECTED(00000003)
SSL_connect:before/connect initialization
write to 0x196a050 [0x1a0b3a0] (113 bytes => 113 (0x71))
0000 - 16 03 01 00 6c 01 00 00-68 03 01 4d f8 f4 a4 f9   ....l...h..M....
0010 - 07 b3 11 f8 3d ff 5d 80-ed 69 87 52 e2 60 80 57   ....=.]..i.R.`.W
0020 - 59 c7 83 4c ea 5b e5 37-06 e0 13 00 00 3a 00 39   Y..L.[.7.....:.9
0030 - 00 38 00 88 00 87 00 35-00 84 00 16 00 13 00 0a   .8.....5........
0040 - 00 33 00 32 00 9a 00 99-00 45 00 44 00 2f 00 96   .3.2.....E.D./..
0050 - 00 41 00 05 00 04 00 15-00 12 00 09 00 14 00 11   .A..............
0060 - 00 08 00 06 00 03 00 ff-02 01 00 00 04 00 23      ..............#
0071 - <SPACES/NULS>
SSL_connect:SSLv2/v3 write client hello A
read from 0x196a050 [0x1a10900] (7 bytes => 7 (0x7))
0000 - 16 03 01 00 35 02                                 ....5.
0007 - <SPACES/NULS>
read from 0x196a050 [0x1a1090a] (51 bytes => 51 (0x33))
0000 - 00 31 03 01 4d f8 f4 a4-7d 35 00 74 24 43 bc c9   .1..M...}5.t$C..
0010 - 84 5d fe e3 90 1a e8 14-39 a1 b1 7e e8 19 c7 9f   .]......9..~....
0020 - 45 20 d1 cb 00 00 39 01-00 09 ff 01 00 01 00 00   E ....9.........
0030 - 23                                                #
0033 - <SPACES/NULS>
SSL_connect:SSLv3 read server hello A
read from 0x196a050 [0x1a10903] (5 bytes => 5 (0x5))
0000 - 16 03 01 0c 2c                                    ....,
read from 0x196a050 [0x1a10908] (3116 bytes => 3116 (0xC2C))
0000 - 0b 00 0c 28 00 0c 25 00-04 c2 30 82 04 be 30 82   ...(..%...0...0.
0010 - 03 a6 a0 03 02 01 02 02-03 02 15 24 30 0d 06 09   ...........$0...
0020 - 2a 86 48 86 f7 0d 01 01-05 05 00 30 3c 31 0b 30   *.H........0<1.0
0030 - 09 06 03 55 04 06 13 02-55 53 31 17 30 15 06 03   ...U....US1.0...
0040 - 55 04 0a 13 0e 47 65 6f-54 72 75 73 74 2c 20 49   U....GeoTrust, I
0050 - 6e 63 2e 31 14 30 12 06-03 55 04 03 13 0b 52 61   nc.1.0...U....Ra
0060 - 70 69 64 53 53 4c 20 43-41 30 1e 17 0d 31 31 30   pidSSL CA0...110
0070 - 36 31 34 31 32 31 39 30-31 5a 17 0d 31 31 30 37   614121901Z..1107
0080 - 31 36 31 35 35 36 31 34-5a 30 81 d9 31 29 30 27   16155614Z0..1)0'
0090 - 06 03 55 04 05 13 20 30-54 53 35 57 7a 61 75 51   ..U... 0TS5WzauQ
00a0 - 52 4a 37 73 63 32 62 2d-68 54 47 77 4b 31 79 78   RJ7sc2b-hTGwK1yx
00b0 - 53 66 45 44 70 68 46 31-0b 30 09 06 03 55 04 06   SfEDphF1.0...U..
00c0 - 13 02 43 41 31 14 30 12-06 03 55 04 0a 13 0b 61   ..CA1.0...U....a
00d0 - 6c 74 65 65 76 65 2e 63-6f 6d 31 13 30 11 06 03   lteeve.com1.0...
00e0 - 55 04 0b 13 0a 47 54 31-33 39 30 38 38 31 37 31   U....GT139088171
00f0 - 31 30 2f 06 03 55 04 0b-13 28 53 65 65 20 77 77   10/..U...(See ww
0100 - 77 2e 72 61 70 69 64 73-73 6c 2e 63 6f 6d 2f 72   w.rapidssl.com/r
0110 - 65 73 6f 75 72 63 65 73-2f 63 70 73 20 28 63 29   esources/cps (c)
0120 - 31 31 31 2b 30 29 06 03-55 04 0b 13 22 44 6f 6d   111+0)..U..."Dom
0130 - 61 69 6e 20 43 6f 6e 74-72 6f 6c 20 56 61 6c 69   ain Control Vali
0140 - 64 61 74 65 64 20 2d 20-46 72 65 65 53 53 4c 31   dated - FreeSSL1
0150 - 14 30 12 06 03 55 04 03-13 0b 61 6c 74 65 65 76   .0...U....alteev
0160 - 65 2e 63 6f 6d 30 82 01-22 30 0d 06 09 2a 86 48   e.com0.."0...*.H
0170 - 86 f7 0d 01 01 01 05 00-03 82 01 0f 00 30 82 01   .............0..
0180 - 0a 02 82 01 01 00 c7 b5-75 03 c7 a9 b5 21 b2 7a   ........u....!.z
0190 - 9b 70 8d f2 44 5d e0 18-f4 05 52 c6 93 d3 17 a5   .p..D]....R.....
01a0 - 3a c7 46 03 68 d1 01 53-1b e8 b8 d3 4c 56 46 b2   :.F.h..S....LVF.
01b0 - ca 63 34 88 2c 4f 7b 23-49 07 ef 8e 37 5c 8a ac   .c4.,O{#I...7\..
01c0 - d7 88 9b ed a1 01 90 bc-32 d8 46 30 6d 82 33 59   ........2.F0m.3Y
01d0 - ea b5 38 2c 8a 16 e1 63-e7 ba 39 d8 2a fa 8a 6b   ..8,...c..9.*..k
01e0 - 25 45 0b c9 4d b8 d2 be-a9 3a e3 ff 61 60 f9 a4   %E..M....:..a`..
01f0 - 99 4e 3f c2 25 0b 21 07-c6 1b 1e 63 71 2e 3d 31   .N?.%.!....cq.=1
0200 - 42 98 01 f4 88 b8 80 26-b7 bf 5b 00 b1 57 86 b4   B......&..[..W..
0210 - d8 70 e6 ec ea 98 e1 17-45 a7 ff 83 e0 76 6f 8a   .p......E....vo.
0220 - 50 bb 1d cb c5 8f f4 01-84 4e 59 c3 4d 28 73 70   P........NY.M(sp
0230 - 39 c8 da 85 43 b9 07 ae-57 26 04 24 b2 d6 d4 7c   9...C...W&.$...|
0240 - 03 af 4f 72 00 8f 20 ed-26 77 b3 bf 4e 01 62 8b   ..Or.. .&w..N.b.
0250 - 62 1b 10 16 65 92 f5 bb-5a dc 83 5c f2 56 f3 60   b...e...Z..\.V.`
0260 - 34 2c ef 62 f4 ee cf 26-6d 9b 4a 5e 74 05 74 fb   4,.b...&m.J^t.t.
0270 - 23 86 07 6f cf b0 48 6d-ba 2d 89 5d 0f e0 c0 01   #..o..Hm.-.]....
0280 - 1c 91 af 00 5f f3 02 03-01 00 01 a3 82 01 29 30   ...._.........)0
0290 - 82 01 25 30 1f 06 03 55-1d 23 04 18 30 16 80 14   ..%0...U.#..0...
02a0 - 6b 69 3d 6a 18 42 4a dd-8f 02 65 39 fd 35 24 86   ki=j.BJ...e9.5$.
02b0 - 78 91 16 30 30 0e 06 03-55 1d 0f 01 01 ff 04 04   x..00...U.......
02c0 - 03 02 05 a0 30 1d 06 03-55 1d 25 04 16 30 14 06   ....0...U.%..0..
02d0 - 08 2b 06 01 05 05 07 03-01 06 08 2b 06 01 05 05   .+.........+....
02e0 - 07 03 02 30 16 06 03 55-1d 11 04 0f 30 0d 82 0b   ...0...U....0...
02f0 - 61 6c 74 65 65 76 65 2e-63 6f 6d 30 43 06 03 55   alteeve.ca.0C..U
0300 - 1d 1f 04 3c 30 3a 30 38-a0 36 a0 34 86 32 68 74   ...<0:08.6.4.2ht
0310 - 74 70 3a 2f 2f 72 61 70-69 64 73 73 6c 2d 63 72   tp://rapidssl-cr
0320 - 6c 2e 67 65 6f 74 72 75-73 74 2e 63 6f 6d 2f 63   l.geotrust.com/c
0330 - 72 6c 73 2f 72 61 70 69-64 73 73 6c 2e 63 72 6c   rls/rapidssl.crl
0340 - 30 1d 06 03 55 1d 0e 04-16 04 14 a1 2b 4e af 55   0...U.......+N.U
0350 - 08 7b 34 be 74 fc 57 41-de bc 8f d9 4a 1d c9 30   .{4.t.WA....J..0
0360 - 0c 06 03 55 1d 13 01 01-ff 04 02 30 00 30 49 06   ...U.......0.0I.
0370 - 08 2b 06 01 05 05 07 01-01 04 3d 30 3b 30 39 06   .+........=0;09.
0380 - 08 2b 06 01 05 05 07 30-02 86 2d 68 74 74 70 3a   .+.....0..-http:
0390 - 2f 2f 72 61 70 69 64 73-73 6c 2d 61 69 61 2e 67   //rapidssl-aia.g
03a0 - 65 6f 74 72 75 73 74 2e-63 6f 6d 2f 72 61 70 69   eotrust.com/rapi
03b0 - 64 73 73 6c 2e 63 72 74-30 0d 06 09 2a 86 48 86   dssl.crt0...*.H.
03c0 - f7 0d 01 01 05 05 00 03-82 01 01 00 66 8b 6f a8   ............f.o.
03d0 - d5 d2 84 c7 89 31 fb a5-ba e1 11 5e 2f 67 6f df   .....1.....^/go.
03e0 - 0d 3c 0b 1a 4b ac d9 38-ee 29 0a 4d d9 06 98 2c   .<..K..8.).M...,
03f0 - 25 0a 59 bb 39 03 b0 cd-3b 06 93 3e 59 90 cf 06   %.Y.9...;..>Y...
0400 - 17 74 77 bb cd 91 34 d0-6f b9 8f 53 57 ed 14 30   .tw...4.o..SW..0
0410 - bd e9 6c 04 84 b6 f0 16-9d 29 9b b1 47 f8 84 64   ..l......)..G..d
0420 - 5f 03 36 ea e1 d6 13 97-5b 50 b9 b2 59 cc f8 ef   _.6.....[P..Y...
0430 - 23 01 99 91 6e 5e e8 d0-77 54 38 49 18 58 e7 0e   #...n^..wT8I.X..
0440 - 54 35 c0 37 b5 9e 79 b2-d4 c6 d9 ff 27 31 d4 bf   T5.7..y.....'1..
0450 - 04 ae d3 0a 90 4b bc 34-bc 53 f8 bc e7 4c 22 b7   .....K.4.S...L".
0460 - b3 bc 8c d7 41 44 fc e0-50 2e 9a ac ba 5c ee 88   ....AD..P....\..
0470 - 03 fc 0e 53 32 aa dd a4-24 ee a6 7c 3d dc 9d 7a   ...S2...$..|=..z
0480 - 82 0b 9f b8 91 e0 a1 12-77 a3 95 f7 d0 c4 9e f1   ........w.......
0490 - d7 d9 99 68 80 e8 af ad-68 f5 1a 5f 66 06 78 c9   ...h....h.._f.x.
04a0 - 56 f8 36 37 16 fa 7d 27-df 1d a2 d8 7c 8c 5b 50   V.67..}'....|.[P
04b0 - db c6 fe 06 ff 96 86 f5-1f e4 35 ce cf 43 66 53   ..........5..CfS
04c0 - da a1 50 b5 c0 73 ec 1e-f4 c8 20 13 00 03 d9 30   ..P..s.... ....0
04d0 - 82 03 d5 30 82 02 bd a0-03 02 01 02 02 03 02 36   ...0...........6
04e0 - d1 30 0d 06 09 2a 86 48-86 f7 0d 01 01 05 05 00   .0...*.H........
04f0 - 30 42 31 0b 30 09 06 03-55 04 06 13 02 55 53 31   0B1.0...U....US1
0500 - 16 30 14 06 03 55 04 0a-13 0d 47 65 6f 54 72 75   .0...U....GeoTru
0510 - 73 74 20 49 6e 63 2e 31-1b 30 19 06 03 55 04 03   st Inc.1.0...U..
0520 - 13 12 47 65 6f 54 72 75-73 74 20 47 6c 6f 62 61   ..GeoTrust Globa
0530 - 6c 20 43 41 30 1e 17 0d-31 30 30 32 31 39 32 32   l CA0...10021922
0540 - 34 35 30 35 5a 17 0d 32-30 30 32 31 38 32 32 34   4505Z..200218224
0550 - 35 30 35 5a 30 3c 31 0b-30 09 06 03 55 04 06 13   505Z0<1.0...U...
0560 - 02 55 53 31 17 30 15 06-03 55 04 0a 13 0e 47 65   .US1.0...U....Ge
0570 - 6f 54 72 75 73 74 2c 20-49 6e 63 2e 31 14 30 12   oTrust, Inc.1.0.
0580 - 06 03 55 04 03 13 0b 52-61 70 69 64 53 53 4c 20   ..U....RapidSSL 
0590 - 43 41 30 82 01 22 30 0d-06 09 2a 86 48 86 f7 0d   CA0.."0...*.H...
05a0 - 01 01 01 05 00 03 82 01-0f 00 30 82 01 0a 02 82   ..........0.....
05b0 - 01 01 00 c7 71 f8 56 c7-1e d9 cc b5 ad f6 b4 97   ....q.V.........
05c0 - a3 fb a1 e6 0b 50 5f 50-aa 3a da 0f fc 3d 29 24   .....P_P.:...=)$
05d0 - 43 c6 10 29 c1 fc 55 40-72 ee bd ea df 9f b6 41   C..)..U@r......A
05e0 - f4 48 4b c8 6e fe 4f 57-12 8b 5b fa 92 dd 5e e8   .HK.n.OW..[...^.
05f0 - ad f3 f0 1b b1 7b 4d fb-cf fd d1 e5 f8 e3 dc e7   .....{M.........
0600 - f5 73 7f df 01 49 cf 8c-56 c1 bd 37 e3 5b be b5   .s...I..V..7.[..
0610 - 4f 8b 8b f0 da 4f c7 e3-dd 55 47 69 df f2 5b 7b   O....O...UGi..[{
0620 - 07 4f 3d e5 ac 21 c1 c8-1d 7a e8 e7 f6 0f a1 aa   .O=..!...z......
0630 - f5 6f de a8 65 4f 10 89-9c 03 f3 89 7a a5 5e 01   .o..eO......z.^.
0640 - 72 33 ed a9 e9 5a 1e 79-f3 87 c8 df c8 c5 fc 37   r3...Z.y.......7
0650 - c8 9a 9a d7 b8 76 cc b0-3e e7 fd e6 54 ea df 5f   .....v..>...T.._
0660 - 52 41 78 59 57 ad f1 12-d6 7f bc d5 9f 70 d3 05   RAxYW........p..
0670 - 6c fa a3 7d 67 58 dd 26-62 1d 31 92 0c 79 79 1c   l..}gX.&b.1..yy.
0680 - 8e cf ca 7b c1 66 af a8-74 48 fb 8e 82 c2 9e 2c   ...{.f..tH.....,
0690 - 99 5c 7b 2d 5d 9b bc 5b-57 9e 7c 3a 7a 13 ad f2   .\{-]..[W.|:z...
06a0 - a3 18 5b 2b 59 0f cd 5c-3a eb 68 33 c6 28 1d 82   ..[+Y..\:.h3.(..
06b0 - d1 50 8b 02 03 01 00 01-a3 81 d9 30 81 d6 30 0e   .P.........0..0.
06c0 - 06 03 55 1d 0f 01 01 ff-04 04 03 02 01 06 30 1d   ..U...........0.
06d0 - 06 03 55 1d 0e 04 16 04-14 6b 69 3d 6a 18 42 4a   ..U......ki=j.BJ
06e0 - dd 8f 02 65 39 fd 35 24-86 78 91 16 30 30 1f 06   ...e9.5$.x..00..
06f0 - 03 55 1d 23 04 18 30 16-80 14 c0 7a 98 68 8d 89   .U.#..0....z.h..
0700 - fb ab 05 64 0c 11 7d aa-7d 65 b8 ca cc 4e 30 12   ...d..}.}e...N0.
0710 - 06 03 55 1d 13 01 01 ff-04 08 30 06 01 01 ff 02   ..U.......0.....
0720 - 01 00 30 3a 06 03 55 1d-1f 04 33 30 31 30 2f a0   ..0:..U...3010/.
0730 - 2d a0 2b 86 29 68 74 74-70 3a 2f 2f 63 72 6c 2e   -.+.)http://crl.
0740 - 67 65 6f 74 72 75 73 74-2e 63 6f 6d 2f 63 72 6c   geotrust.com/crl
0750 - 73 2f 67 74 67 6c 6f 62-61 6c 2e 63 72 6c 30 34   s/gtglobal.crl04
0760 - 06 08 2b 06 01 05 05 07-01 01 04 28 30 26 30 24   ..+........(0&0$
0770 - 06 08 2b 06 01 05 05 07-30 01 86 18 68 74 74 70   ..+.....0...http
0780 - 3a 2f 2f 6f 63 73 70 2e-67 65 6f 74 72 75 73 74   ://ocsp.geotrust
0790 - 2e 63 6f 6d 30 0d 06 09-2a 86 48 86 f7 0d 01 01   .com0...*.H.....
07a0 - 05 05 00 03 82 01 01 00-ab bc bc 0a 5d 18 94 e3   ............]...
07b0 - c1 b1 c3 a8 4c 55 d6 be-b4 98 f1 ee 3c 1c cd cf   ....LU......<...
07c0 - f3 24 24 5c 96 03 27 58-fc 36 ae a2 2f 8f f1 fe   .$$\..'X.6../...
07d0 - da 2b 02 c3 33 bd c8 dd-48 22 2b 60 0f a5 03 10   .+..3...H"+`....
07e0 - fd 77 f8 d0 ed 96 67 4f-fd ea 47 20 70 54 dc a9   .w....gO..G pT..
07f0 - 0c 55 7e e1 96 25 8a d9-b5 da 57 4a be 8d 8e 49   .U~..%....WJ...I
0800 - 43 63 a5 6c 4e 27 87 25-eb 5b 6d fe a2 7f 38 28   Cc.lN'.%.[m...8(
0810 - e0 36 ab ad 39 a5 a5 62-c4 b7 5c 58 2c aa 5d 01   .6..9..b..\X,.].
0820 - 60 a6 62 67 a3 c0 c7 62-23 f4 e7 6c 46 ee b5 d3   `.bg...b#..lF...
0830 - 80 6a 22 13 d2 2d 3f 74-4f ea af 8c 5f b4 38 9c   .j"..-?tO..._.8.
0840 - db ae ce af 84 1e a6 f6-34 51 59 79 d3 e3 75 dc   ........4QYy..u.
0850 - bc d7 f3 73 df 92 ec d2-20 59 6f 9c fb 95 f8 92   ...s.... Yo.....
0860 - 76 18 0a 7c 0f 2c a6 ca-de 8a 62 7b d8 f3 ce 5f   v..|.,....b{..._
0870 - 68 bd 8f 3e c1 74 bb 15-72 3a 16 83 a9 0b e6 4d   h..>.t..r:.....M
0880 - 99 9c d8 57 ec a8 01 51-c7 6f 57 34 5e ab 4a 2c   ...W...Q.oW4^.J,
0890 - 42 f6 4f 1c 89 78 de 26-4e f5 6f 93 4c 15 6b 27   B.O..x.&N.o.L.k'
08a0 - 56 4d 00 54 6c 7a b7 b7-00 03 81 30 82 03 7d 30   VM.Tlz.....0..}0
08b0 - 82 02 e6 a0 03 02 01 02-02 03 12 bb e6 30 0d 06   .............0..
08c0 - 09 2a 86 48 86 f7 0d 01-01 05 05 00 30 4e 31 0b   .*.H........0N1.
08d0 - 30 09 06 03 55 04 06 13-02 55 53 31 10 30 0e 06   0...U....US1.0..
08e0 - 03 55 04 0a 13 07 45 71-75 69 66 61 78 31 2d 30   .U....Equifax1-0
08f0 - 2b 06 03 55 04 0b 13 24-45 71 75 69 66 61 78 20   +..U...$Equifax 
0900 - 53 65 63 75 72 65 20 43-65 72 74 69 66 69 63 61   Secure Certifica
0910 - 74 65 20 41 75 74 68 6f-72 69 74 79 30 1e 17 0d   te Authority0...
0920 - 30 32 30 35 32 31 30 34-30 30 30 30 5a 17 0d 31   020521040000Z..1
0930 - 38 30 38 32 31 30 34 30-30 30 30 5a 30 42 31 0b   80821040000Z0B1.
0940 - 30 09 06 03 55 04 06 13-02 55 53 31 16 30 14 06   0...U....US1.0..
0950 - 03 55 04 0a 13 0d 47 65-6f 54 72 75 73 74 20 49   .U....GeoTrust I
0960 - 6e 63 2e 31 1b 30 19 06-03 55 04 03 13 12 47 65   nc.1.0...U....Ge
0970 - 6f 54 72 75 73 74 20 47-6c 6f 62 61 6c 20 43 41   oTrust Global CA
0980 - 30 82 01 22 30 0d 06 09-2a 86 48 86 f7 0d 01 01   0.."0...*.H.....
0990 - 01 05 00 03 82 01 0f 00-30 82 01 0a 02 82 01 01   ........0.......
09a0 - 00 da cc 18 63 30 fd f4-17 23 1a 56 7e 5b df 3c   ....c0...#.V~[.<
09b0 - 6c 38 e4 71 b7 78 91 d4-bc a1 d8 4c f8 a8 43 b6   l8.q.x.....L..C.
09c0 - 03 e9 4d 21 07 08 88 da-58 2f 66 39 29 bd 05 78   ..M!....X/f9)..x
09d0 - 8b 9d 38 e8 05 b7 6a 7e-71 a4 e6 c4 60 a6 b0 ef   ..8...j~q...`...
09e0 - 80 e4 89 28 0f 9e 25 d6-ed 83 f3 ad a6 91 c7 98   ...(..%.........
09f0 - c9 42 18 35 14 9d ad 98-46 92 2e 4f ca f1 87 43   .B.5....F..O...C
0a00 - c1 16 95 57 2d 50 ef 89-2d 80 7a 57 ad f2 ee 5f   ...W-P..-.zW..._
0a10 - 6b d2 00 8d b9 14 f8 14-15 35 d9 c0 46 a3 7b 72   k........5..F.{r
0a20 - c8 91 bf c9 55 2b cd d0-97 3e 9c 26 64 cc df ce   ....U+...>.&d...
0a30 - 83 19 71 ca 4e e6 d4 d5-7b a9 19 cd 55 de c8 ec   ..q.N...{...U...
0a40 - d2 5e 38 53 e5 5c 4f 8c-2d fe 50 23 36 fc 66 e6   .^8S.\O.-.P#6.f.
0a50 - cb 8e a4 39 19 00 b7 95-02 39 91 0b 0e fe 38 2e   ...9.....9....8.
0a60 - d1 1d 05 9a f6 4d 3e 6f-0f 07 1d af 2c 1e 8f 60   .....M>o....,..`
0a70 - 39 e2 fa 36 53 13 39 d4-5e 26 2b db 3d a8 14 bd   9..6S.9.^&+.=...
0a80 - 32 eb 18 03 28 52 04 71-e5 ab 33 3d e1 38 bb 07   2...(R.q..3=.8..
0a90 - 36 84 62 9c 79 ea 16 30-f4 5f c0 2b e8 71 6b e4   6.b.y..0._.+.qk.
0aa0 - f9 02 03 01 00 01 a3 81-f0 30 81 ed 30 1f 06 03   .........0..0...
0ab0 - 55 1d 23 04 18 30 16 80-14 48 e6 68 f9 2b d2 b2   U.#..0...H.h.+..
0ac0 - 95 d7 47 d8 23 20 10 4f-33 98 90 9f d4 30 1d 06   ..G.# .O3....0..
0ad0 - 03 55 1d 0e 04 16 04 14-c0 7a 98 68 8d 89 fb ab   .U.......z.h....
0ae0 - 05 64 0c 11 7d aa 7d 65-b8 ca cc 4e 30 0f 06 03   .d..}.}e...N0...
0af0 - 55 1d 13 01 01 ff 04 05-30 03 01 01 ff 30 0e 06   U.......0....0..
0b00 - 03 55 1d 0f 01 01 ff 04-04 03 02 01 06 30 3a 06   .U...........0:.
0b10 - 03 55 1d 1f 04 33 30 31-30 2f a0 2d a0 2b 86 29   .U...3010/.-.+.)
0b20 - 68 74 74 70 3a 2f 2f 63-72 6c 2e 67 65 6f 74 72   http://crl.geotr
0b30 - 75 73 74 2e 63 6f 6d 2f-63 72 6c 73 2f 73 65 63   ust.com/crls/sec
0b40 - 75 72 65 63 61 2e 63 72-6c 30 4e 06 03 55 1d 20   ureca.crl0N..U. 
0b50 - 04 47 30 45 30 43 06 04-55 1d 20 00 30 3b 30 39   .G0E0C..U. .0;09
0b60 - 06 08 2b 06 01 05 05 07-02 01 16 2d 68 74 74 70   ..+........-http
0b70 - 73 3a 2f 2f 77 77 77 2e-67 65 6f 74 72 75 73 74   s://www.geotrust
0b80 - 2e 63 6f 6d 2f 72 65 73-6f 75 72 63 65 73 2f 72   .com/resources/r
0b90 - 65 70 6f 73 69 74 6f 72-79 30 0d 06 09 2a 86 48   epository0...*.H
0ba0 - 86 f7 0d 01 01 05 05 00-03 81 81 00 76 e1 12 6e   ............v..n
0bb0 - 4e 4b 16 12 86 30 06 b2-81 08 cf f0 08 c7 c7 71   NK...0.........q
0bc0 - 7e 66 ee c2 ed d4 3b 1f-ff f0 f0 c8 4e d6 43 38   ~f....;.....N.C8
0bd0 - b0 b9 30 7d 18 d0 55 83-a2 6a cb 36 11 9c e8 48   ..0}..U..j.6...H
0be0 - 66 a3 6d 7f b8 13 d4 47-fe 8b 5a 5c 73 fc ae d9   f.m....G..Z\s...
0bf0 - 1b 32 19 38 ab 97 34 14-aa 96 d2 eb a3 1c 14 08   .2.8..4.........
0c00 - 49 b6 bb e5 91 ef 83 36-eb 1d 56 6f ca da bc 73   I......6..Vo...s
0c10 - 63 90 e4 7f 7b 3e 22 cb-3d 07 ed 5f 38 74 9c e3   c...{>".=.._8t..
0c20 - 03 50 4e a1 af 98 ee 61-f2 84 3f 12               .PN....a..?.
depth=3 C = US, O = Equifax, OU = Equifax Secure Certificate Authority
verify return:1
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
verify return:1
depth=1 C = US, O = "GeoTrust, Inc.", CN = RapidSSL CA
verify return:1
depth=0 serialNumber = 0TS5WzauQRJ7sc2b-hTGwK1yxSfEDphF, C = CA, O = alteeve.ca, OU = GT13908817, OU = See www.rapidssl.com/resources/cps (c)11, OU = Domain Control Validated - FreeSSL, CN = alteeve.ca
verify return:1
SSL_connect:SSLv3 read server certificate A
read from 0x196a050 [0x1a10903] (5 bytes => 5 (0x5))
0000 - 16 03 01 02 0d                                    .....
read from 0x196a050 [0x1a10908] (525 bytes => 525 (0x20D))
0000 - 0c 00 02 09 00 80 d6 7d-e4 40 cb bb dc 19 36 d6   .......}.@....6.
0010 - 93 d3 4a fd 0a d5 0c 84-d2 39 a4 5f 52 0b b8 81   ..J......9._R...
0020 - 74 cb 98 bc e9 51 84 9f-91 2e 63 9c 72 fb 13 b4   t....Q....c.r...
0030 - b4 d7 17 7e 16 d5 5a c1-79 ba 42 0b 2a 29 fe 32   ...~..Z.y.B.*).2
0040 - 4a 46 7a 63 5e 81 ff 59-01 37 7b ed dc fd 33 16   JFzc^..Y.7{...3.
0050 - 8a 46 1a ad 3b 72 da e8-86 00 78 04 5b 07 a7 db   .F..;r....x.[...
0060 - ca 78 74 08 7d 15 10 ea-9f cc 9d dd 33 05 07 dd   .xt.}.......3...
0070 - 62 db 88 ae aa 74 7d e0-f4 d6 e2 bd 68 b0 e7 39   b....t}.....h..9
0080 - 3e 0f 24 21 8e b3 00 01-02 00 80 51 5c 13 33 38   >.$!.......Q\.38
0090 - 83 ef 76 6f 23 52 55 bf-23 ba 7f f0 a4 ca 35 01   ..vo#RU.#.....5.
00a0 - 9c 70 e1 61 b2 0d 7b 5c-1c 32 02 c1 ac 14 be e9   .p.a..{\.2......
00b0 - b9 7a 5d 11 9b 53 48 64-cd 12 b8 15 4c df cc 10   .z]..SHd....L...
00c0 - 4e 2b e7 cd 3f 33 68 1a-60 cc f7 18 25 7c e5 ca   N+..?3h.`...%|..
00d0 - c8 cb 45 ba 2a 6d dc 84-5f 26 6f 9a a3 73 b9 7f   ..E.*m.._&o..s..
00e0 - 02 cb 7b a7 ac 59 9f f3-6e c9 01 ed b9 35 99 49   ..{..Y..n....5.I
00f0 - 37 77 68 65 ec e2 f7 17-03 e7 f5 f5 86 33 e6 6c   7whe.........3.l
0100 - 06 3c 15 83 98 74 2e b9-83 31 11 01 00 20 6e 17   .<...t...1... n.
0110 - 3d 2d ec 3e 19 b2 9e 5b-37 38 3a 31 57 3d 0e c1   =-.>...[78:1W=..
0120 - 6b c4 b4 83 d9 6b f0 d3-44 db 9f 18 55 15 e1 09   k....k..D...U...
0130 - 73 59 8c 46 3d a4 47 58-b1 71 a3 32 b5 06 26 8c   sY.F=.GX.q.2..&.
0140 - 27 88 9e 13 c8 12 5d 94-9b 24 54 10 aa 79 e5 b4   '.....]..$T..y..
0150 - 43 f5 5e 4c 01 dc 02 aa-69 02 37 71 4e 26 1c 0b   C.^L....i.7qN&..
0160 - 40 19 c9 95 4d af 93 35-07 7a ff b1 96 7f 03 ce   @...M..5.z......
0170 - 7a eb a2 1c 97 6b d2 97-d2 0f 1a f5 b2 af fb 65   z....k.........e
0180 - 86 b9 e3 38 30 ba f5 02-d6 6b fc da 94 93 8b b3   ...80....k......
0190 - 96 b5 b7 58 dc 36 55 6d-e9 47 e5 4a 33 1d b9 d9   ...X.6Um.G.J3...
01a0 - ec 33 e8 fb 58 c8 74 13-ff dd 40 b7 35 56 63 03   .3..X.t...@.5Vc.
01b0 - 9f 16 2f 72 be 56 56 c3-15 3a c3 10 09 f0 9d f2   ../r.VV..:......
01c0 - 42 52 5a ce d6 db 61 0e-d0 e2 ac 2e 9e 04 30 8e   BRZ...a.......0.
01d0 - 0d d7 07 f9 3e 0a a8 3b-8d 11 5c 6e 21 47 28 2d   ....>..;..\n!G(-
01e0 - 28 31 a6 3d d0 e9 2e 7a-de 4a 00 2a a8 6f 5d 82   (1.=...z.J.*.o].
01f0 - 45 df 3e 06 e3 11 e3 3c-b9 1e 34 b8 bd 60 fd a7   E.>....<..4..`..
0200 - a2 c1 c8 19 61 19 da 10-e4 c3 70 7e 5f            ....a.....p~_
SSL_connect:SSLv3 read server key exchange A
read from 0x196a050 [0x1a10903] (5 bytes => 5 (0x5))
0000 - 16 03 01 00 04                                    .....
read from 0x196a050 [0x1a10908] (4 bytes => 4 (0x4))
0000 - 0e                                                .
0004 - <SPACES/NULS>
SSL_connect:SSLv3 read server done A
write to 0x196a050 [0x1a1add0] (139 bytes => 139 (0x8B))
0000 - 16 03 01 00 86 10 00 00-82 00 80 7f 9d d2 3b 68   ..............;h
0010 - 49 c9 dd ed 4f 35 a0 70-3a 28 0f ce c1 5a 81 ce   I...O5.p:(...Z..
0020 - cd 46 c5 e5 a4 44 25 04-4e b4 48 d8 3b a6 d4 44   .F...D%.N.H.;..D
0030 - 4e 9a dc 20 fa 52 9f eb-52 3b 3c 3e 34 dc ed 34   N.. .R..R;<>4..4
0040 - e5 b7 10 f9 6d 3a c0 84-64 bf b8 91 54 6c 37 1b   ....m:..d...Tl7.
0050 - eb 75 7a 95 aa e8 83 6f-e0 16 f2 af 77 0f 7a 0c   .uz....o....w.z.
0060 - a8 82 27 a4 a5 f2 f0 1b-d2 6e 46 c4 ef 10 7c 39   ..'......nF...|9
0070 - 6c 87 74 ec 68 7e d5 9a-10 ab 10 03 75 a2 fb 4b   l.t.h~......u..K
0080 - 8c 49 4c da 64 49 bd 27-ba 51 a4                  .IL.dI.'.Q.
SSL_connect:SSLv3 write client key exchange A
write to 0x196a050 [0x1a1add0] (6 bytes => 6 (0x6))
0000 - 14 03 01 00 01 01                                 ......
SSL_connect:SSLv3 write change cipher spec A
write to 0x196a050 [0x1a1add0] (53 bytes => 53 (0x35))
0000 - 16 03 01 00 30 b4 8a 74-4d a4 bf b1 54 04 8a 25   ....0..tM...T..%
0010 - 24 f8 81 f1 64 9f 1f 6d-fb bd a7 4c 57 6a a5 63   $...d..m...LWj.c
0020 - fb 3a dd 8e e3 f9 38 f6-22 fd 7e 42 81 2e a2 41   .:....8.".~B...A
0030 - 1f 74 d1 27 02                                    .t.'.
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
read from 0x196a050 [0x1a10903] (5 bytes => 5 (0x5))
0000 - 16 03 01 00 ca                                    .....
read from 0x196a050 [0x1a10908] (202 bytes => 202 (0xCA))
0000 - 04 00 00 c6 00 00 00 00-00 c0 6c f3 41 26 c8 6b   ..........l.A&.k
0010 - 1e 9c 2e 78 af 75 b2 46-34 f4 30 c3 bd e4 ee 2f   ...x.u.F4.0..../
0020 - f6 28 37 f6 7c 55 3b c7-08 ad 1e 48 f1 83 9f 9a   .(7.|U;....H....
0030 - d4 ef 9b 7d 5a 9c f7 5b-92 e9 2f ca c3 e5 44 c7   ...}Z..[../...D.
0040 - 7a c1 ed db 98 1a 18 bd-25 30 3c 50 ad 96 23 22   z.......%0<P..#"
0050 - 7e a1 b7 eb 1d b5 cc 69-2a 43 63 13 4f 21 90 32   ~......i*Cc.O!.2
0060 - 87 94 0b 6a 66 da 99 fa-45 79 cc 53 29 35 59 0d   ...jf...Ey.S)5Y.
0070 - 02 93 c6 c6 af f3 52 79-b5 36 c0 a6 4d 22 9f af   ......Ry.6..M"..
0080 - 4a f2 86 b4 50 68 83 b1-ab a6 a6 ac 6e 4e 18 3d   J...Ph......nN.=
0090 - 80 a7 b4 85 77 06 69 60-fa b2 22 9a 79 14 c6 3e   ....w.i`..".y..>
00a0 - 3e 68 33 4e 1e a9 40 09-47 d0 02 97 8b ba 39 db   >h3N..@.G.....9.
00b0 - 2f b1 1c 2e 66 49 d3 bc-99 cc 56 4f 1d f4 c6 7b   /...fI....VO...{
00c0 - 58 3e 28 df b1 ce 2b 45-36 ca                     X>(...+E6.
SSL_connect:SSLv3 read server session ticket A
read from 0x196a050 [0x1a10903] (5 bytes => 5 (0x5))
0000 - 14 03 01 00 01                                    .....
read from 0x196a050 [0x1a10908] (1 bytes => 1 (0x1))
0000 - 01                                                .
read from 0x196a050 [0x1a10903] (5 bytes => 5 (0x5))
0000 - 16 03 01 00 30                                    ....0
read from 0x196a050 [0x1a10908] (48 bytes => 48 (0x30))
0000 - c0 79 35 bf c6 1e 7e d4-04 cf 68 c7 9d f5 9f 42   .y5...~...h....B
0010 - 03 91 5f 72 ae 5b ec a8-aa e7 af e8 f3 39 1b cd   .._r.[.......9..
0020 - 13 05 56 f2 1b 28 c9 42-4b 67 88 48 20 c2 a5 06   ..V..(.BKg.H ...
SSL_connect:SSLv3 read finished A
---
Certificate chain
 0 s:/serialNumber=0TS5WzauQRJ7sc2b-hTGwK1yxSfEDphF/C=CA/O=alteeve.ca/OU=GT13908817/OU=See www.rapidssl.com/resources/cps (c)11/OU=Domain Control Validated - FreeSSL/CN=alteeve.ca
   i:/C=US/O=GeoTrust, Inc./CN=RapidSSL CA
 1 s:/C=US/O=GeoTrust, Inc./CN=RapidSSL CA
   i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
 2 s:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
   i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIEvjCCA6agAwIBAgIDAhUkMA0GCSqGSIb3DQEBBQUAMDwxCzAJBgNVBAYTAlVT
MRcwFQYDVQQKEw5HZW9UcnVzdCwgSW5jLjEUMBIGA1UEAxMLUmFwaWRTU0wgQ0Ew
HhcNMTEwNjE0MTIxOTAxWhcNMTEwNzE2MTU1NjE0WjCB2TEpMCcGA1UEBRMgMFRT
NVd6YXVRUko3c2MyYi1oVEd3SzF5eFNmRURwaEYxCzAJBgNVBAYTAkNBMRQwEgYD
VQQKEwthbHRlZXZlLmNvbTETMBEGA1UECxMKR1QxMzkwODgxNzExMC8GA1UECxMo
U2VlIHd3dy5yYXBpZHNzbC5jb20vcmVzb3VyY2VzL2NwcyAoYykxMTErMCkGA1UE
CxMiRG9tYWluIENvbnRyb2wgVmFsaWRhdGVkIC0gRnJlZVNTTDEUMBIGA1UEAxML
YWx0ZWV2ZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDHtXUD
x6m1IbJ6m3CN8kRd4Bj0BVLGk9MXpTrHRgNo0QFTG+i400xWRrLKYzSILE97I0kH
7443XIqs14ib7aEBkLwy2EYwbYIzWeq1OCyKFuFj57o52Cr6imslRQvJTbjSvqk6
4/9hYPmkmU4/wiULIQfGGx5jcS49MUKYAfSIuIAmt79bALFXhrTYcObs6pjhF0Wn
/4Pgdm+KULsdy8WP9AGETlnDTShzcDnI2oVDuQeuVyYEJLLW1HwDr09yAI8g7SZ3
s79OAWKLYhsQFmWS9bta3INc8lbzYDQs72L07s8mbZtKXnQFdPsjhgdvz7BIbbot
iV0P4MABHJGvAF/zAgMBAAGjggEpMIIBJTAfBgNVHSMEGDAWgBRraT1qGEJK3Y8C
ZTn9NSSGeJEWMDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEG
CCsGAQUFBwMCMBYGA1UdEQQPMA2CC2FsdGVldmUuY29tMEMGA1UdHwQ8MDowOKA2
oDSGMmh0dHA6Ly9yYXBpZHNzbC1jcmwuZ2VvdHJ1c3QuY29tL2NybHMvcmFwaWRz
c2wuY3JsMB0GA1UdDgQWBBShK06vVQh7NL50/FdB3ryP2UodyTAMBgNVHRMBAf8E
AjAAMEkGCCsGAQUFBwEBBD0wOzA5BggrBgEFBQcwAoYtaHR0cDovL3JhcGlkc3Ns
LWFpYS5nZW90cnVzdC5jb20vcmFwaWRzc2wuY3J0MA0GCSqGSIb3DQEBBQUAA4IB
AQBmi2+o1dKEx4kx+6W64RFeL2dv3w08CxpLrNk47ikKTdkGmCwlClm7OQOwzTsG
kz5ZkM8GF3R3u82RNNBvuY9TV+0UML3pbASEtvAWnSmbsUf4hGRfAzbq4dYTl1tQ
ubJZzPjvIwGZkW5e6NB3VDhJGFjnDlQ1wDe1nnmy1MbZ/ycx1L8ErtMKkEu8NLxT
+LznTCK3s7yM10FE/OBQLpqsulzuiAP8DlMyqt2kJO6mfD3cnXqCC5+4keChEnej
lffQxJ7x19mZaIDor61o9RpfZgZ4yVb4NjcW+n0n3x2i2HyMW1Dbxv4G/5aG9R/k
Nc7PQ2ZT2qFQtcBz7B70yCAT
-----END CERTIFICATE-----
subject=/serialNumber=0TS5WzauQRJ7sc2b-hTGwK1yxSfEDphF/C=CA/O=alteeve.ca/OU=GT13908817/OU=See www.rapidssl.com/resources/cps (c)11/OU=Domain Control Validated - FreeSSL/CN=alteeve.ca
issuer=/C=US/O=GeoTrust, Inc./CN=RapidSSL CA
---
No client certificate CA names sent
---
SSL handshake has read 3984 bytes and written 311 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: zlib compression
Expansion: zlib compression
SSL-Session:
    Protocol  : TLSv1
    Cipher    : DHE-RSA-AES256-SHA
    Session-ID: 2880725EB8BDD73F469C17BCA54DF373DFE8EDE3D52A1C8F5E0A5919694FB111
    Session-ID-ctx: 
    Master-Key: F329DEA0DF39FF181ACFBCA69BEC417D7CAA4399D73229A1D912CC8236A858FD099B834F5B32C9BF979C4B5948196FC9
    Key-Arg   : None
    Krb5 Principal: None
    PSK identity: None
    PSK identity hint: None
    TLS session ticket:
    0000 - 6c f3 41 26 c8 6b 1e 9c-2e 78 af 75 b2 46 34 f4   l.A&.k...x.u.F4.
    0010 - 30 c3 bd e4 ee 2f f6 28-37 f6 7c 55 3b c7 08 ad   0..../.(7.|U;...
    0020 - 1e 48 f1 83 9f 9a d4 ef-9b 7d 5a 9c f7 5b 92 e9   .H.......}Z..[..
    0030 - 2f ca c3 e5 44 c7 7a c1-ed db 98 1a 18 bd 25 30   /...D.z.......%0
    0040 - 3c 50 ad 96 23 22 7e a1-b7 eb 1d b5 cc 69 2a 43   <P..#"~......i*C
    0050 - 63 13 4f 21 90 32 87 94-0b 6a 66 da 99 fa 45 79   c.O!.2...jf...Ey
    0060 - cc 53 29 35 59 0d 02 93-c6 c6 af f3 52 79 b5 36   .S)5Y.......Ry.6
    0070 - c0 a6 4d 22 9f af 4a f2-86 b4 50 68 83 b1 ab a6   ..M"..J...Ph....
    0080 - a6 ac 6e 4e 18 3d 80 a7-b4 85 77 06 69 60 fa b2   ..nN.=....w.i`..
    0090 - 22 9a 79 14 c6 3e 3e 68-33 4e 1e a9 40 09 47 d0   ".y..>>h3N..@.G.
    00a0 - 02 97 8b ba 39 db 2f b1-1c 2e 66 49 d3 bc 99 cc   ....9./...fI....
    00b0 - 56 4f 1d f4 c6 7b 58 3e-28 df b1 ce 2b 45 36 ca   VO...{X>(...+E6.

    Compression: 1 (zlib compression)
    Start Time: 1308161188
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---
GET
write to 0x196a050 [0x1a14e56] (74 bytes => 74 (0x4A))
0000 - 17 03 01 00 20 8a 4c 57-8c b9 d5 d4 c6 1b 56 ce   .... .LW......V.
0010 - 93 b5 78 6b 5f 0e c5 a2-39 2a f9 7a 20 7d 68 85   ..xk_...9*.z }h.
0020 - af 52 e3 5f fc 17 03 01-00 20 c6 c4 19 74 61 64   .R._..... ...tad
0030 - 42 59 e0 52 3f 42 44 53-8b c9 40 69 1c 3d 9b 7f   BY.R?BDS..@i.=..
0040 - aa e8 8f a4 5c de c9 d4-0a a4                     ....\.....
read from 0x196a050 [0x1a10903] (5 bytes => 5 (0x5))
0000 - 17 03 01 00 60                                    ....`
read from 0x196a050 [0x1a10908] (96 bytes => 96 (0x60))
0000 - 46 4c 99 93 29 c9 ed 66-81 43 89 39 26 2b d1 b0   FL..)..f.C.9&+..
0010 - 19 73 eb 51 18 45 54 49-74 43 e0 92 1b f8 af f0   .s.Q.ETItC......
0020 - 0d e1 08 79 96 38 e1 5e-29 9d 66 9c 30 04 8e c4   ...y.8.^).f.0...
0030 - 10 83 49 7e 09 d7 8a ff-4b 11 f9 13 3e ac 77 73   ..I~....K...>.ws
0040 - e8 94 e3 f3 74 db 4e 5f-67 13 1d c4 3a 06 98 b3   ....t.N_g...:...
0050 - da 20 41 3c ca 9a fb 3f-f3 d7 64 a1 e9 f4 0a 98   . A<...?..d.....
<head>
	<title>AN!Wiki - SSL Test Server</title>
</head>
<body>
	<h1>SSL Test</h1>
</body>
read from 0x196a050 [0x1a10903] (5 bytes => 5 (0x5))
0000 - 15 03 01                                          ...
0005 - <SPACES/NULS>
read from 0x196a050 [0x1a10908] (32 bytes => 32 (0x20))
0000 - 2e bb a7 d6 dc ce 6c 34-dc 2e 43 c7 89 02 a9 5c   ......l4..C....\
0010 - 3b 3e d0 43 1c ec fa c7-89 48 fd 76 58 82 ef 45   ;>.C.....H.vX..E
SSL3 alert read:warning:close notify
closed
write to 0x196a050 [0x1a14e53] (37 bytes => 37 (0x25))
0000 - 15 03 01 00 20 d8 6f 46-24 e9 fa 0c c9 9f aa 2d   .... .oF$......-
0010 - db 69 2a d8 fb 61 66 b0-23 23 f9 a4 ac 49 b7 e6   .i*..af.##...I..
0020 - 31 73 56 05 ed                                    1sV..
SSL3 alert write:warning:close notify

Perfect!

Open Port 443 On The Firewall

At this point, if you try to connect to the SSL virtual host remotely, you will fail because port 443 is not yet open.

Use your favourite program to open inbound TCP port 443. I like to directly edit the firewall's config.

vim /etc/sysconfig/iptables
# Firewall configuration written by system-config-firewall
# Manual customization of this file is not recommended.
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT
/etc/init.d/iptables restart
iptables: Flushing firewall rules:                         [  OK  ]
iptables: Setting chains to policy ACCEPT: filter          [  OK  ]
iptables: Unloading modules:                               [  OK  ]
iptables: Applying firewall rules:                         [  OK  ]

Browse to the New Virtual Host

You should now be able to access the new SSL virtual host! Simply browse to https://alteeve.ca (replace with your domain).

Test SSL virtual host in Firefox 4.

Note the 'alteeve.ca' to the left of the address bar showing that the site is encrypted and verified!

Common apachectl -t Configuration Problems

httpd: apr_sockaddr_info_get() failed for <domain>

Make sure that the hostname for the server resolves to an IP address. This is done by ensuring that the name returned by hostname has a DNS entry or has an entry in the /etc/hosts file.

[warn] NameVirtualHost *:80 has no VirtualHosts

This will be shown when no virtual host containers have been configured ye.

PostgreSQL

We need to initialize the postgres core databases before we can start it for the first time.

/etc/init.d/postgresql-9.4 initdb
Initializing database:                                     [  OK  ]

From now on, we can start PostgreSQL normally.

/etc/init.d/postgresql-9.4 restart
Stopping postgresql-9.4 service:                           [  OK  ]
Starting postgresql-9.4 service:                           [  OK  ]

Create the admin user called alteeve which will own the databases we will create and use.

su - postgres
createuser -S -d -R alteeve
psql template1

At the shell, run the following:

Note: If your password has a single-quote in it, escape it with (ie: ALTER USER alteeve WITH PASSWORD 'someones secret password';).
ALTER USER alteeve WITH PASSWORD 'secret';
ALTER ROLE
\q

Tell PostgreSQL to require a password for all local and incoming connections. Also enable access to the database from the local network.

vim /var/lib/pgsql/9.4/data/pg_hba.conf
# TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD
host    all         all         10.222.0.0/16         md5

# "local" is for Unix domain socket connections only
local   all         all                               md5
# IPv4 local connections:
host    all         all         127.0.0.1/32          md5
# IPv6 local connections:
host    all         all         ::1/128               md5

Reload PostgreSQL's configuration.

/etc/init.d/postgresql-9.4 reload

Now create a Database that is owned by the alteeve user, then connect to it to make sure we're asked for a password.

su postgres -c "createdb an_wiki -O alteeve"
psql an_wiki -U alteeve
Password for user alteeve: 
psql (9.4.1)
Type "help" for help.

an_wiki=>

Now load a database from a backup file.

psql an_wiki -U alteeve -f /var/www/ssl_alteeve.ca/temp/an_wiki_3.out
Password for user alteeve:
SET
SET
SET
SET
SET
SET
CREATE SCHEMA
ALTER SCHEMA
psql:/root/an_wiki_2.out:25: ERROR:  language "plpgsql" already exists
ALTER LANGUAGE
SET
CREATE TYPE
ALTER TYPE
CREATE FUNCTION
ALTER FUNCTION
CREATE FUNCTION
ALTER FUNCTION
CREATE FUNCTION
ALTER FUNCTION
CREATE FUNCTION
ALTER FUNCTION
SET
SET
CREATE TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
 setval 
--------
     39
(1 row)

CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
 setval 
--------
     28
(1 row)

CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
 setval 
--------
   2507
(1 row)

CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
 setval 
--------
  14274
(1 row)

CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
 setval 
--------
   6586
(1 row)

CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
 setval 
--------
     50
(1 row)

CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
 setval 
--------
   1563
(1 row)

CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
 setval 
--------
      1
(1 row)

CREATE TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
 setval 
--------
   6335
(1 row)

CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
 setval 
--------
   6741
(1 row)

CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
 setval 
--------
   6663
(1 row)

CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
 setval 
--------
      1
(1 row)

CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE SEQUENCE
ALTER TABLE
 setval 
--------
     20
(1 row)

CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
COPY 137
COPY 2
COPY 9
COPY 0
COPY 0
COPY 2372
COPY 28
COPY 0
COPY 742
COPY 872
COPY 92
COPY 21
COPY 0
COPY 0
COPY 6626
COPY 0
COPY 2
COPY 6586
COPY 0
COPY 2
COPY 16
COPY 44
COPY 28
COPY 51
COPY 104959
COPY 254
COPY 1497
COPY 0
COPY 0
COPY 6335
COPY 3901
COPY 0
COPY 0
COPY 0
COPY 0
COPY 0
COPY 385
COPY 124
COPY 6525
COPY 1
COPY 0
COPY 1276
COPY 0
COPY 0
COPY 1
COPY 7
COPY 0
COPY 2
COPY 0
COPY 29
COPY 0
COPY 12
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE TRIGGER
CREATE TRIGGER
CREATE TRIGGER
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
psql:/root/an_wiki_2.out:145782: WARNING:  no privileges could be revoked for "public"
REVOKE
psql:/root/an_wiki_2.out:145783: WARNING:  no privileges could be revoked for "public"
REVOKE
psql:/root/an_wiki_2.out:145784: WARNING:  no privileges were granted for "public"
GRANT
psql:/root/an_wiki_2.out:145785: WARNING:  no privileges were granted for "public"
GRANT

Voila!

Media Wiki Problem

If you moved a MediaWiki DB and it generated an error like this in the log file:

[Wed Jun 15 21:37:20 2011] [error] [client 206.108.5.162] PHP Warning:  pg_query(): Query failed: ERROR:  relation "objectcache" does not exist\nLINE 1: ...ECT /* SqlBagOStuff::get  */  value,exptime  FROM objectcach...\n
                                                             ^ in /var/www/ssl_alteeve.ca/html/includes/db/DatabasePostgres.php on line 584
[Wed Jun 15 21:37:20 2011] [error] [client 206.108.5.162] PHP Warning:  pg_query(): Query failed: ERROR:  relation "l10n_cache" does not exist\nLINE 1: ... LCStore_DB::get 206.108.5.162 */  lc_value  FROM l10n_cache...\n
                                                             ^ in /var/www/ssl_alteeve.ca/html/includes/db/DatabasePostgres.php on line 584

The fix is to run:

ALTER DATABASE an_wiki SET search_path=mediawiki;

Of course, replace an_wiki with the name of your wiki database.

MySQL

Start MySQL for the first time:

/etc/init.d/mysqld start
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 asakusa.alteeve.ca password 'new-password'

Alternatively you can run:
/usr/bin/mysql_secure_installation

which will also give you the option of removing the test
databases and anonymous user created by default.  This is
strongly recommended for production servers.

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 /usr/mysql-test ; perl mysql-test-run.pl

Please report any problems with the /usr/bin/mysqlbug script!

                                                           [  OK  ]
Starting mysqld:                                           [  OK  ]

Secure the server.

mysql_secure_installation
NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MySQL
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!


In order to log into MySQL to secure it, we'll need the current
password for the root user.  If you've just installed MySQL, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.

Enter current password for root (enter for none): 
OK, successfully used password, moving on...

Setting the root password ensures that nobody can log into the MySQL
root user without the proper authorisation.

Set root password? [Y/n] y
New password: 
Re-enter new password: 
Password updated successfully!
Reloading privilege tables..
 ... Success!


By default, a MySQL installation has an anonymous user, allowing anyone
to log into MySQL without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] y
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n]  
 ... Success!

By default, MySQL comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] 
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] 
 ... Success!

Cleaning up...



All done!  If you've completed all of the above steps, your MySQL
installation should now be secure.

Thanks for using MySQL!

BIND

Note: This is not meant to cover creating the actual zone files for DNS. It's goal is to setup BIND on your EL6 server only.

This is the BIND named server that handles DNS resolution. It will be setup in two parts; The global options and then the zones file.

Install bind

yum install bind bind-libs bind-utils

Global Configuration

Edit the main configuration file, making a backup first.

cp /etc/named.conf /etc/named.conf.orig
vim /etc/named.conf

Enable queries on any interface and answer queries for any domain, not just ours. Edit or add the following;

        listen-on port 53       { any; };
        allow-query             { any; };
        allow-query-cache       { any; };

For now, we're going to disable DNSSEC. Make the following changes;

        dnssec-enable           no;
        dnssec-validation       no;

Now tell bind where to look for a domain name's IP when we don't know. Add;

        forwarders {
                // These are Google's open DNS servers
                8.8.8.8;
                8.8.4.4;
        };

This server will have a slave, and we want to notify that slave when a record changes. Add;

        notify                  yes;

Done. I like to clean up the file to put the variables in line with one another. With this in mind, let's look at the changes as a unified diff;

diff -u /etc/named.conf.orig /etc/named.conf
--- /etc/named.conf.orig	2012-02-05 00:54:48.434068501 -0500
+++ /etc/named.conf	2012-02-05 13:45:16.484083319 -0500
@@ -8,18 +8,26 @@
 //
 
 options {
-	listen-on port 53 { 127.0.0.1; };
-	listen-on-v6 port 53 { ::1; };
-	directory 	"/var/named";
-	dump-file 	"/var/named/data/cache_dump.db";
-        statistics-file "/var/named/data/named_stats.txt";
-        memstatistics-file "/var/named/data/named_mem_stats.txt";
-	allow-query     { localhost; };
-	recursion yes;
-
-	dnssec-enable yes;
-	dnssec-validation yes;
-	dnssec-lookaside auto;
+	listen-on port		53 { any; };
+	listen-on-v6 port	53 { ::1; };
+	directory		"/var/named";
+	dump-file 		"/var/named/data/cache_dump.db";
+        statistics-file		"/var/named/data/named_stats.txt";
+        memstatistics-file	"/var/named/data/named_mem_stats.txt";
+	allow-query		{ any; };
+	allow-query-cache 	{ any; };
+	recursion 		yes;
+	notify			yes;
+
+	dnssec-enable		no;
+	dnssec-validation	no;
+	dnssec-lookaside	auto;
+
+	forwarders {
+		// These are Google's open DNS servers
+		8.8.8.8;
+		8.8.4.4;
+	};
 
 	/* Path to ISC DLV key */
 	bindkeys-file "/etc/named.iscdlv.key";

Setting Up rndc

This ensures that we're transferring zone data between the real master and slave servers.

Note: This will take a long time to finish. Please be patient!
rndc-confgen -a

Eventually, this will be returned;

wrote key file "/etc/rndc.key"

Now make sure everything is owned by named:named.

chown named:named /etc/rndc.key 
chown -R named:named /etc/named

Now copy the rndc.key to the other node:

rsync -av /etc/rndc.key root@ns2.alteeve.ca:/etc/
root@ns2.alteeve.ca's password: 
sending incremental file list

sent 49 bytes  received 15 bytes  11.64 bytes/sec
total size is 77  speedup is 1.20

Done.

Adding Zones

This is where we tell BIND which zones we have SOA for. This includes the pointers to the actual files on disk with each domain's information.

Backup then edit the zones file.

cp /etc/named.rfc1912.zones /etc/named.rfc1912.zones.orig
vim /etc/named.rfc1912.zones

On the master server:

In here is where we add the entries for the domains we have SOA for at the end of the file. These will differ for every install, so only two examples will be shown.

// Our zones which this server is SOA for.

zone "digimer.ca" in {
	type master;
	file "/etc/named/db.digimer.ca";
	allow-transfer {
		65.39.153.67;
		10.255.5.4;
		10.222.1.4;
	};
};

On the slave server:

// Our zones which this server is SOA for.

zone "digimer.ca" in {
	type slave;
	file "/etc/named/bak.digimer.ca";
	masters {
		65.39.153.66;
		10.255.5.3;
		10.222.1.3;
	};
};


This tutorial does not aim to cover actual zone files, but here is one for reference:

cat /etc/named/db.digimer.ca
$ORIGIN .
$TTL 600	; Time To Live.
digimer.ca		IN SOA ns1.alteeve.ca. admin.alteeve.ca. (
				2013022106	;	Serial Number (yyyymmdd##)
				300		;	refresh (in seconds)
				180		;	retry (in seconds)
				300		;	expire (in seconds)
				300		;	minimum (in seconds)
				)
			NS	ns1.alteeve.ca.
			NS	ns2.alteeve.ca.
			A	65.39.153.65
			MX	10	mail.digimer.ca.
$ORIGIN digimer.ca.
localhost		A	127.0.0.1
mail			A	64.34.141.3
www			CNAME	digimer.ca.

Start the named daemon on the master node;

/etc/init.d/named start
Starting named:                                            [  OK  ]

In syslog, you should see something like this;

Feb 23 18:21:46 vm03-dns01 named[2126]: starting BIND 9.8.2rc1-RedHat-9.8.2-0.10.rc1.el6_3.6 -u named
Feb 23 18:21:46 vm03-dns01 named[2126]: built with '--build=x86_64-redhat-linux-gnu' '--host=x86_64-redhat-linux-gnu' '--target=x86_64-redhat-linux-gnu' '--program-prefix=' '--prefix=/usr' '--exec-prefix=/usr' '--bindir=/usr/bin' '--sbindir=/usr/sbin' '--sysconfdir=/etc' '--datadir=/usr/share' '--includedir=/usr/include' '--libdir=/usr/lib64' '--libexecdir=/usr/libexec' '--sharedstatedir=/var/lib' '--mandir=/usr/share/man' '--infodir=/usr/share/info' '--with-libtool' '--localstatedir=/var' '--enable-threads' '--enable-ipv6' '--with-pic' '--disable-static' '--disable-openssl-version-check' '--with-dlz-ldap=yes' '--with-dlz-postgres=yes' '--with-dlz-mysql=yes' '--with-dlz-filesystem=yes' '--with-gssapi=yes' '--disable-isc-spnego' '--with-docbook-xsl=/usr/share/sgml/docbook/xsl-stylesheets' '--enable-fixed-rrset' 'build_alias=x86_64-redhat-linux-gnu' 'host_alias=x86_64-redhat-linux-gnu' 'target_alias=x86_64-redhat-linux-gnu' 'CFLAGS= -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic' 'CPPFLAGS= -DDIG_SIGCHASE'
Feb 23 18:21:46 vm03-dns01 named[2126]: ----------------------------------------------------
Feb 23 18:21:46 vm03-dns01 named[2126]: BIND 9 is maintained by Internet Systems Consortium,
Feb 23 18:21:46 vm03-dns01 named[2126]: Inc. (ISC), a non-profit 501(c)(3) public-benefit 
Feb 23 18:21:46 vm03-dns01 named[2126]: corporation.  Support and training for BIND 9 are 
Feb 23 18:21:46 vm03-dns01 named[2126]: available at https://www.isc.org/support
Feb 23 18:21:46 vm03-dns01 named[2126]: ----------------------------------------------------
Feb 23 18:21:46 vm03-dns01 named[2126]: adjusted limit on open files from 4096 to 1048576
Feb 23 18:21:46 vm03-dns01 named[2126]: found 2 CPUs, using 2 worker threads
Feb 23 18:21:46 vm03-dns01 named[2126]: using up to 4096 sockets
Feb 23 18:21:46 vm03-dns01 named[2126]: loading configuration from '/etc/named.conf'
Feb 23 18:21:46 vm03-dns01 named[2126]: reading built-in trusted keys from file '/etc/named.iscdlv.key'
Feb 23 18:21:46 vm03-dns01 named[2126]: using default UDP/IPv4 port range: [1024, 65535]
Feb 23 18:21:46 vm03-dns01 named[2126]: using default UDP/IPv6 port range: [1024, 65535]
Feb 23 18:21:46 vm03-dns01 named[2126]: listening on IPv4 interface lo, 127.0.0.1#53
Feb 23 18:21:46 vm03-dns01 named[2126]: listening on IPv4 interface eth0, 65.39.153.66#53
Feb 23 18:21:46 vm03-dns01 named[2126]: listening on IPv4 interface eth0:0, 10.255.5.3#53
Feb 23 18:21:46 vm03-dns01 named[2126]: listening on IPv4 interface eth0:1, 10.222.1.3#53
Feb 23 18:21:46 vm03-dns01 named[2126]: listening on IPv6 interface lo, ::1#53
Feb 23 18:21:46 vm03-dns01 named[2126]: generating session key for dynamic DNS
Feb 23 18:21:46 vm03-dns01 named[2126]: sizing zone task pool based on 7 zones
Feb 23 18:21:46 vm03-dns01 named[2126]: using built-in DLV key for view _default
Feb 23 18:21:46 vm03-dns01 named[2126]: set up managed keys zone for view _default, file '/var/named/dynamic/managed-keys.bind'
Feb 23 18:21:46 vm03-dns01 named[2126]: Warning: 'empty-zones-enable/disable-empty-zone' not set: disabling RFC 1918 empty zones
Feb 23 18:21:46 vm03-dns01 named[2126]: automatic empty zone: 127.IN-ADDR.ARPA
Feb 23 18:21:46 vm03-dns01 named[2126]: automatic empty zone: 254.169.IN-ADDR.ARPA
Feb 23 18:21:46 vm03-dns01 named[2126]: automatic empty zone: 2.0.192.IN-ADDR.ARPA
Feb 23 18:21:46 vm03-dns01 named[2126]: automatic empty zone: 100.51.198.IN-ADDR.ARPA
Feb 23 18:21:46 vm03-dns01 named[2126]: automatic empty zone: 113.0.203.IN-ADDR.ARPA
Feb 23 18:21:46 vm03-dns01 named[2126]: automatic empty zone: 255.255.255.255.IN-ADDR.ARPA
Feb 23 18:21:46 vm03-dns01 named[2126]: automatic empty zone: 0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA
Feb 23 18:21:46 vm03-dns01 named[2126]: automatic empty zone: D.F.IP6.ARPA
Feb 23 18:21:46 vm03-dns01 named[2126]: automatic empty zone: 8.E.F.IP6.ARPA
Feb 23 18:21:46 vm03-dns01 named[2126]: automatic empty zone: 9.E.F.IP6.ARPA
Feb 23 18:21:46 vm03-dns01 named[2126]: automatic empty zone: A.E.F.IP6.ARPA
Feb 23 18:21:46 vm03-dns01 named[2126]: automatic empty zone: B.E.F.IP6.ARPA
Feb 23 18:21:46 vm03-dns01 named[2126]: automatic empty zone: 8.B.D.0.1.0.0.2.IP6.ARPA
Feb 23 18:21:46 vm03-dns01 named[2126]: command channel listening on 127.0.0.1#953
Feb 23 18:21:46 vm03-dns01 named[2126]: command channel listening on ::1#953
Feb 23 18:21:46 vm03-dns01 named[2126]: zone 0.in-addr.arpa/IN: loaded serial 0
Feb 23 18:21:46 vm03-dns01 named[2126]: zone 1.0.0.127.in-addr.arpa/IN: loaded serial 0
Feb 23 18:21:46 vm03-dns01 named[2126]: zone 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa/IN: loaded serial 0
Feb 23 18:21:46 vm03-dns01 named[2126]: zone digimer.ca/IN: loaded serial 2013022106
Feb 23 18:21:46 vm03-dns01 named[2126]: zone localhost.localdomain/IN: loaded serial 0
Feb 23 18:21:46 vm03-dns01 named[2126]: zone localhost/IN: loaded serial 0
Feb 23 18:21:46 vm03-dns01 named[2126]: managed-keys-zone ./IN: loaded serial 3
Feb 23 18:21:46 vm03-dns01 named[2126]: zone digimer.ca/IN: sending notifies (serial 2013022106)
Feb 23 18:21:46 vm03-dns01 named[2126]: running

You can test that it's working by querying one of your zones.

dig digimer.ca @localhost
; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.10.rc1.el6_3.6 <<>> digimer.ca @localhost
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 18362
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 1

;; QUESTION SECTION:
;digimer.ca.			IN	A

;; ANSWER SECTION:
digimer.ca.		600	IN	A	65.39.153.65

;; AUTHORITY SECTION:
digimer.ca.		600	IN	NS	ns1.alteeve.ca.
digimer.ca.		600	IN	NS	ns2.alteeve.ca.

;; ADDITIONAL SECTION:
ns2.alteeve.ca.		268	IN	A	78.46.37.135

;; Query time: 0 msec
;; SERVER: ::1#53(::1)
;; WHEN: Sat Feb 23 18:27:04 2013
;; MSG SIZE  rcvd: 104

Now start named on the slave. First though, check /etc/named/ to see that there are no files there yet.

ls -lah /etc/named/
total 8.0K
drwxr-x---   2 named named 4.0K Dec  6 15:49 .
drwxr-xr-x. 66 root  root  4.0K Feb 23 18:13 ..

Now start named;

/etc/init.d/named start
Starting named:                                            [  OK  ]

In syslog on the slave, you will see something like;

Feb 23 18:29:28 vm04-dns02 named[2072]: starting BIND 9.8.2rc1-RedHat-9.8.2-0.10.rc1.el6_3.6 -u named
Feb 23 18:29:28 vm04-dns02 named[2072]: built with '--build=x86_64-redhat-linux-gnu' '--host=x86_64-redhat-linux-gnu' '--target=x86_64-redhat-linux-gnu' '--program-prefix=' '--prefix=/usr' '--exec-prefix=/usr' '--bindir=/usr/bin' '--sbindir=/usr/sbin' '--sysconfdir=/etc' '--datadir=/usr/share' '--includedir=/usr/include' '--libdir=/usr/lib64' '--libexecdir=/usr/libexec' '--sharedstatedir=/var/lib' '--mandir=/usr/share/man' '--infodir=/usr/share/info' '--with-libtool' '--localstatedir=/var' '--enable-threads' '--enable-ipv6' '--with-pic' '--disable-static' '--disable-openssl-version-check' '--with-dlz-ldap=yes' '--with-dlz-postgres=yes' '--with-dlz-mysql=yes' '--with-dlz-filesystem=yes' '--with-gssapi=yes' '--disable-isc-spnego' '--with-docbook-xsl=/usr/share/sgml/docbook/xsl-stylesheets' '--enable-fixed-rrset' 'build_alias=x86_64-redhat-linux-gnu' 'host_alias=x86_64-redhat-linux-gnu' 'target_alias=x86_64-redhat-linux-gnu' 'CFLAGS= -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic' 'CPPFLAGS= -DDIG_SIGCHASE'
Feb 23 18:29:28 vm04-dns02 named[2072]: ----------------------------------------------------
Feb 23 18:29:28 vm04-dns02 named[2072]: BIND 9 is maintained by Internet Systems Consortium,
Feb 23 18:29:28 vm04-dns02 named[2072]: Inc. (ISC), a non-profit 501(c)(3) public-benefit 
Feb 23 18:29:28 vm04-dns02 named[2072]: corporation.  Support and training for BIND 9 are 
Feb 23 18:29:28 vm04-dns02 named[2072]: available at https://www.isc.org/support
Feb 23 18:29:28 vm04-dns02 named[2072]: ----------------------------------------------------
Feb 23 18:29:28 vm04-dns02 named[2072]: adjusted limit on open files from 4096 to 1048576
Feb 23 18:29:28 vm04-dns02 named[2072]: found 2 CPUs, using 2 worker threads
Feb 23 18:29:28 vm04-dns02 named[2072]: using up to 4096 sockets
Feb 23 18:29:28 vm04-dns02 named[2072]: loading configuration from '/etc/named.conf'
Feb 23 18:29:28 vm04-dns02 named[2072]: reading built-in trusted keys from file '/etc/named.iscdlv.key'
Feb 23 18:29:28 vm04-dns02 named[2072]: using default UDP/IPv4 port range: [1024, 65535]
Feb 23 18:29:28 vm04-dns02 named[2072]: using default UDP/IPv6 port range: [1024, 65535]
Feb 23 18:29:28 vm04-dns02 named[2072]: listening on IPv4 interface lo, 127.0.0.1#53
Feb 23 18:29:28 vm04-dns02 named[2072]: listening on IPv4 interface eth0, 65.39.153.67#53
Feb 23 18:29:28 vm04-dns02 named[2072]: listening on IPv4 interface eth0:0, 10.255.5.4#53
Feb 23 18:29:28 vm04-dns02 named[2072]: listening on IPv4 interface eth0:1, 10.222.1.4#53
Feb 23 18:29:28 vm04-dns02 named[2072]: listening on IPv6 interface lo, ::1#53
Feb 23 18:29:28 vm04-dns02 named[2072]: generating session key for dynamic DNS
Feb 23 18:29:28 vm04-dns02 named[2072]: sizing zone task pool based on 7 zones
Feb 23 18:29:28 vm04-dns02 named[2072]: using built-in DLV key for view _default
Feb 23 18:29:28 vm04-dns02 named[2072]: set up managed keys zone for view _default, file '/var/named/dynamic/managed-keys.bind'
Feb 23 18:29:28 vm04-dns02 named[2072]: Warning: 'empty-zones-enable/disable-empty-zone' not set: disabling RFC 1918 empty zones
Feb 23 18:29:28 vm04-dns02 named[2072]: automatic empty zone: 127.IN-ADDR.ARPA
Feb 23 18:29:28 vm04-dns02 named[2072]: automatic empty zone: 254.169.IN-ADDR.ARPA
Feb 23 18:29:28 vm04-dns02 named[2072]: automatic empty zone: 2.0.192.IN-ADDR.ARPA
Feb 23 18:29:28 vm04-dns02 named[2072]: automatic empty zone: 100.51.198.IN-ADDR.ARPA
Feb 23 18:29:28 vm04-dns02 named[2072]: automatic empty zone: 113.0.203.IN-ADDR.ARPA
Feb 23 18:29:28 vm04-dns02 named[2072]: automatic empty zone: 255.255.255.255.IN-ADDR.ARPA
Feb 23 18:29:28 vm04-dns02 named[2072]: automatic empty zone: 0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA
Feb 23 18:29:28 vm04-dns02 named[2072]: automatic empty zone: D.F.IP6.ARPA
Feb 23 18:29:28 vm04-dns02 named[2072]: automatic empty zone: 8.E.F.IP6.ARPA
Feb 23 18:29:28 vm04-dns02 named[2072]: automatic empty zone: 9.E.F.IP6.ARPA
Feb 23 18:29:28 vm04-dns02 named[2072]: automatic empty zone: A.E.F.IP6.ARPA
Feb 23 18:29:28 vm04-dns02 named[2072]: automatic empty zone: B.E.F.IP6.ARPA
Feb 23 18:29:28 vm04-dns02 named[2072]: automatic empty zone: 8.B.D.0.1.0.0.2.IP6.ARPA
Feb 23 18:29:28 vm04-dns02 named[2072]: command channel listening on 127.0.0.1#953
Feb 23 18:29:28 vm04-dns02 named[2072]: command channel listening on ::1#953
Feb 23 18:29:28 vm04-dns02 named[2072]: zone 0.in-addr.arpa/IN: loaded serial 0
Feb 23 18:29:28 vm04-dns02 named[2072]: zone 1.0.0.127.in-addr.arpa/IN: loaded serial 0
Feb 23 18:29:28 vm04-dns02 named[2072]: zone 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa/IN: loaded serial 0
Feb 23 18:29:28 vm04-dns02 named[2072]: zone localhost.localdomain/IN: loaded serial 0
Feb 23 18:29:28 vm04-dns02 named[2072]: zone localhost/IN: loaded serial 0
Feb 23 18:29:28 vm04-dns02 named[2072]: managed-keys-zone ./IN: loaded serial 0
Feb 23 18:29:28 vm04-dns02 named[2072]: running
Feb 23 18:29:28 vm04-dns02 named[2072]: zone digimer.ca/IN: Transfer started.
Feb 23 18:29:28 vm04-dns02 named[2072]: transfer of 'digimer.ca/IN' from 65.39.153.66#53: connected using 65.39.153.67#47099
Feb 23 18:29:28 vm04-dns02 named[2072]: zone digimer.ca/IN: transferred serial 2013022106
Feb 23 18:29:28 vm04-dns02 named[2072]: transfer of 'digimer.ca/IN' from 65.39.153.66#53: Transfer completed: 1 messages, 9 records, 247 bytes, 0.001 secs (247000 bytes/sec)

If you look in syslog on the master, you will see that the digimer.ca domain was transferred;

Feb 23 18:29:28 vm03-dns01 named[2126]: client 65.39.153.67#47099: transfer of 'digimer.ca/IN': AXFR started
Feb 23 18:29:28 vm03-dns01 named[2126]: client 65.39.153.67#47099: transfer of 'digimer.ca/IN': AXFR ended

Indeed, you will now see that the /etc/named/bak.digimer.ca file was created.

ls -lah /etc/named/
total 12K
drwxr-x---   2 named named 4.0K Feb 23 18:29 .
drwxr-xr-x. 66 root  root  4.0K Feb 23 18:13 ..
-rw-r--r--   1 named named  438 Feb 23 18:29 bak.digimer.ca

We can confirm that it's working by querying the slave;

dig digimer.ca @localhost
; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.10.rc1.el6_3.6 <<>> digimer.ca @localhost
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 15602
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 0

;; QUESTION SECTION:
;digimer.ca.			IN	A

;; ANSWER SECTION:
digimer.ca.		600	IN	A	65.39.153.65

;; AUTHORITY SECTION:
digimer.ca.		600	IN	NS	ns1.alteeve.ca.
digimer.ca.		600	IN	NS	ns2.alteeve.ca.

;; Query time: 0 msec
;; SERVER: ::1#53(::1)
;; WHEN: Sat Feb 23 18:32:52 2013
;; MSG SIZE  rcvd: 88

Excellent! Now you can add more DNS servers to the master server.

Adding a Firewall Entry

Assuming you have a firewall running, be sure to add an entry for TCP port 53.

(Re)Start BIND

Once all the configuration files and domain zone files are in place, (re)start the named service.

/etc/init.d/named restart
Stopping named: .                                          [  OK  ]
Starting named:                                            [  OK  ]

Testing Name resolution

To properly test name resolution, you will want to resolve a domain we are SOA for and another domain which we are not. We will repeat this twice, once on the server and once from a remote machine to ensure that it is answering remote queries. Note that in the examples below, my DNS server's IP address is 78.46.37.135.

On the server;

Query alteeve.ca, which we're SOA for.

dig alteeve.ca @localhost
; <<>> DiG 9.7.3-P3-RedHat-9.7.3-8.P3.el6_2.2 <<>> alteeve.ca @localhost
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 1418
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 2

;; QUESTION SECTION:
;alteeve.ca.			IN	A

;; ANSWER SECTION:
alteeve.ca.		600	IN	A	192.139.81.121

;; AUTHORITY SECTION:
alteeve.ca.		600	IN	NS	ns1.alteeve.ca.
alteeve.ca.		600	IN	NS	ns2.alteeve.ca.

;; ADDITIONAL SECTION:
ns1.alteeve.ca.	600	IN	A	192.139.81.117
ns2.alteeve.ca.	600	IN	A	192.139.81.119

;; Query time: 0 msec
;; SERVER: ::1#53(::1)
;; WHEN: Sun Feb  5 13:57:11 2012
;; MSG SIZE  rcvd: 113

Now query google.ca which we obviously are not SOA for.

dig google.ca @localhost
; <<>> DiG 9.7.3-P3-RedHat-9.7.3-8.P3.el6_2.2 <<>> google.ca @localhost
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56760
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 13, ADDITIONAL: 0

;; QUESTION SECTION:
;google.ca.			IN	A

;; ANSWER SECTION:
google.ca.		300	IN	A	74.125.232.56

;; AUTHORITY SECTION:
.			2967	IN	NS	f.root-servers.net.
.			2967	IN	NS	c.root-servers.net.
.			2967	IN	NS	b.root-servers.net.
.			2967	IN	NS	a.root-servers.net.
.			2967	IN	NS	k.root-servers.net.
.			2967	IN	NS	i.root-servers.net.
.			2967	IN	NS	e.root-servers.net.
.			2967	IN	NS	h.root-servers.net.
.			2967	IN	NS	l.root-servers.net.
.			2967	IN	NS	d.root-servers.net.
.			2967	IN	NS	j.root-servers.net.
.			2967	IN	NS	g.root-servers.net.
.			2967	IN	NS	m.root-servers.net.

;; Query time: 12 msec
;; SERVER: ::1#53(::1)
;; WHEN: Sun Feb  5 14:02:03 2012
;; MSG SIZE  rcvd: 254

Now from a remote machine, repeat the same queries to ensure that our DNS server will respond to external queries.

On the server;

Query alteeve.ca, which we're SOA for.

dig alteeve.ca @78.46.37.135
; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.2.rc1.fc16 <<>> alteeve.ca @78.46.37.135
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 46628
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 2

;; QUESTION SECTION:
;alteeve.ca.			IN	A

;; ANSWER SECTION:
alteeve.ca.		600	IN	A	192.139.81.121

;; AUTHORITY SECTION:
alteeve.ca.		600	IN	NS	ns2.alteeve.ca.
alteeve.ca.		600	IN	NS	ns1.alteeve.ca.

;; ADDITIONAL SECTION:
ns1.alteeve.ca.	600	IN	A	192.139.81.117
ns2.alteeve.ca.	600	IN	A	192.139.81.119

;; Query time: 138 msec
;; SERVER: 78.46.37.135#53(78.46.37.135)
;; WHEN: Sun Feb  5 14:04:09 2012
;; MSG SIZE  rcvd: 113

Now query google.ca which we obviously are not SOA for.

dig google.ca @78.46.37.135
; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.2.rc1.fc16 <<>> google.ca @78.46.37.135
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 18204
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 13, ADDITIONAL: 0

;; QUESTION SECTION:
;google.ca.			IN	A

;; ANSWER SECTION:
google.ca.		138	IN	A	74.125.232.56

;; AUTHORITY SECTION:
.			2805	IN	NS	h.root-servers.net.
.			2805	IN	NS	c.root-servers.net.
.			2805	IN	NS	j.root-servers.net.
.			2805	IN	NS	i.root-servers.net.
.			2805	IN	NS	b.root-servers.net.
.			2805	IN	NS	m.root-servers.net.
.			2805	IN	NS	g.root-servers.net.
.			2805	IN	NS	d.root-servers.net.
.			2805	IN	NS	a.root-servers.net.
.			2805	IN	NS	l.root-servers.net.
.			2805	IN	NS	f.root-servers.net.
.			2805	IN	NS	k.root-servers.net.
.			2805	IN	NS	e.root-servers.net.

;; Query time: 140 msec
;; SERVER: 78.46.37.135#53(78.46.37.135)
;; WHEN: Sun Feb  5 14:04:31 2012
;; MSG SIZE  rcvd: 254

Done!

Email

This is a pretty heavily customized postfix install using a custom schema. It was originally based on this Debian Etch tutorial, but adapted for PostgreSQL. Much time has passed and the operating system is now significantly changed, but it's lineage is thus. A more recent, but still Debian-focused version of the tutorial is here. I also used this tutorial to help sort out the PostgreSQL stuff.

This will use a few applications;

  • Postfix - The program that receives email.
  • PostgreSQL - The database used to validate the existence of email accounts and validates incoming user credentials.
  • Dovecot - Takes email coming from postfix, via amavis, and records them to disk. It also answers requests from users wanting to check their email.
  • Amavis - Filters incoming email for spam (via spamassassin) and virsus (via clamav)

We will also be using graylisting, which is a spam fighting tactic where the first email from a given user to one of our users is bounced for a few minutes. Proper mail servers will acknowledge the bound, wait the time and resend. Spam mailers though are usually fire-and-forget and will not resend, thus effectively blocking the spam message. This is a very effective method of blocking spam with minimal chance of losing real mail from real users. Any subsequent message from the user would be allowed through with no delay, provided the user had in fact resent the first message as requested.

Install

To install the applications;

yum install postfix postfix-perl-scripts dovecot dovecot-pgsql spamassassin postgresql-server postgresql-plperl mutt

Configuring Postfix

Installation requires several steps. The AN!Console database must be loaded. Various applications need to be installed. Postfix, Dovecot and helper applications need to be configured and so on.

This tutorial uses the following values that you may need to adjust;

  • Database name; an_tools
  • Database user; alteeve
  • Database password; secret
  • Database host; 127.0.0.1
Note: Do not use the database host "localhost" unless you are certain you can connect to the DB using a standard unix socket.

Building Support for PostgreSQL

Warning: We need to build our own RPM in order to support postgresql. This means we will have to disable postfix from future updates, placing the onus on us to make sure critical updates are applied. This will require downloading the latest source RPMs, re-enabling postgres and recompile/reinstall.

Add the source RPM repository by adding the following;

vim /etc/yum.repos.d/CentOS-Base.repo
# Source RPM repository
[base-source]
name=CentOS-$releasever - Base - Source
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os
baseurl=http://vault.centos.org/6.3/os/Source/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

Now download the source RPM for postfix.

yumdownloader --source postfix
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: centos.vieth-server.de
 * extras: centos.vieth-server.de
 * updates: centos.vieth-server.de
base                               | 3.7 kB     00:00
base-source                        | 1.9 kB     00:00
extras                             | 3.5 kB     00:00
updates                            | 3.5 kB     00:00
No source RPM found for 2:postfix-2.6.6-2.2.el6_1.x86_64
./postfix-2.6.6-2.el6.src.rpm already exists and appears to be complete
nikko:/etc/postfix# rm postfix-2.6.6-2.el6.src.rpm 
rm: remove regular file `postfix-2.6.6-2.el6.src.rpm'? y
nikko:/etc/postfix# yumdownloader --source postfix
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: centos.vieth-server.de
 * extras: centos.vieth-server.de
 * updates: centos.vieth-server.de
No source RPM found for 2:postfix-2.6.6-2.2.el6_1.x86_64
postfix-2.6.6-2.el6.src.rpm        | 3.3 MB     00:00

Now that we have the postfix source RPM, we will install it.

rpm -Uvh postfix-2.6.6-2.el6.src.rpm
   1:postfix                warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root
warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root
warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root
warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root
warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root
warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root
warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root
warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root
########################################### [100%]
warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root
warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root
warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root
warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root

Now edit the .spec file to enable postgres support.

cp ~/rpmbuild/SPECS/postfix.spec ~/rpmbuild/SPECS/postfix.spec.orig
vim ~/rpmbuild/SPECS/postfix.spec

Make the following changes.

  • Enable PostgreSQL support
%{?!PGSQL: %define PGSQL 1}

Increment the release version by one.

Release: 3%{?dist}

We can see the changes here:

diff -u ~/rpmbuild/SPECS/postfix.spec.orig ~/rpmbuild/SPECS/postfix.spec
--- /root/rpmbuild/SPECS/postfix.spec.orig      2012-02-11 16:54:54.495330859 -0500
+++ /root/rpmbuild/SPECS/postfix.spec   2012-02-11 16:53:39.873331101 -0500
@@ -1,5 +1,5 @@
 %{?!MYSQL: %define MYSQL 1}
-%{?!PGSQL: %define PGSQL 0}
+%{?!PGSQL: %define PGSQL 1}
 %define LDAP 2
 %define PCRE 1
 %define SASL 2
@@ -35,7 +35,7 @@
 Name: postfix
 Summary: Postfix Mail Transport Agent
 Version: 2.6.6
-Release: 2%{?dist}
+Release: 3%{?dist}
 Epoch: 2
 Group: System Environment/Daemons
 URL: http://www.postfix.org

Now rebuild the RPM, which means we need to install the build tools.

yum groupinstall development
yum install db4-devel openldap-devel cyrus-sasl-devel pcre-devel mysql-devel postgresql-devel openssl-devel
rpmbuild -bb ~/rpmbuild/SPECS/postfix.spec
(compile output)
Processing files: postfix-debuginfo-2.6.6-3.el6.x86_64
Checking for unpackaged file(s): /usr/lib/rpm/check-files /root/rpmbuild/BUILDROOT/postfix-2.6.6-3.el6.x86_64
Wrote: /root/rpmbuild/RPMS/x86_64/postfix-2.6.6-3.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/postfix-perl-scripts-2.6.6-3.el6.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/postfix-debuginfo-2.6.6-3.el6.x86_64.rpm
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.rymr5C
+ umask 022
+ cd /root/rpmbuild/BUILD
+ cd postfix-2.6.6
+ rm -rf /root/rpmbuild/BUILDROOT/postfix-2.6.6-3.el6.x86_64
+ exit 0

Install the updated postfix.

rpm -Uvh ~/rpmbuild/RPMS/x86_64/postfix-2.6.6-3.el6.x86_64.rpm ~/rpmbuild/RPMS/x86_64/postfix-perl-scripts-2.6.6-3.el6.x86_64.rpm
Preparing...                ########################################### [100%]
   1:postfix                ########################################### [ 50%]
   2:postfix-perl-scripts   ########################################### [100%]

Now exclude postfix from future updates.

cp /etc/yum.conf /etc/yum.conf.orig
vim /etc/yum.conf
diff -u /etc/yum.conf.orig /etc/yum.conf
--- /etc/yum.conf.orig  2012-02-11 16:59:53.720079168 -0500
+++ /etc/yum.conf       2012-02-11 17:00:47.013331283 -0500
@@ -10,6 +10,7 @@
 installonly_limit=5
 bugtracker_url=http://bugs.centos.org/set_project.php?project_id=16&ref=http://bugs.centos.org/bug_report_page.php?category=yum
 distroverpkg=centos-release
+exclude=postfix*
 
 #  This is the default, if you make this bigger yum won't see if the metadata
 # is newer on the remote and so you'll "gain" the bandwidth of not having to

Basic Postfix Configuration

Since we'll be using virtual domains, users, aliases and mailboxes, we'll need to start by commenting out some of the default options in Postfix. By default, Postfix is set up for small numbers of local users, and it only allows connections from the localhost. Our configuration will be more scalable, allowing many domains and users to be stored in the Postgres database.

Comment out the following:

vim /etc/postfix/main.cf
# inet_interfaces = localhost
# mydestination = $myhostname, localhost.$mydomain, localhost 
# alias_maps = hash:/etc/aliases  
# alias_database = hash:/etc/aliases

And uncomment/add these:

vim /etc/postfix/main.cf
inet_interfaces = all   # allows us to connect and test from another machine
mynetworks = 192.168.1.0/32, 127.0.0.0/8  # use the IP or subnet of your test machine here
message_size_limit = 36700160 # increase max message size to 35MB to allow for ~25MB attachments

Setup Virtual Domain Lookup

This tells postfix how to find which domains we have.

vim /etc/postfix/pgsql-virtual-mailbox-domains.cf
user = alteeve
password = secret
hosts = 127.0.0.1
dbname = an_tools
query = SELECT 1 FROM domains WHERE dom_name='%s'

Now tell Postfix to use this new file by appending the following to the main postfix configuration file.

vim /etc/postfix/main.cf
# Tell postfix to validate domains using our postgresql databae via the
# pgsql-virtual-mailbox-domains.cf
virtual_mailbox_domains=pgsql:/etc/postfix/pgsql-virtual-mailbox-domains.cf

Now reload postfix;

/etc/init.d/postfix reload
Reloading postfix:                                         [  OK  ]

Now we can test that domains resolve. In my case, I will test the look-up for alteeve.ca.

postmap -q alteeve.ca pgsql:/etc/postfix/pgsql-virtual-mailbox-domains.cf
1

Now make sure it returns nothing when query a bad domain.

postmap -q example.com pgsql:/etc/postfix/pgsql-virtual-mailbox-domains.cf
<nothing returned>

Setup Mailbox Mapping

This section will tell postfix which users for a given domain are valid.

vim /etc/postfix/pgsql-virtual-mailbox-maps.cf
user = alteeve
password = secret
hosts = 127.0.0.1
dbname = an_tools
query = SELECT 1 FROM email_file WHERE email='%s'

Tell postfix to use this new file when looking up users.

vim /etc/postfix/main.cf

And add:

# Tell postfix which table to look in when validating a local user via their
# email address.
virtual_mailbox_maps=pgsql:/etc/postfix/pgsql-virtual-mailbox-maps.cf

Reload postfix.

/etc/init.d/postfix reload
Reloading postfix:                                         [  OK  ]

Now do a test of a valid user, which should return 1, and an invalid user, which should return nothing.

postmap -q digimer@alteeve.ca pgsql:/etc/postfix/pgsql-virtual-mailbox-maps.cf
1
postmap -q nobody@alteeve.ca pgsql:/etc/postfix/pgsql-virtual-mailbox-maps.cf
<nothing returned>

Setup Email Forwards

This will allow for email addresses to be forwarded to other email addresses.

vim /etc/postfix/pgsql-virtual-alias-maps.cf
user = alteeve
password = secret
hosts = 127.0.0.1
dbname = an_tools
query = SELECT fwd_destination FROM forwards WHERE fwd_source='%s'

Now tell postfix where to look.

vim /etc/postfix/main.cf

Add;

# This tells postfix where to forward incoming email to, where appropriate.
virtual_alias_maps=pgsql:/etc/postfix/pgsql-virtual-alias-maps.cf

Reload;

/etc/init.d/postfix reload
Reloading postfix:                                         [  OK  ]

I've setup a forward where digimer@alteeve.ca forwards to digimer@alteeve.ca, so we will use that for the next test.

postmap -q digimer@alteeve.ca pgsql:/etc/postfix/pgsql-virtual-alias-maps.cf
digimer@alteeve.ca

An email address with no forward should return nothing.

postmap -q digimer@alteeve.ca pgsql:/etc/postfix/pgsql-virtual-alias-maps.cf
<nothing returned>

Excellent.

Setup Postfix Mail Delivery via Dovecot

Define a mail transport method in the main Postfix config.

vim /etc/postfix/main.cf
# this option is ignored, but may be useful for reference
virtual_mailbox_base=/email

# deliver mail via dovecot
virtual_transport = dovecot

# prevent postfix from sending multiple recipients per delivery request,
# since dovecot only supports one recipient for each delivery
dovecot_destination_recipient_limit = 1

Tell Postfix what virtual_transport "dovecot" means, and how to use it.

vim /etc/postfix/master.cf

Append this for RHEL/CentOS 6 machines. For other distros, make sure that /usr/libexec/dovecot/deliver exists and change the path if necessary.

dovecot   unix  -       n       n       -       -       pipe
  flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${recipient}

Setup Postfix SMTP Authentication using Dovecot

Dovecot provides an SMTP authentication mechanism to Postfix called SASL. Enabling this will require users to authenticate against the server before sending mail.

vim /etc/postfix/main.cf

Append the following to enable smtp authentication:

smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
broken_sasl_auth_clients = yes

# allow authenticated users to send mail through Postfix SMTP
# more info at /usr/share/doc/postfix-2.6.6/README_FILES/SMTPD_ACCESS_README
smtpd_recipient_restrictions =
        permit_mynetworks
        permit_sasl_authenticated
        reject_unauth_destination

# general smtpd settings
# - reject clients that speak too early
# - reject mail from a null address to many recipients (usually spam)
smtpd_data_restrictions =
        reject_unauth_pipelining
        reject_multi_recipient_bounce
        permit

Configuring Dovecot

Dovecot handles writing incoming mail to the disk and moving/deleting mail as the user wishes. We're going to create a user and group called vmail which will be used to manage the email stored on disk.

useradd -m vmail
mkdir /email
chown -R vmail:vmail /email

Dovecot is configured in /etc/dovecot and the main configuration file is dovecot.conf.

cp /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.orig
vim /etc/dovecot/dovecot.conf

Dovecot uses .d style configuration files.

  • Authentication
cp /etc/dovecot/conf.d/10-auth.conf /etc/dovecot/conf.d/10-auth.conf.orig
vim /etc/dovecot/conf.d/10-auth.conf

Tell dovecot to accept plain-text passwords (needed for some old email clients, you may not need to enable this).

disable_plaintext_auth = no

Tell it not to use the database, and not local users for mail delivery.

#!include auth-system.conf.ext
!include auth-sql.conf.ext
  • Mail store

Tell dovecot where to store the email. The %d tells dovecot to substitute the user's domain name and %n is substituted by the user's email name. For example, digimer@alteeve.ca becomes /email/alteeve.ca/mkelly.

cp /etc/dovecot/conf.d/10-mail.conf /etc/dovecot/conf.d/10-mail.conf.orig
vim /etc/dovecot/conf.d/10-mail.conf
mail_location = mbox:/email/%d/%n

Dovecot Authentication and SQL Settings

We need to tell dovecot where to look for passwords when authenticating a user. Where to look is controlled in the auth-sql.conf.ext file and is broken down into user and password lookups. We will want to first tell Dovecot which user to use when accessing the mail store on disk.

cp /etc/dovecot/conf.d/auth-sql.conf.ext /etc/dovecot/conf.d/auth-sql.conf.ext.orig
vim /etc/dovecot/conf.d/auth-sql.conf.ext
userdb {
  driver = static
  args = uid=vmail gid=vmail home=/email/%d/%n allow_all_users=yes
}
  • Now configure the SQL server access details.
Note: Make sure that PostgreSQL has sufficient max_connections set in /var/lib/pgsql/data/postgresql.conf to handle enough connections for the expected number of email connections, plus other connections from other applications.
cp /usr/share/doc/dovecot-2.0.9/example-config/dovecot-sql.conf.ext /etc/dovecot/dovecot-sql.conf.ext
chown root:root /etc/dovecot/dovecot-sql.conf.ext
chmod 600 /etc/dovecot/dovecot-sql.conf.ext
vim /etc/dovecot/dovecot-sql.conf.ext

Tell dovecot to use PostgreSQL.

driver = pgsql

Configure the connection string.

Note: If your database uses a password with a space character in it, quote the password. Ie: password='super secret'.
connect = host=127.0.0.1 dbname=an_tools user=alteeve password=secret

Tell dovecot to accept plain-text passwords (this is needed for some stupid MS clients, this will probably change soon).

default_pass_scheme = PLAIN

Tell dovecot how to pull use the user's password.

password_query = SELECT email, password FROM email_password WHERE email='%u'

The last thing to setup is the user query. The query needs to return the UID and GID of the vmail user we setup earlier. To get it, you can use the id command.

id vmail
uid=503(vmail) gid=503(vmail) groups=503(vmail)

The numbers we want are 503 and 503 for the UID and GID, respectively. Knowing this, we can set the userdb SQL string.

user_query = SELECT '/email/'||file AS email_dir, '503' AS uid, '503' AS gid FROM email_file WHERE email='%u'

Configure Listener Sockets

Setup the authentication socket to allow the vmail user. This will allow Dovecot to access the user authentication socket.

vim /etc/dovecot/conf.d/10-master.conf
  unix_listener auth-userdb {
    mode = 0600
    user = vmail
    group = vmail
  }

Configure Dovecot to authenticate Postfix SMTP requests.

vim /etc/dovecot/conf.d/10-master.conf
   unix_listener smtp-auth {
    mode = 0600
    user = postfix
    group = postfix
    path = /var/spool/postfix/private/auth
  }

Tell Dovecot to increase the number of allowed connections and child processes to handle heavier loads.

vim /etc/dovecot/conf.d/10-master.conf
default_process_limit = 200
default_client_limit = 2000

Enable Logging

This is very useful for debugging an initial setup. It will place details about login attempts in /var/log/maillog.

vim /etc/dovecot/conf.d/10-logging.conf
log_path = syslog
auth_verbose = yes
auth_debug = yes
mail_debug = yes

At this point, it's a good idea to restart the Postfix and Dovecot services, and test out the basic configuration.

service postfix restart
service dovecot restart

Watch the maillog while attempting to authenticate with an email client like Thunderbird.

tail -f /var/log/maillog

If basic authentication is working, we can go ahead and add another layer of complexity on top of it: SSL.

SSL/TLS

Add TLS support to Postfix, to encrypt SMTP authentication traffic.

vim /etc/postfix/main.cf
smtpd_use_tls = yes
smtpd_tls_auth_only = yes
smtpd_tls_cert_file = /etc/pki/CA/ssl_mail.alteeve.ca.crt
smtpd_tls_key_file = /etc/pki/CA/private/mail.alteeve.ca.key
smtpd_tls_loglevel = 1

Add TLS support to Dovecot, to encrypt IMAP authentication traffic.

vim /etc/dovecot/conf.d/10-ssl.conf
ssl = yes

# PEM encoded X.509 SSL/TLS certificate and private key.
ssl_cert = </etc/pki/CA/ssl_mail.alteeve.ca.crt
ssl_key = </etc/pki/CA/private/mail.alteeve.ca.key

# PEM encoded trusted certificate authority. Otherwise your CA will be untrusted.
# This is the intermediary certificate.
ssl_ca = </etc/pki/CA/RapidSSL_CA_bundle_alteeve.ca.pem

Dovecot prefers the following permissions for SSL certs, so set them accordingly.

chmod 0444 /etc/pki/CA/ssl_mail.alteeve.ca.crt
chmod 0400 /etc/pki/CA/private/mail.alteeve.ca.key
chmod 0400 /etc/pki/CA/RapidSSL_CA_bundle_alteeve.ca.pem

Restart Postfix and Dovecot, then change your Thunderbird server options to 'STARTTLS'. If you're still able to connect to the mail server and send mail, proceed to the next section.

User Password Encryption

In addition to SSL/TSL, which only encrypts the transport of user credentials, we're also going to encrypt the passwords themselves. This will avoid storing any plaintext passwords in the Postgres database.

vim /etc/dovecot/conf.d/10-auth.conf

Remove the "plain" authentication, and replace with cram-md5.

disable_plaintext_auth = yes
auth_mechanisms = cram-md5

Any user credentials that were previously stored in plaintext will no longer work. To encrypt your password in a way that Dovecot recognizes, use the following command:

doveadm -v pw -s CRAM-MD5 -p mypassword

It will return a hash like this.

{CRAM-MD5}de5924752ad74e36bc271a8dc7fad4b2d341f21f05382f20dedf1fdfbd5a1717

Take the entire hash, including the '{CRAM-MD5}' portion, and use it to replace the password entry in the database for that user. This will allow Dovecot to authenticate the user using the CRAM-MD5 auth mechanism.

To automate this process for all users in the database, you can look at the number of userid's there are and loop through them, encrypting and replacing each password.

#!/bin/bash
#
# a script to encrypt the users.usr_password values of the an_tools database

export PGUSER="alteeve"
export PGPASSWORD='secret'

for usrid in {1..219}; do

    # grab the user's password, removing whitespace
    usrpass=$(psql -d an_tools -c "SELECT users.usr_password FROM users WHERE users.usr_id=$usrid;"\
 | sed -n 3p | sed -e 's/^[ ]*//')

    if [[ "$usrpass" == *CRAM* ]]; then
        echo "Password for user #$usrid is already encrypted; skipping."
    else
        # encrypt and surround in single quotes for psql
        encrypted=\'$(doveadm -v pw -s CRAM-MD5 -p "$usrpass")\'
        echo "old password: [$usrpass] ; encrypted: $encrypted"

        # set password to encrypted value
        psql -d an_tools -c "UPDATE users SET usr_password=$encrypted WHERE usr_id=$usrid;"
    fi
done

unset PGUSER
unset PGPASSWORD

Postgrey Greylisting

Enabling postgrey for anti-spam greylisting.

First install the RPMForge repos. (See Dakini's blog for details.)

yum -y install postgrey

Create the config file with the following options. This will delay mail from untrusted sources by 6 minutes. A legitimate mailserver will resend the request after that time, and be allowed through. But spam is generally sent out only once, so those messages will drop.

vim /etc/sysconfig/postgrey
OPTIONS="--unix=/var/spool/postfix/postgrey/socket --delay=360"

Ensure that Postgrey starts on boot.

chkconfig --levels 345 postgrey on
/etc/postfix/main.cf

Configure Postfix to check SMTP requests through Postgrey. Postgrey will decide if the mail should be blocked or accepted.

smtpd_recipient_restrictions =
        permit_mynetworks
        permit_sasl_authenticated
        reject_unauth_destination
        check_policy_service unix:postgrey/socket

Restart Postfix and Postgrey to take affect.

service postgrey start
service postfix restart

RoundCube Web Mail

Install the packages (these require the EPEL repo);

yum install roundcubemail php-pear-MDB2-Driver-pgsql

You need to set the timezone in the /etc/php.ini file.

cp /etc/php.ini /etc/php.ini.orig
vim /etc/php.ini

Set date.timezone value. If you aren't sure of the format or name of your timezone, run tzselect and follow the prompts. We want America/Toronto.

diff -u /etc/php.ini.orig /etc/php.ini
--- /etc/php.ini.orig	2012-08-18 22:27:05.244670258 -0400
+++ /etc/php.ini	2012-08-18 21:49:37.926938864 -0400
@@ -943,7 +943,7 @@
 [Date]
 ; Defines the default timezone used by the date functions
 ; http://www.php.net/manual/en/datetime.configuration.php#ini.date.timezone
-;date.timezone = 
+date.timezone = America/Toronto
 
 ; http://www.php.net/manual/en/datetime.configuration.php#ini.date.default-latitude
 ;date.default_latitude = 31.7667

Create the database for roundcube

su - postgres
createdb -O alteeve -E UNICODE roundcubemail
psql -U alteeve -D roundcubemail
\i /usr/share/doc/roundcubemail-0.5.4/SQL/postgres.initial.sql

Edit main configuration file

vim /etc/roundcubemail/main.inc.php
$rcmail_config['default_host'] = 'localhost';
$rcmail_config['smtp_server'] = 'tls://mail.alteeve.ca';
$rcmail_config['smtp_user'] = '%u';
$rcmail_config['smtp_pass'] = '%p';
$rcmail_config['smtp_auth_type'] = 'CRAM-MD5';
$rcmail_config['force_https'] = true;
$rcmail_config['use_https'] = true;
$rcmail_config['login_autocomplete'] = 1;

Now setup roundcube for connecting to our DB;

cp /etc/roundcubemail/db.inc.php /etc/roundcubemail/db.inc.php.orig
vim /etc/roundcubemail/db.inc.php

Now set the connection string. Note to switch the DB driver to pgsql.

diff -u /etc/roundcubemail/db.inc.php.orig /etc/roundcubemail/db.inc.php
--- /etc/roundcubemail/db.inc.php.orig	2012-05-06 13:53:52.000000000 -0400
+++ /etc/roundcubemail/db.inc.php	2012-05-06 15:45:30.000000000 -0400
@@ -18,7 +18,7 @@
 // format is db_provider://user:password@host/database 
 // For examples see http://pear.php.net/manual/en/package.database.mdb2.intro-dsn.php
 
-$rcmail_config['db_dsnw'] = 'mysql://roundcube:pass@localhost/roundcubemail';
+$rcmail_config['db_dsnw'] = 'pgsql://alteeve:secret@localhost/roundcubemail';
 // postgres example: 'pgsql://roundcube:pass@localhost/roundcubemail';
 // Warning: for SQLite use absolute path in DSN:

Now setup roundcube to communicate with the mail server.

cp /etc/roundcubemail/main.inc.php /etc/roundcubemail/main.inc.php.orig
vim /etc/roundcubemail/main.inc.php

There are several variables to set. Our server will talk to localhost using tls on port 587 using CRAM_MD5 encryption. We use, and require, https connections. There are a couple special values for querying the user's name and password from the database. Finally, we want to enable the user's browser's auto-complete functions and set the name shown to the users. Once all set, the diff should be similar to the one below.

diff -u /etc/roundcubemail/main.inc.php.orig /etc/roundcubemail/main.inc.php
--- /etc/roundcubemail/main.inc.php.orig	2012-05-06 13:53:59.000000000 -0400
+++ /etc/roundcubemail/main.inc.php	2012-07-06 14:59:07.000000000 -0400
@@ -65,7 +65,7 @@
 // %n - http hostname ($_SERVER['SERVER_NAME'])
 // %d - domain (http hostname without the first part)
 // For example %n = mail.domain.tld, %d = domain.tld
-$rcmail_config['default_host'] = '';
+$rcmail_config['default_host'] = 'localhost';
 
 // TCP port used for IMAP connections
 $rcmail_config['default_port'] = 143;
@@ -121,22 +121,22 @@
 // %d - domain (http hostname without the first part)
 // %z - IMAP domain (IMAP hostname without the first part)
 // For example %n = mail.domain.tld, %d = domain.tld
-$rcmail_config['smtp_server'] = '';
+$rcmail_config['smtp_server'] = 'tls://mail.alteeve.ca';
 
 // SMTP port (default is 25; 465 for SSL)
-$rcmail_config['smtp_port'] = 25;
+$rcmail_config['smtp_port'] = 587;
 
 // SMTP username (if required) if you use %u as the username Roundcube
 // will use the current username for login
-$rcmail_config['smtp_user'] = '';
+$rcmail_config['smtp_user'] = '%u';
 
 // SMTP password (if required) if you use %p as the password Roundcube
 // will use the current user's password for login
-$rcmail_config['smtp_pass'] = '';
+$rcmail_config['smtp_pass'] = '%p';
 
 // SMTP AUTH type (DIGEST-MD5, CRAM-MD5, LOGIN, PLAIN or empty to use
 // best server supported one)
-$rcmail_config['smtp_auth_type'] = '';
+$rcmail_config['smtp_auth_type'] = 'CRAM-MD5';
 
 // Optional SMTP authentication identifier to be used as authorization proxy
 $rcmail_config['smtp_auth_cid'] = null;
@@ -179,16 +179,16 @@
 // enforce connections over https
 // with this option enabled, all non-secure connections will be redirected.
 // set the port for the ssl connection as value of this option if it differs from the default 443
-$rcmail_config['force_https'] = false;
+$rcmail_config['force_https'] = true;
 
 // tell PHP that it should work as under secure connection
 // even if it doesn't recognize it as secure ($_SERVER['HTTPS'] is not set)
 // e.g. when you're running Roundcube behind a https proxy
-$rcmail_config['use_https'] = false;
+$rcmail_config['use_https'] = true;
 
 // Allow browser-autocompletion on login form.
 // 0 - disabled, 1 - username and host only, 2 - username, host, password
-$rcmail_config['login_autocomplete'] = 0;
+$rcmail_config['login_autocomplete'] = 1;
 
 // If users authentication is not case sensitive this must be enabled.
 // You can also use it to force conversion of logins to lower case.
@@ -261,7 +261,7 @@
 $rcmail_config['useragent'] = 'Roundcube Webmail/'.RCMAIL_VERSION;
 
 // use this name to compose page titles
-$rcmail_config['product_name'] = 'Roundcube Webmail';
+$rcmail_config['product_name'] = 'AN!Mail';
 
 // try to load host-specific configuration
 // see http://trac.roundcube.net/wiki/Howto_Config for more details

That should be it.

Error No. [500]

After a recent OS update, 6.3 to 6.4, I started to get:

Error No. [500]

When trying to log into Round Cube. When I tail'ed /var/www/ssl_alteeve.ca/logs/error.log, there were two errors;

[Tue Sep 03 10:39:05 2013] [error] [client 108.168.16.38] PHP Warning:  Error writing to log file /var/log/roundcubemail/errors; Please check permissions in /usr/share/roundcubemail/program/include/main.inc on line 1965, referer: https://alteeve.ca/m/
[Tue Sep 03 10:39:05 2013] [error] [client 108.168.16.38] PHP Notice:  Could not perform encryption; make sure Mcrypt is installed or lib/des.inc is available in /usr/share/roundcubemail/program/include/main.inc on line 2120, referer: https://alteeve.ca/m/

Fixing the first was easy. The owner on /var/log/roundcubemail/errors was root:apache and the mode was 644, so a quick;

chmod 664 /var/log/roundcubemail/errors

Resolved that issue. Then I tail'ed the roundcube log and still saw the "Mcrypt" error. I found this post which had the fix. The trick was to alter /etc/php.d/mcrypt.ini.orig.

cp /etc/php.d/mcrypt.ini /etc/php.d/mcrypt.ini.orig
vim /etc/php.d/mcrypt.ini

Change module.so to mcrypt.so, save and reload apache.

diff -u /etc/php.d/mcrypt.ini.orig /etc/php.d/mcrypt.ini
--- /etc/php.d/mcrypt.ini.orig	2013-09-03 11:10:26.375001302 -0400
+++ /etc/php.d/mcrypt.ini	2013-09-03 10:46:52.340999323 -0400
@@ -1,2 +1,3 @@
 ; Enable mcrypt extension module
-extension=module.so
+;extension=module.so
+extension=mcrypt.so

Reload httpd;

/etc/init.d/httpd reload
Reloading httpd:

RoundCube should now work again.

Adding a password-reset link to the login page

Edit the login page template to insert the AN!Console password recovery link.

vim /usr/share/roundcubemail/skins/default/templates/login.html

(The part we're adding is the '<a href=""></a>'. Other parts of the template file are included here as a reference.)

<div id="login-form">
<div class="boxtitle"><roundcube:label name="welcome" /></div>
<div class="boxcontent">

<form name="form" action="./" method="post">
<roundcube:object name="loginform" form="form" />

<p style="text-align:center;"><input type="submit" class="button mainaction" value="<roundcube:label name='login' />" /></p>

</form>
<a href="../../cgi-bin/t/password.cgi">Forgot your password?</a>
</div>
</div>

Bugzilla

This tutorial covers installing bugzilla 4.4 on AN!'s bugzilla server.

Installing Bugzilla

  • Installed on a fresh minimal CentOS / RHEL 6.4 install.
  • Installed at: /var/www/ssl_bugs.alteeve.ca/html/ on a dedicated server.
  • Databases hosted on an external server running PostgreSQL.

Setup your webserver as above. Be sure to use SSL certificates! In this case, we will host our bugzilla at https://bugs.alteeve.ca.

Create the working directory, go to that directory, download the 4.4 install, extract it and switch into the created bugzilla-4.4 directory.

mkdir -p /var/www/{bugs.alteeve.ca,ssl_bugs.alteeve.ca}/{html,logs,cgi-bin,temp}
cd /var/www/ssl_bugs.alteeve.ca/temp/
wget -c http://ftp.mozilla.org/pub/mozilla.org/webtools/bugzilla-4.4.tar.gz
tar -xvzf bugzilla-4.4.tar.gz 
cd bugzilla-4.4

Install dependent RPMs;

yum groupinstall development
yum install perl-ExtUtils-MakeMaker perl-GD perl-GDTextUtil perl-MIME-tools perl-XML-Twig perl-DBD-Pg openssl-devel mod_perl-devel \
            mod_perl patchutils perl-Authen-SASL perl-BSD-Resource perl-CPAN perl-Class-Singleton perl-Convert-ASN1 perl-DateTime \
            perl-Digest-HMAC perl-Digest-SHA1 vim rsync wget acpid gpm mlocate syslinux perl-GSSAPI perl-LDAP perl-List-MoreUtils \
            perl-Params-Validate perl-SOAP-Lite perl-Test-Simple perl-Text-Iconv perl-XML-Filter-BufferText perl-XML-NamespaceSupport \
            perl-XML-SAX-Writer httpd cvs postgresql

Remove RPMs with perl modules that are too old.

yum remove perl-TimeDate perl-List-MoreUtils

Install from CPAN remaining needed perl modules.

# Don't ask us questions
export PERL_MM_USE_DEFAULT=1

# Optional modules
perl -MCPAN -e 'install("YAML")'
perl -MCPAN -e 'install Chart::Lines'
perl -MCPAN -e 'install Template::Plugin::GD::Image'
perl -MCPAN -e 'install GD::Graph'
perl -MCPAN -e 'install MIME::Parser'
perl -MCPAN -e 'install PatchReader'
perl -MCPAN -e 'install Net::SMTP::SSL'
perl -MCPAN -e 'install Authen::Radius'
perl -MCPAN -e 'install SOAP::Lite'
perl -MCPAN -e 'install JSON::RPC'
perl -MCPAN -e 'install JSON::XS'
perl -MCPAN -e 'install Test::Taint'
perl -MCPAN -e 'install HTML::Scrubber'
perl -MCPAN -e 'install Encode::Detect'
perl -MCPAN -e 'install Email::Reply'
perl -MCPAN -e 'install HTML::FormatText::WithLinks'
perl -MCPAN -e 'install TheSchwartz'
perl -MCPAN -e 'install Daemon::Generic'
perl -MCPAN -e 'install Apache2::SizeLimit'
perl -MCPAN -e 'install File::MimeInfo::Magic'

# Required modules
perl -MCPAN -e 'install DateTime'
perl -MCPAN -e 'install Email::Send'
perl -MCPAN -e 'install Math::Random::ISAAC'

If the above completed successfully, you should be able to run bugzilla's checksetup.pl script and have no missing modules, save for the DB drivers we're not going to use.

./checksetup.pl --check-modules
* This is Bugzilla 4.4 on perl 5.10.1
* Running on Linux 2.6.32-358.18.1.el6.x86_64 #1 SMP Wed Aug 28 17:19:38 UTC 2013

Checking perl modules...
Checking for               CGI.pm (v3.51)     ok: found v3.63 
Checking for           Digest-SHA (any)       ok: found v5.47 
Checking for             TimeDate (v2.23)     ok: found v2.24 
Checking for             DateTime (v0.28)     ok: found v1.03 
Checking for    DateTime-TimeZone (v0.71)     ok: found v1.60 
Checking for                  DBI (v1.54)     ok: found v1.609 
Checking for     Template-Toolkit (v2.22)     ok: found v2.25 
Checking for           Email-Send (v2.04)     ok: found v2.199 
Checking for           Email-MIME (v1.904)    ok: found v1.924 
Checking for                  URI (v1.37)     ok: found v1.60 
Checking for       List-MoreUtils (v0.32)     ok: found v0.33 
Checking for    Math-Random-ISAAC (v1.0.1)    ok: found v1.004 

Checking available perl DBD modules...
Checking for               DBD-Pg (v2.7.0)    ok: found v2.15.1 
Checking for            DBD-mysql (v4.001)    not found 
Checking for           DBD-SQLite (v1.29)     not found 
Checking for           DBD-Oracle (v1.19)     not found 

The following Perl modules are optional:
Checking for                   GD (v1.20)     ok: found v2.44 
Checking for                Chart (v2.1)      ok: found v2.4.6 
Checking for          Template-GD (any)       ok: found v1.56 
Checking for           GDTextUtil (any)       ok: found v0.86 
Checking for              GDGraph (any)       ok: found v1.48 
Checking for           MIME-tools (v5.406)    ok: found v5.504 
Checking for          libwww-perl (any)       ok: found v6.05 
Checking for             XML-Twig (any)       ok: found v3.34 
Checking for          PatchReader (v0.9.6)    ok: found v0.9.6 
Checking for            perl-ldap (any)       ok: found v0.40 
Checking for          Authen-SASL (any)       ok: found v2.13 
Checking for         Net-SMTP-SSL (v1.01)     ok: found v1.01 
Checking for           RadiusPerl (any)       ok: found v0.23 
Checking for            SOAP-Lite (v0.712)    ok: found v1.06 
Checking for             JSON-RPC (any)       ok: found v1.03 
Checking for              JSON-XS (v2.0)      ok: found v2.34 
Checking for           Test-Taint (any)       ok: found v1.06 
Checking for          HTML-Parser (v3.40)     ok: found v3.64 
Checking for        HTML-Scrubber (any)       ok: found v0.09 
Checking for               Encode (v2.21)     ok: found v2.35 
Checking for        Encode-Detect (any)       ok: found v1.01 
Checking for          Email-Reply (any)       ok: found v1.203 
Checking for HTML-FormatText-WithLinks (v0.13)     ok: found v0.14 
Checking for          TheSchwartz (any)       ok: found v1.10 
Use of uninitialized value $ENV{"FLOCK_FORKING_USE"} in string eq at /usr/local/share/perl5/File/Flock/Forking.pm line 13, <DATA> line 522.
Checking for       Daemon-Generic (any)       ok: found v0.83 
Checking for             mod_perl (v1.999022) ok: found v2.000004 
Checking for     Apache-SizeLimit (v0.96)     ok: found v0.96 
Checking for        File-MimeInfo (any)       ok: found v0.18 
Checking for           IO-stringy (any)       ok: found v2.110 
Checking for          mod_headers (any)       ok 
Checking for          mod_expires (any)       ok 
Checking for              mod_env (any)       ok

Excellent!

Now re-run checksetup.pl by itself;

./checksetup.pl
* This is Bugzilla 4.4 on perl 5.10.1
* Running on Linux 2.6.32-358.18.1.el6.x86_64 #1 SMP Wed Aug 28 17:19:38 UTC 2013

Checking perl modules...
Checking for               CGI.pm (v3.51)     ok: found v3.63 
Checking for           Digest-SHA (any)       ok: found v5.47 
Checking for             TimeDate (v2.23)     ok: found v2.24 
Checking for             DateTime (v0.28)     ok: found v1.03 
Checking for    DateTime-TimeZone (v0.71)     ok: found v1.60 
Checking for                  DBI (v1.54)     ok: found v1.609 
Checking for     Template-Toolkit (v2.22)     ok: found v2.25 
Checking for           Email-Send (v2.04)     ok: found v2.199 
Checking for           Email-MIME (v1.904)    ok: found v1.924 
Checking for                  URI (v1.37)     ok: found v1.60 
Checking for       List-MoreUtils (v0.32)     ok: found v0.33 
Checking for    Math-Random-ISAAC (v1.0.1)    ok: found v1.004 

Checking available perl DBD modules...
Checking for               DBD-Pg (v2.7.0)    ok: found v2.15.1 
Checking for            DBD-mysql (v4.001)    not found 
Checking for           DBD-SQLite (v1.29)     not found 
Checking for           DBD-Oracle (v1.19)     not found 

The following Perl modules are optional:
Checking for                   GD (v1.20)     ok: found v2.44 
Checking for                Chart (v2.1)      ok: found v2.4.6 
Checking for          Template-GD (any)       ok: found v1.56 
Checking for           GDTextUtil (any)       ok: found v0.86 
Checking for              GDGraph (any)       ok: found v1.48 
Checking for           MIME-tools (v5.406)    ok: found v5.504 
Checking for          libwww-perl (any)       ok: found v6.05 
Checking for             XML-Twig (any)       ok: found v3.34 
Checking for          PatchReader (v0.9.6)    ok: found v0.9.6 
Checking for            perl-ldap (any)       ok: found v0.40 
Checking for          Authen-SASL (any)       ok: found v2.13 
Checking for         Net-SMTP-SSL (v1.01)     ok: found v1.01 
Checking for           RadiusPerl (any)       ok: found v0.23 
Checking for            SOAP-Lite (v0.712)    ok: found v1.06 
Checking for             JSON-RPC (any)       ok: found v1.03 
Checking for              JSON-XS (v2.0)      ok: found v2.34 
Checking for           Test-Taint (any)       ok: found v1.06 
Checking for          HTML-Parser (v3.40)     ok: found v3.64 
Checking for        HTML-Scrubber (any)       ok: found v0.09 
Checking for               Encode (v2.21)     ok: found v2.35 
Checking for        Encode-Detect (any)       ok: found v1.01 
Checking for          Email-Reply (any)       ok: found v1.203 
Checking for HTML-FormatText-WithLinks (v0.13)     ok: found v0.14 
Checking for          TheSchwartz (any)       ok: found v1.10 
Use of uninitialized value $ENV{"FLOCK_FORKING_USE"} in string eq at /usr/local/share/perl5/File/Flock/Forking.pm line 13, <DATA> line 522.
Checking for       Daemon-Generic (any)       ok: found v0.83 
Checking for             mod_perl (v1.999022) ok: found v2.000004 
Checking for     Apache-SizeLimit (v0.96)     ok: found v0.96 
Checking for        File-MimeInfo (any)       ok: found v0.18 
Checking for           IO-stringy (any)       ok: found v2.110 
Checking for          mod_headers (any)       ok 
Checking for          mod_expires (any)       ok 
Checking for              mod_env (any)       ok 
Reading ./localconfig...

This version of Bugzilla contains some variables that you may want to
change and adapt to your local settings. The following variables are
new to ./localconfig since you last ran checksetup.pl:

create_htaccess, webservergroup, use_suexec, db_driver, db_host,
db_name, db_user, db_pass, db_port, db_sock, db_check, index_html,
cvsbin, interdiffbin, diffpath, site_wide_secret

Please edit the file ./localconfig and then re-run checksetup.pl
to complete your installation.

This will generate a file called localconfig with initial values. Make a backup of this and then edit it.

cp localconfig localconfig.orig
vim localconfig

Change the values as needed. Below is the diff of the configuration use by AN!.

diff -u localconfig.orig localconfig
--- localconfig.orig	2013-09-03 18:21:10.265003147 -0400
+++ localconfig	2013-09-03 18:38:00.231000167 -0400
@@ -47,30 +47,30 @@
 # can be obtained by listing Bugzilla/DB directory - every module corresponds
 # to one supported database and the name of the module (before ".pm")
 # corresponds to a valid value for this variable.
-$db_driver = 'mysql';
+$db_driver = 'Pg';
 
 # The DNS name or IP address of the host that the database server runs on.
-$db_host = 'localhost';
+$db_host = 'vm09-db01.alteeve.ca';
 
 # The name of the database. For Oracle, this is the database's SID. For
 # SQLite, this is a name (or path) for the DB file.
-$db_name = 'bugs';
+$db_name = 'an_bugs';
 
 # Who we connect to the database as.
-$db_user = 'bugs';
+$db_user = 'alteeve';
 
 # Enter your database password here. It's normally advisable to specify
 # a password for your bugzilla database user.
 # If you use apostrophe (') or a backslash (\) in your password, you'll
 # need to escape it by preceding it with a '\' character. (\') or (\)
 # (It is far simpler to just not use those characters.)
-$db_pass = '';
+$db_pass = 'secret';
 
 # Sometimes the database server is running on a non-standard port. If that's
 # the case for your database server, set this to the port number that your
 # database server is running on. Setting this to 0 means "use the default
 # port for my database server."
-$db_port = 0;
+$db_port = 5432;
 
 # MySQL Only: Enter a path to the unix socket for MySQL. If this is
 # blank, then MySQL's compiled-in default will be used. You probably

Create the an_bugs database.

createdb an_bugs -h vm09-db01.alteeve.ca -U alteeve
Password:

Rerun checksetup.pl again to verify your new configuration is sensible.

./checksetup.pl
* This is Bugzilla 4.4 on perl 5.10.1
* Running on Linux 2.6.32-358.18.1.el6.x86_64 #1 SMP Wed Aug 28 17:19:38 UTC 2013

Checking perl modules...
Checking for               CGI.pm (v3.51)     ok: found v3.63 
Checking for           Digest-SHA (any)       ok: found v5.47 
Checking for             TimeDate (v2.23)     ok: found v2.24 
Checking for             DateTime (v0.28)     ok: found v1.03 
Checking for    DateTime-TimeZone (v0.71)     ok: found v1.60 
Checking for                  DBI (v1.54)     ok: found v1.609 
Checking for     Template-Toolkit (v2.22)     ok: found v2.25 
Checking for           Email-Send (v2.04)     ok: found v2.199 
Checking for           Email-MIME (v1.904)    ok: found v1.924 
Checking for                  URI (v1.37)     ok: found v1.60 
Checking for       List-MoreUtils (v0.32)     ok: found v0.33 
Checking for    Math-Random-ISAAC (v1.0.1)    ok: found v1.004 

Checking available perl DBD modules...
Checking for               DBD-Pg (v2.7.0)    ok: found v2.15.1 
Checking for            DBD-mysql (v4.001)    not found 
Checking for           DBD-SQLite (v1.29)     not found 
Checking for           DBD-Oracle (v1.19)     not found 

The following Perl modules are optional:
Checking for                   GD (v1.20)     ok: found v2.44 
Checking for                Chart (v2.1)      ok: found v2.4.6 
Checking for          Template-GD (any)       ok: found v1.56 
Checking for           GDTextUtil (any)       ok: found v0.86 
Checking for              GDGraph (any)       ok: found v1.48 
Checking for           MIME-tools (v5.406)    ok: found v5.504 
Checking for          libwww-perl (any)       ok: found v6.05 
Checking for             XML-Twig (any)       ok: found v3.34 
Checking for          PatchReader (v0.9.6)    ok: found v0.9.6 
Checking for            perl-ldap (any)       ok: found v0.40 
Checking for          Authen-SASL (any)       ok: found v2.13 
Checking for         Net-SMTP-SSL (v1.01)     ok: found v1.01 
Checking for           RadiusPerl (any)       ok: found v0.23 
Checking for            SOAP-Lite (v0.712)    ok: found v1.06 
Checking for             JSON-RPC (any)       ok: found v1.03 
Checking for              JSON-XS (v2.0)      ok: found v2.34 
Checking for           Test-Taint (any)       ok: found v1.06 
Checking for          HTML-Parser (v3.40)     ok: found v3.64 
Checking for        HTML-Scrubber (any)       ok: found v0.09 
Checking for               Encode (v2.21)     ok: found v2.35 
Checking for        Encode-Detect (any)       ok: found v1.01 
Checking for          Email-Reply (any)       ok: found v1.203 
Checking for HTML-FormatText-WithLinks (v0.13)     ok: found v0.14 
Checking for          TheSchwartz (any)       ok: found v1.10 
Use of uninitialized value $ENV{"FLOCK_FORKING_USE"} in string eq at /usr/local/share/perl5/File/Flock/Forking.pm line 13, <DATA> line 522.
Checking for       Daemon-Generic (any)       ok: found v0.83 
Checking for             mod_perl (v1.999022) ok: found v2.000004 
Checking for     Apache-SizeLimit (v0.96)     ok: found v0.96 
Checking for        File-MimeInfo (any)       ok: found v0.18 
Checking for           IO-stringy (any)       ok: found v2.110 
Checking for          mod_headers (any)       ok 
Checking for          mod_expires (any)       ok 
Checking for              mod_env (any)       ok 
Reading ./localconfig...
Checking for               DBD-Pg (v2.7.0)    ok: found v2.15.1 
Checking for           PostgreSQL (v8.03.0000) ok: found v08.04.1300 

Adding new table bz_schema...
Initializing bz_schema...
Creating tables...
Creating function array_accum...
Removing index 'bugs_fulltext_comments_idx' from the bugs_fulltext table...
Removing index 'bugs_fulltext_comments_noprivate_idx' from the bugs_fulltext table...
Adding new index 'profiles_login_name_lower_idx' to the profiles table ...
Adding new index 'fielddefs_name_lower_idx' to the fielddefs table ...
Adding new index 'keyworddefs_name_lower_idx' to the keyworddefs table ...
Adding new index 'products_name_lower_idx' to the products table ...
Setting up choices for standard drop-down fields:
   bug_status priority rep_platform resolution op_sys bug_severity
Creating ./data directory...
Creating ./data/attachments directory...
Creating ./data/db directory...
Creating ./data/extensions directory...
Creating ./data/mining directory...
Creating ./data/webdot directory...
Creating ./graphs directory...
Creating ./skins/custom directory...
Creating ./data/extensions/additional...
Creating ./data/mailer.testfile...
Creating ./Bugzilla/.htaccess...
Creating ./data/.htaccess...
Creating ./data/attachments/.htaccess...
Creating ./data/webdot/.htaccess...
Creating ./graphs/.htaccess...
Creating ./lib/.htaccess...
Creating ./template/.htaccess...
Creating contrib/.htaccess...
Creating t/.htaccess...
Creating xt/.htaccess...
Precompiling templates...done.
Fixing file permissions...
Initializing "Dependency Tree Changes" email_setting ...
Initializing "Product/Component Changes" email_setting ...
Marking closed bug statuses as such...
Creating default classification 'Unclassified'...
Setting up foreign keys...
Setting up the default status workflow...
Creating default groups...
Setting up user preferences...

Looks like we don't have an administrator set up yet. Either this is
your first time using Bugzilla, or your administrator's privileges
might have accidentally been deleted.
Enter the e-mail address of the administrator: admin@alteeve.ca
Enter the real name of the administrator: Alteeve Admin
Enter a password for the administrator account: 
Please retype the password to verify:
admin@alteeve.ca is now set up as an administrator.
Creating initial dummy product 'TestProduct'...

Now that you have installed Bugzilla, you should visit the 'Parameters'
page (linked in the footer of the Administrator account) to ensure it
is set up as you wish - this includes setting the 'urlbase' option to
the correct URL.
checksetup.pl complete.

Configure Apache for Bugzilla

Now move the files into the web root, switch to the web root document

rsync -av /var/www/ssl_bugs.alteeve.ca/temp/bugzilla-4.4/* /var/www/ssl_bugs.alteeve.ca/html/
chown -R apache:apache /var/www/ssl_bugs.alteeve.ca
cd /var/www/ssl_bugs.alteeve.ca/html

Next, setup the apache configuration files. We'll need two;

  • bugs.alteeve.ca.conf; rewrite all non-SSL requests to their SSL version.
  • ssl_bugs.alteeve.ca.conf; The actual configuration file.

The configuration to rewrite any incoming http:// requests to https:// requests.

vim /etc/httpd/conf.d/bugs.alteeve.ca.conf
<VirtualHost *:80>
	ServerAdmin admin@alteeve.ca

	ServerName bugs.alteeve.ca

	RedirectMatch permanent (.*) https://bugs.alteeve.ca$1

	ErrorLog /var/www/bugs.alteeve.ca/logs/error.log

	# Possible values include: debug, info, notice, warn, error, crit,
	# alert, emerg.
	LogLevel debug

	CustomLog /var/www/bugs.alteeve.ca/logs/access.log combined
	ServerSignature On
</VirtualHost>

Now write the actual SSL-enabled configuration for bugzilla.

vim /etc/httpd/conf.d/ssl_bugs.alteeve.ca.conf
<VirtualHost *:443>
	ServerAdmin admin@alteeve.ca

	ServerName bugs.alteeve.ca

	#DirectoryIndex index.cgi
	
	# We can haz security?
	SSLEngine on
	SSLProtocol all
	SSLCACertificateFile /etc/pki/CA/RapidSSL_CA_bundle.pem
	SSLCertificateFile /etc/pki/CA/ssl_bugs.alteeve.ca.crt
	SSLCertificateKeyFile /etc/pki/CA/private/bugs.alteeve.ca.key
    	
	DocumentRoot /var/www/ssl_bugs.alteeve.ca/html/
	Alias /w /var/www/ssl_bugs.alteeve.ca/html/index.php
	<Directory /var/www/ssl_bugs.alteeve.ca/html>
		AddHandler cgi-script .cgi
		Options +ExecCGI
		DirectoryIndex index.cgi index.html
		AllowOverride Limit FileInfo Indexes Options
		#Options +Includes Indexes FollowSymLinks MultiViews
		#AllowOverride All 
		#Order allow,deny
		#allow from all
	</Directory>

	ErrorLog /var/www/ssl_bugs.alteeve.ca/logs/error.log
	TransferLog /var/www/ssl_bugs.alteeve.ca/logs/transfer.log

	# Possible values include: debug, info, notice, warn, error, crit,
	# alert, emerg.
	LogLevel info

	CustomLog /var/www/ssl_bugs.alteeve.ca/logs/access.log combined
	ServerSignature On
</VirtualHost>

Verify the syntax;

apachectl -t
Syntax OK
apachectl -S
VirtualHost configuration:
wildcard NameVirtualHosts and _default_ servers:
*:443                  bugs.alteeve.ca (/etc/httpd/conf.d/ssl_bugs.alteeve.ca.conf:1)
*:80                   is a NameVirtualHost
         default server unknown.alteeve.ca (/etc/httpd/conf.d/00_default.conf:1)
         port 80 namevhost unknown.alteeve.ca (/etc/httpd/conf.d/00_default.conf:1)
         port 80 namevhost bugs.alteeve.ca (/etc/httpd/conf.d/bugs.alteeve.ca.conf:1)
         port 80 namevhost bugs.alteeve.ca (/etc/httpd/conf.d/ssl.conf:74)
Syntax OK

Run a final check of the bugzilla configuration;

cd /var/www/ssl_bugs.alteeve.ca/html
./checksetup.pl
* This is Bugzilla 4.4 on perl 5.10.1
* Running on Linux 2.6.32-358.18.1.el6.x86_64 #1 SMP Wed Aug 28 17:19:38 UTC 2013

Checking perl modules...
Checking for               CGI.pm (v3.51)     ok: found v3.63 
Checking for           Digest-SHA (any)       ok: found v5.47 
Checking for             TimeDate (v2.23)     ok: found v2.24 
Checking for             DateTime (v0.28)     ok: found v1.03 
Checking for    DateTime-TimeZone (v0.71)     ok: found v1.60 
Checking for                  DBI (v1.54)     ok: found v1.609 
Checking for     Template-Toolkit (v2.22)     ok: found v2.25 
Checking for           Email-Send (v2.04)     ok: found v2.199 
Checking for           Email-MIME (v1.904)    ok: found v1.924 
Checking for                  URI (v1.37)     ok: found v1.60 
Checking for       List-MoreUtils (v0.32)     ok: found v0.33 
Checking for    Math-Random-ISAAC (v1.0.1)    ok: found v1.004 

Checking available perl DBD modules...
Checking for               DBD-Pg (v2.7.0)    ok: found v2.15.1 
Checking for            DBD-mysql (v4.001)    not found 
Checking for           DBD-SQLite (v1.29)     not found 
Checking for           DBD-Oracle (v1.19)     not found 

The following Perl modules are optional:
Checking for                   GD (v1.20)     ok: found v2.44 
Checking for                Chart (v2.1)      ok: found v2.4.6 
Checking for          Template-GD (any)       ok: found v1.56 
Checking for           GDTextUtil (any)       ok: found v0.86 
Checking for              GDGraph (any)       ok: found v1.48 
Checking for           MIME-tools (v5.406)    ok: found v5.504 
Checking for          libwww-perl (any)       ok: found v6.05 
Checking for             XML-Twig (any)       ok: found v3.34 
Checking for          PatchReader (v0.9.6)    ok: found v0.9.6 
Checking for            perl-ldap (any)       ok: found v0.40 
Checking for          Authen-SASL (any)       ok: found v2.13 
Checking for         Net-SMTP-SSL (v1.01)     ok: found v1.01 
Checking for           RadiusPerl (any)       ok: found v0.23 
Checking for            SOAP-Lite (v0.712)    ok: found v1.06 
Checking for             JSON-RPC (any)       ok: found v1.03 
Checking for              JSON-XS (v2.0)      ok: found v2.34 
Checking for           Test-Taint (any)       ok: found v1.06 
Checking for          HTML-Parser (v3.40)     ok: found v3.64 
Checking for        HTML-Scrubber (any)       ok: found v0.09 
Checking for               Encode (v2.21)     ok: found v2.35 
Checking for        Encode-Detect (any)       ok: found v1.01 
Checking for          Email-Reply (any)       ok: found v1.203 
Checking for HTML-FormatText-WithLinks (v0.13)     ok: found v0.14 
Checking for          TheSchwartz (any)       ok: found v1.10 
Use of uninitialized value $ENV{"FLOCK_FORKING_USE"} in string eq at /usr/local/share/perl5/File/Flock/Forking.pm line 13, <DATA> line 522.
Checking for       Daemon-Generic (any)       ok: found v0.83 
Checking for             mod_perl (v1.999022) ok: found v2.000004 
Checking for     Apache-SizeLimit (v0.96)     ok: found v0.96 
Checking for        File-MimeInfo (any)       ok: found v0.18 
Checking for           IO-stringy (any)       ok: found v2.110 
Checking for          mod_headers (any)       ok 
Checking for          mod_expires (any)       ok 
Checking for              mod_env (any)       ok 
Reading ./localconfig...
Checking for               DBD-Pg (v2.7.0)    ok: found v2.15.1 
Checking for           PostgreSQL (v8.03.0000) ok: found v08.04.1300 

Removing existing compiled templates...
Precompiling templates...done.
Fixing file permissions...

Now that you have installed Bugzilla, you should visit the 'Parameters'
page (linked in the footer of the Administrator account) to ensure it
is set up as you wish - this includes setting the 'urlbase' option to
the correct URL.
checksetup.pl complete.

Start up the server!

/etc/init.d/httpd start
Starting httpd: Apache/2.2.15 mod_ssl/2.2.15 (Pass Phrase Dialog)
Some of your private key files are encrypted for security reasons.
In order to read them you have to provide the pass phrases.

Server bugs.alteeve.ca:443 (RSA)
Enter pass phrase:

OK: Pass Phrase Dialog successful.
                                                           [  OK  ]

If everything is working, you should be able to browse to your bugzilla install!

Configure Bugzilla Itself

Log in as the adminitrator (user name is the email address you entered earlier with ./checksetup.pl) and go to https://<domain>/editparams.cgi.

  • General
Variab Value
urlbase https://bugs.alteeve.ca
ssl_redirect Click to check On
sslbase https://bugs.alteeve.ca
  • Email
Variab Value
mail_delivery_method SMTP
mailfrom bugs@alteeve.ca
use_mailer_queue Click to check On
smtpserver mail.alteeve.ca
smtp_username bugs@alteeve.ca
smtp_password secret
smtp_ssl Click to check On
globalwatchers admin@alteeve.ca

Mailman

Mailing list software!

Install Mailman

We need mailman 3 in order to get encrypted passwords. So we'll not be using mailman as shipped with RHEL6.

Install Prerequisite RPMs

yum -y install postfix mailx httpd gcc mod_ssl
chkconfig postfix on
chkconfig httpd on

Install Python 2.7

From here.

wget -qO- http://people.redhat.com/bkabrda/scl_python27.repo >> /etc/yum.repos.d/scl.repo
yum update
yum -y install python27
scl enable python27 bash
python -V

You should get:

Python 2.7.5

Configure Local Postfix

vim /etc/postfix/main.cf

Add:

queue_directory = /var/spool/postfix
command_directory = /usr/sbin
daemon_directory = /usr/libexec/postfix
data_directory = /var/lib/postfix
mail_owner = postfix
mydomain = lists.alteeve.ca
inet_interfaces = all
inet_protocols = all
mydestination = lists.alteeve.ca
unknown_local_recipient_reject_code = 550
mynetworks_style = subnet
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
debug_peer_level = 2
debugger_command =
	 PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
	 ddd $daemon_directory/$process_name $process_id & sleep 5
sendmail_path = /usr/sbin/sendmail.postfix
newaliases_path = /usr/bin/newaliases.postfix
mailq_path = /usr/bin/mailq.postfix
setgid_group = postdrop
html_directory = no
manpage_directory = /usr/share/man
sample_directory = /usr/share/doc/postfix-2.6.6/samples
readme_directory = /usr/share/doc/postfix-2.6.6/README_FILES

(Re)start postfix:

/etc/init.d/postfix restart

Test local mail delivery:

echo hi | mailx -s test admin@alteeve.ca

If you got an email, local mail delivery is working.

Configure Apache for Mailman

Follow the Apache install above. Come back here

We will configure http://lists.alteeve.ca to redirect all calls to https://lists.alteeve.ca.

Specific configs:

Base apache:

diff -U0 /etc/httpd/conf/httpd.conf.orig /etc/httpd/conf/httpd.conf
--- /etc/httpd/conf/httpd.conf.orig	2013-02-25 18:26:51.000000000 -0500
+++ /etc/httpd/conf/httpd.conf	2014-04-03 21:00:51.952003006 -0400
@@ -103,6 +103,6 @@
-StartServers       8
-MinSpareServers    5
-MaxSpareServers   20
-ServerLimit      256
-MaxClients       256
-MaxRequestsPerChild  4000
+StartServers      16
+MinSpareServers   10
+MaxSpareServers   40
+ServerLimit      512
+MaxClients       512
+MaxRequestsPerChild  8000
@@ -119,5 +119,5 @@
-StartServers         4
-MaxClients         300
-MinSpareThreads     25
-MaxSpareThreads     75 
-ThreadsPerChild     25
+StartServers         8
+MaxClients         600
+MinSpareThreads     50
+MaxSpareThreads    150 
+ThreadsPerChild     50
@@ -262 +262 @@
-ServerAdmin root@localhost
+ServerAdmin admin@alteeve.ca
@@ -276 +276 @@
-#ServerName www.example.com:80
+ServerName lists.alteeve.ca:80
@@ -292 +292 @@
-DocumentRoot "/var/www/html"
+DocumentRoot "/var/www/default/html"
@@ -317 +317 @@
-<Directory "/var/www/html">
+<Directory "/var/www/default/html">
@@ -551 +551 @@
-Alias /icons/ "/var/www/icons/"
+Alias /icons/ "/var/www/default/icons/"
@@ -553 +553 @@
-<Directory "/var/www/icons">
+<Directory "/var/www/default/icons">
@@ -576 +576 @@
-ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
+ScriptAlias /cgi-bin/ "/var/www/default/cgi-bin/"
@@ -579 +579 @@
-# "/var/www/cgi-bin" should be changed to whatever your ScriptAliased
+# "/var/www/default/cgi-bin" should be changed to whatever your ScriptAliased
@@ -582 +582 @@
-<Directory "/var/www/cgi-bin">
+<Directory "/var/www/default/cgi-bin">
@@ -851 +851 @@
-# /var/www/error/include/ files and
+# /var/www/default/error/include/ files and
@@ -855 +855 @@
-Alias /error/ "/var/www/error/"
+Alias /error/ "/var/www/default/error/"
@@ -859 +859 @@
-    <Directory "/var/www/error">
+    <Directory "/var/www/default/error">
@@ -990 +990 @@
-#NameVirtualHost *:80
+NameVirtualHost *:80

SSL setup:

diff -U0 /etc/httpd/conf.d/ssl.conf.orig /etc/httpd/conf.d/ssl.conf
--- /etc/httpd/conf.d/ssl.conf.orig	2014-04-03 21:37:26.431005814 -0400
+++ /etc/httpd/conf.d/ssl.conf	2014-04-03 21:10:16.558004490 -0400
@@ -74 +74 @@
-<VirtualHost _default_:443>
+<VirtualHost _default_:80>

Configure the http redirect to https:

vim /etc/httpd/conf.d/lists.alteeve.ca.conf
<VirtualHost *:80>
	ServerAdmin admin@alteeve.ca

	ServerName lists.alteeve.ca

	RedirectMatch permanent (.*) https://lists.alteeve.ca$1

	ErrorLog /var/www/lists.alteeve.ca/logs/error.log
	LogLevel debug

	CustomLog /var/www/lists.alteeve.ca/logs/access.log combined
	ServerSignature On
</VirtualHost>

Setup the main https page:

vim /etc/httpd/conf.d/ssl_lists.alteeve.ca.conf
<VirtualHost *:443>
        ServerAdmin admin@alteeve.ca
 
        ServerName lists.alteeve.ca
 
        DirectoryIndex index.php index.html
 
        # We can haz security?
        SSLEngine on
        SSLProtocol all
        SSLCACertificateFile /etc/pki/CA/RapidSSL_CA_bundle.pem
        SSLCertificateFile /etc/pki/CA/wildcard_ssl_alteeve.ca.crt
        SSLCertificateKeyFile /etc/pki/CA/private/wildcard_alteeve.ca.key
 
        DocumentRoot /var/www/ssl_lists.alteeve.ca/html/
        Alias /w /var/www/ssl_lists.alteeve.ca/html/index.php
        <Directory /var/www/ssl_lists.alteeve.ca/html>
                Options +Includes Indexes FollowSymLinks MultiViews
                AllowOverride All
                Order allow,deny
                allow from all
        </Directory>
 
        ScriptAlias /cgi-bin/ /var/www/ssl_lists.alteeve.ca/cgi-bin/
        <Directory "/var/www/ssl_lists.alteeve.ca/cgi-bin">
                AllowOverride None
                Options ExecCGI -MultiViews +SymLinksIfOwnerMatch
                Order allow,deny
                Allow from all
        </Directory>
 
        ErrorLog /var/www/ssl_lists.alteeve.ca/logs/error.log
        TransferLog /var/www/ssl_lists.alteeve.ca/logs/transfer.log
 
        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel debug
 
        CustomLog /var/www/ssl_lists.alteeve.ca/logs/access.log combined
        ServerSignature On
</VirtualHost>

Copy the wildcard SSL certs into place.

Create a redirect page:

mkdir -p /var/www/ssl_lists.alteeve.ca/{cgi-bin,html,logs}
touch /var/www/ssl_lists.alteeve.ca/html/index.html
chown -R apache:apache /var/www
vim /var/www/ssl_lists.alteeve.ca/html/index.html
<head>
        <title>Alteeve's Niche! - Mailing Lists</title>
</head>
<body>
        <meta http-equiv="refresh" content="0; url=mailman/listinfo/" />
</body>

Connect to http://lists.alteeve.ca and it should automatically redirect to: http://lists.alteeve.ca/mailman/listinfo/.

Add an MX Record to Bind For lists.alteeve.ca

Add an entry in bind so that there is an MX record for lists.alteeve.ca:

/etc/named/db.alteeve.ca

Add:

lists.alteeve.ca.	MX	10	lists.alteeve.ca.

Save and reload named.

/etc/init.d/named reload

Install Mailman v3 from Source

At this time, the only v3 install is beta.

mkdir ~/temp
cd ~/temp/
wget https://launchpad.net/mailman/3.0/3.0.0b3/+download/mailman-3.0.0b3.tar.gz
tar -xvzf mailman-3.0.0b3.tar.gz 
cd mailman-3.0.0b3
python setup.py build
python setup.py install

And here, the best laid plans fell to pieces... Back to mailman 2.

Configure Mailmain

Create the initial mailman list.

/usr/lib/mailman/bin/newlist anvil-users
Enter the email of the person running the list: admin@alteeve.ca
Initial anvil-users password:
To finish creating your mailing list, you must edit your /etc/aliases (or
equivalent) file by adding the following lines, and possibly running the
`newaliases' program:

## anvil-users mailing list
anvil-users:              "|/usr/lib/mailman/mail/mailman post anvil-users"
anvil-users-admin:        "|/usr/lib/mailman/mail/mailman admin anvil-users"
anvil-users-bounces:      "|/usr/lib/mailman/mail/mailman bounces anvil-users"
anvil-users-confirm:      "|/usr/lib/mailman/mail/mailman confirm anvil-users"
anvil-users-join:         "|/usr/lib/mailman/mail/mailman join anvil-users"
anvil-users-leave:        "|/usr/lib/mailman/mail/mailman leave anvil-users"
anvil-users-owner:        "|/usr/lib/mailman/mail/mailman owner anvil-users"
anvil-users-request:      "|/usr/lib/mailman/mail/mailman request anvil-users"
anvil-users-subscribe:    "|/usr/lib/mailman/mail/mailman subscribe anvil-users"
anvil-users-unsubscribe:  "|/usr/lib/mailman/mail/mailman unsubscribe anvil-users"

Hit enter to notify anvil-users owner...

Edit the alias file:

vim /etc/aliases

Append:

## anvil-users mailing list
anvil-users:              "|/usr/lib/mailman/mail/mailman post anvil-users"
anvil-users-admin:        "|/usr/lib/mailman/mail/mailman admin anvil-users"
anvil-users-bounces:      "|/usr/lib/mailman/mail/mailman bounces anvil-users"
anvil-users-confirm:      "|/usr/lib/mailman/mail/mailman confirm anvil-users"
anvil-users-join:         "|/usr/lib/mailman/mail/mailman join anvil-users"
anvil-users-leave:        "|/usr/lib/mailman/mail/mailman leave anvil-users"
anvil-users-owner:        "|/usr/lib/mailman/mail/mailman owner anvil-users"
anvil-users-request:      "|/usr/lib/mailman/mail/mailman request anvil-users"
anvil-users-subscribe:    "|/usr/lib/mailman/mail/mailman subscribe anvil-users"
anvil-users-unsubscribe:  "|/usr/lib/mailman/mail/mailman unsubscribe anvil-users"

And load:

newaliases

WebUI Config

  1. https://lists.alteeve.ca/mailman/admin/anvil-users/general
    1. Hide the sender of a message, replacing it with the list address (Removes From, Sender and Reply-To fields) -> Yes.

Deleting Mail from the Archive

Go to the list directory:

cd /var/lib/mailman/archives/private

Edit the .mbox file for the list.

vim anvil-users.mbox/anvil-users.mbox

Find the message you want to delete and then delete everything from From <sender email> <date> until the same line from the next message (or end of the file if it's the last message in the list).

Example:

From lists@alteeve.ca  Thu Apr  3 23:35:27 2014
Return-Path: <lists@alteeve.ca>
X-Original-To: anvil-users@lists.alteeve.ca
Delivered-To: anvil-users@lists.alteeve.ca
Received: from vm08-mail01.alteeve.ca (unknown [65.39.153.71])
        by vm17-lists.alteeve.ca (Postfix) with ESMTP id DD83313FB13
        for <anvil-users@lists.alteeve.ca>;
        Thu,  3 Apr 2014 23:35:27 -0400 (EDT)
Received: from lemass.alteeve.ca (dhcp-108-168-20-202.cable.user.start.ca
        [108.168.20.202])
        by vm08-mail01.alteeve.ca (Postfix) with ESMTPSA id 80EC720171
        for <anvil-users@lists.alteeve.ca>;
        Thu,  3 Apr 2014 23:00:07 -0400 (EDT)
Message-ID: <533E2037.1020302@alteeve.ca>
Date: Thu, 03 Apr 2014 23:00:07 -0400
From: Digimer <lists@alteeve.ca>
User-Agent: Mozilla/5.0 (X11; Linux x86_64;
        rv:24.0) Gecko/20100101 Thunderbird/24.4.0
MIME-Version: 1.0
To: anvil-users@lists.alteeve.ca
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Subject: [Anvil-users] Test
X-BeenThere: anvil-users@lists.alteeve.ca
X-Mailman-Version: 2.1.12
Precedence: list
List-Id: <anvil-users.lists.alteeve.ca>
List-Unsubscribe: <https://lists.alteeve.ca/mailman/options/anvil-users>,
        <mailto:anvil-users-request@lists.alteeve.ca?subject=unsubscribe>
List-Archive: <http://lists.alteeve.ca/pipermail/anvil-users/>
List-Post: <mailto:anvil-users@lists.alteeve.ca>
List-Help: <mailto:anvil-users-request@lists.alteeve.ca?subject=help>
List-Subscribe: <https://lists.alteeve.ca/mailman/listinfo/anvil-users>,
        <mailto:anvil-users-request@lists.alteeve.ca?subject=subscribe>
X-List-Received-Date: Fri, 04 Apr 2014 03:35:27 -0000

Please ignore.

-- 
Digimer
Papers and Projects: https://alteeve.ca/w/
What if the cure for cancer is trapped in the mind of a person without 
access to education?

Once deleted, move the list directory out of the way and then regenerate the list archives.

mv /var/lib/mailman/archives/private/anvil-users /var/lib/mailman/archives/private/anvil-users.1
/usr/lib/mailman/bin/arch anvil-users
#00000 <CA+scbRK1dZAY6Jv5UqBM7-cG_L385QCtFY5UFx3RWRABN7sG1g@mail.gmail.com>
figuring article archives
2014-April
#00001 <CA+scbRJ96jXnx=0iFk220FsoEFghNoR2gwLg-DmTQ3rL2qDw+w@mail.gmail.com>
figuring article archives
2014-April
#00002 <533E2CF6.7080909@alteeve.ca>
figuring article archives
2014-April
Updating index files for archive [2014-April]
  Date
  Subject
  Author
  Thread
Computing threaded index
Updating HTML for article 0
Updating HTML for article 1
Updating HTML for article 2
Pickling archive state into /var/lib/mailman/archives/private/anvil-users/pipermail.pck

Reload the archive page and verify that the email is gone.

If so, delete the backup directory.

rm -rf /var/lib/mailman/archives/private/anvil-users.1

Thanks

 

Any questions, feedback, advice, complaints or meanderings are welcome.
Alteeve's Niche! Enterprise Support:
Alteeve Support
Community Support
© Alteeve's Niche! Inc. 1997-2024   Anvil! "Intelligent Availability®" Platform
legal stuff: All info is provided "As-Is". Do not use anything here unless you are willing and able to take responsibility for your own actions.