This document covers the steps you need to take to have Atmail working with the NginX platform.
Nginx is a free, open-source, high-performance HTTP server and IMAP/POP3 proxy. This is useful for environments that wish to geographically split machines into independent entities, with a central routing system that forwards a user to his/her specific server.
First, download spawn-fcgi from http://redmine.lighttpd.net/projects/spawn-fcgi/news:
% wget "http://www.lighttpd.net/download/spawn-fcgi-1.6.3.tar.gz"
Untar, install:
% tar xvfz spawn-fcgi-1.6.3.tar.gz
% cd spawn-fcgi-1.6.3
% ./configure && make && make install
Then, download nginx from http://nginx.org/en/download.html:
% wget "http://nginx.org/download/nginx-1.0.8.tar.gz"
Untar, install:
% tar xvfz nginx-0.8.40.tar.gz
% cd nginx-0.8.40
% ./configure && make && make install
This will install nginx in /usr/local/nginx/. You will then need to move the /usr/local/nginx/conf/nginx.conf file:
% mv /usr/local/nginx/conf/nginx.conf /usr/local/nginx/conf/nginx.conf.old
% cd /usr/local/nginx/conf
Replace the nginx.conf file with these contents:
user atmail;
worker_processes 2;
error_log logs/error.log info;
pid logs/nginx.pid;
events {
worker_connections 1024;
}
mail {
auth_http localhost:80/auth.php;
proxy on;
imap_capabilities "IMAP4rev1" "UIDPLUS";
server {
listen 143;
protocol imap;
}
pop3_capabilities "TOP" "USER";
server {
listen 110;
protocol pop3;
}
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 10;
server {
# Your server's IP address. Leave as an asterisk to bind to all interfaces
listen *:80;
# Your domain name
server_name domain.com;
location / {
# Path to your Atmail webmail directory
root /usr/local/atmail/webmail/;
index index.php;
# this serves static files that exist without running other rewrite tests
if (-f $request_filename) {
expires 30d;
break;
}
# Routes directory requests to index.php.
if (!-e $request_filename) {
rewrite ^(.+)$ /index.php?q=$1 last;
}
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:34480; # IP and Port of your spawn-fcgi process
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /usr/local/atmail/webmail/$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
fastcgi_param REDIRECT_STATUS 200;
}
}
}
Spawn the FastCGI process afterwards. For this example, we will run it in port 34480:
% /usr/local/bin/spawn-fcgi -f /usr/bin/php-cgi -a 127.0.0.1 -p 34480 -P /var/run/fastcgi-php.pid -C 2
You will then need to edit the /usr/local/nginx/conf/nginx.conf file. It will contain this line:
fastcgi_pass 127.0.0.1:34480; # IP and Port of your spawn-fcgi process
If you change the spawn-fcgi port, you will need to edit it in the nginx.conf file as well. For example, a spawn-fcgi port of 51000 will have this command:
/usr/local/bin/spawn-fcgi -f /usr/bin/php-cgi -a 127.0.0.1 -p 51000 -P /var/run/fastcgi-php.pid -C 2
And this configuration line:
fastcgi_pass 127.0.0.1:51000; # IP and Port of your spawn-fcgi process
The configuration file will also contain the following lines of interest:
root /usr/local/atmail/webmail/;
This defines the document root you wish to have.
user atmail;
This defines the username you want to run nginx as.
worker_processes 2;
This sets the number of processes that nginx spawns. We recommend it to be set to the number of CPU cores you have available.
Note the document root specified above (in this case, /usr/local/atmail/webmail/). Create the authentication php file at /usr/local/atmail/webmail/auth.php, and fill it with these lines:
$username=$_SERVER["HTTP_AUTH_USER"] ;
$userpass=$_SERVER["HTTP_AUTH_PASS"] ;
$protocol=$_SERVER["HTTP_AUTH_PROTOCOL"] ;
$backend_port=110;
if ($protocol=="imap") {
$backend_port=143;
}
if ($protocol=="smtp") {
$backend_port=25;
}
if (!authuser($username,$userpass)) {
fail();
exit;
}
$userserver=getmailserver($username);
pass($userserver, $backend_port);
// Authentication block
function authuser($user,$pass)
{
// You can put a query for authentication with the DB here.
// Since auth will be done post-proxy, we're just returning true
return true;
}
// MySQL connection function
function mysqlconn($user,$query){
$atmail_dbuser="atmail";
$atmail_dbpass="changeme";
$atmail_db="nginx_map";
$atmail_dbhost="127.0.0.1";
mysql_connect($atmail_dbhost,$atmail_dbuser,$atmail_dbpass);
@mysql_select_db($atmail_db) or die( "Unable to select database");
$server1 = mysql_query($query);
$server = mysql_fetch_array($server1);
$server2 = $server['Server'];
return $server2;
mysql_close();
}
function getmailserver($user){
$query = "select Server from UserMap where Account='$user'";
$server = mysqlconn($user,$query);
return $server;
mysql_close();
}
function fail(){
header("Auth-Status: Invalid login or password");
exit;
}
function pass($server,$port){
header("Auth-Status: OK");
header("Auth-Server: $server");
header("Auth-Port: $port");
exit;
}
Save the file. After it is created, login to MySQL:
% mysql -u [dbuser] -p
Specify [dbuser] as your MySQL root user. Create the database (in this case, nginx_map, with the user 'atmail', the password 'changeme' and the host '127.0.0.1'):
> create database nginx_map;
> grant all privileges on nginx_map.* to 'atmail'@'localhost' identified by 'changeme';
> grant all privileges on nginx_map.* to 'atmail'@'127.0.0.1' identified by 'changeme';
> flush privileges;
Create the database skeleton:
CREATE TABLE `UserMap` (
`Account` varchar(255) NOT NULL default '',
`Server` varchar(255) NOT NULL default '',
PRIMARY KEY (`Account`) );
);
You can create preliminary entries like so:
> insert into UserMap values("john@juno.com","192.168.0.71");
This will forward the user 'john@juno.com' to the IMAP host at '192.168.0.71'.
When you are satisfied, run the nginx process:
% /usr/local/nginx/sbin/nginx
To test it out, login locally with your sample user:
% telnet localhost 143
Trying 127.0.0.1...
Connected to localhost.localdomain (127.0.0.1).
Escape character is '^]'.
* OK IMAP4 ready
1 login john@juno.com changeme
1 OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS MULTIAPPEND UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS QUOTA] Logged in
Congratulations! Now you can set your Nginx process as a forwarding proxy for IMAP and POP requests. This is useful for very large installations that wish to install Atmail as a geographically separated cluster install.