Lots of text, blogs, comparisons and flamewars exist on this topic around the Internet. Some of my favourite when jumping from Apache HTTPd AJP proxy to Nginx are:
- lower memory footprint
- no need to spawn new processes (considering prefork on Apache HTTPd)
- migration to a VPS is cheaper (Nginx consumes less resources, therefore you pay less)
- it is always good to learn something new
- it is super cool to say "I am using Nginx" :)
What am I using on Apache that needs to be migrated to Nginx:
- very simple rewrite (mod_rewrite)
- AJP proxy (mod_proxy_ajp) with Virtual Hosts
- SSL / https (mod_ssl)
- Google Pagespeed (mod_pagespeed)
+--------------------+ +-----------------------+
| Apache HTTPd | | Apache Tomcat |
|--------------------| |-----------------------|
| | | |
| mod_proxy_ajp | | |
| mod_pagespeed +----------> AJP Connector |
| | | |
| | | |
| | | |
| | | |
+--------------------+ +-----------------------+
Buidling Nginx with required modules / extensions on Gentoo
Installing a package from source on Gentoo Linux is super easy because everything is installed (emerged) from source. I was a bit surprised that Nginx needs a special treatment tough. Nginx ebuild located in the portage tree has no USE flags for any additional modules. Luckily there is another way.
For each and every module / addon one wishes to bundle with Nginx, it needs to be recompiled from source. Generaly it means to use a configure directive:
$ # Download ngx_pagespeed @see https://github.com/pagespeed/ngx_pagespeed/
$ cd /usr/src/
$ wget https://github.com/pagespeed/ngx_pagespeed/archive/v1.7.30.3-beta.zip
$ unzip v1.7.30.3-beta.zip # or unzip v1.7.30.3-beta
$ cd ngx_pagespeed-1.7.30.3-beta/
$ wget https://dl.google.com/dl/page-speed/psol/1.7.30.3.tar.gz
$ tar -xf 1.7.30.3.tar.gz # expands to psol/
$ # Download Nginx
$ cd /usr/src/
$ # check http://nginx.org/en/download.html for the latest version
$ wget http://nginx.org/download/nginx-1.4.6.tar.gz
$ tar -xf nginx-1.4.6.tar.gz
$ cd nginx-1.4.6/
$ ./configure --add-module=/usr/src/ngx_pagespeed-1.7.30.3-beta
$ make
$ sudo make install
With Gentoo the procedure is a bit simpler. Just download the addons / modules. Unpack them to a directory (e.g. /usr/src), setup make.conf so that you add NGINX_ADD_MODULES="" variable. In my case I had to add two module paths - one for Nginx AJP and one for Google Pagespeed:
$ cd /usr/src
# Download and unpack ngx_pagespeed and psol
$ wget https://github.com/pagespeed/ngx_pagespeed/archive/v1.7.30.3-beta.zip
$ unzip v1.7.30.3-beta.zip # or unzip v1.7.30.3-beta
$ cd ngx_pagespeed-1.7.30.3-beta/
$ wget https://dl.google.com/dl/page-speed/psol/1.7.30.3.tar.gz
$ tar -xf 1.7.30.3.tar.gz # expands to psol/
$ cd /usr/src
$ wget https://github.com/yaoweibin/nginx_ajp_module/archive/v0.3.0.zip
$ unzip v0.3.0.zip
# possibly fix ownership and permissions
$ chown -R root:root ngx_pagespeed-1.7.30.3-beta nginx_ajp_module-0.3.0
$ find ngx_pagespeed-1.7.30.3-beta nginx_ajp_module-0.3.0 -type d -exec chmod 755 {} +
$ find ngx_pagespeed-1.7.30.3-beta nginx_ajp_module-0.3.0 -type f -exec chmod 644 {} +
# BEWARE, this will issue a warning during the emerge, if you wish to use these modules, you just need to live with it
$ echo 'NGINX_ADD_MODULES="/usr/src/ngx_pagespeed-1.7.30.3-beta /usr/src/nginx_ajp_module-0.3.0"' >> /etc/portage/make.conf
# recompile Nginx server
$ emerge -av www-servers/nginx
Nginx should be ready to go now:
$ cd /etc/init.d/nginx start
Visit http://your.server.address/ and see the Nginx test page.
Converting Apache VirtualHost to Nginx VirtualHost
Simplified version of Apache HTTPd VirtualHost config for www.prvaci.eu domain:
$ cat /etc/apache2/vhosts.d/prvaci.eu.conf
<VirtualHost :80>
ServerName www.prvaci.eu
ServerAlias prvaci.eu *.prvaci.eu
ErrorLog /var/log/apache2/prvaci.eu.ajp.error.log
CustomLog /var/log/apache2/prvaci.eu.ajp.log combined
RewriteEngine On
RewriteCond %{HTTP_HOST} ^prvaci.eu [NC]
RewriteRule ^(.*)$ http://www.prvaci.eu$1 [L,R=301]
RewriteRule ^(.*);jsessionid=[^\?]+(.*)$ $1$2 [NE,R=301]
<Proxy *>
AddDefaultCharset Off
Order deny,allow
Allow from all
</Proxy>
ProxyPass / ajp://127.0.0.1:8009/
ProxyPassReverse / ajp://127.0.0.1:8009/
<IfDefine SSL>
<IfDefine SSL_DEFAULT_VHOST>
<IfModule ssl_module>
<VirtualHost :443>
SSLEngine on
#SSLProtocol all -SSLv2
SSLProtocol -ALL +SSLv3 +TLSv1
#SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCipherSuite HIGH:!SSLv2:!ADH:!aNULL:!eNULL:!NULL
SSLCertificateFile /etc/ssl/apache2/server.crt
SSLCertificateKeyFile /etc/ssl/apache2/server.key
ServerName www.prvaci.eu
ServerAlias prvaci.eu *.prvaci.eu
ErrorLog /var/log/apache2/prvaci.eu.ssl.error.log
CustomLog /var/log/apache2/prvaci.eu.ssl.log combined
RewriteEngine On
RewriteCond %{HTTP_HOST} ^prvaci.eu [NC]
RewriteRule ^(.*)$ https://www.prvaci.eu$1 [L,R=301]
RewriteRule ^(.*);jsessionid=[^\?]+(.*)$ $1$2 [NE,R=301]
</VirtualHost>
</IfModule>
</IfDefine>
</IfDefine>
</VirtualHost>
Corresponding version of Nginx VirtualHost configuration:
$ cat /etc/nginx/vhosts.d/prvaci.eu.conf
http {
upstream tomcats {
server 127.0.0.1:8009;
keepalive 10;
}
server {
listen prvaci.eu:80;
server_name prvaci.eu;
return 301 http://www.prvaci.eu$request_uri;
}
server {
listen www.prvaci.eu:80;
server_name www.prvaci.eu admin.prvaci.eu;
access_log /var/log/nginx/prvaci.eu_ajp_access_log;
error_log /var/log/nginx/prvaci.eu_ajp_error_log;
location / {
rewrite ^(.*)\;[jJ][sS][eE][sS][sS][iI][oO][nN][iI][dD]=[^\?]+(.*)$ $1$2 permanent;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
ajp_keep_conn on;
ajp_pass tomcats;
}
}
server {
## IP:Port and server name
listen prvaci.eu:444;
server_name prvaci.eu www.prvaci.eu admin.prvaci.eu;
## SSL log files
access_log /var/log/nginx/prvaci.eu_ssl_access_log;
error_log /var/log/nginx/prvaci.eu_ssl_error_log;
## SSL certificates
ssl_certificate /etc/nginx/ssl/prvaci.eu/self-ssl.crt;
ssl_certificate_key /etc/nginx/ssl/prvaci.eu/self-ssl.key;
## SSL settings
ssl on;
## SSL caching/optimization
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!SSLv2:!ADH:!aNULL:!eNULL:!NULL;
ssl_prefer_server_ciphers on;
keepalive_timeout 60;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
## Rest of server config goes here
location / {
proxy_set_header Accept-Encoding "";
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-By $server_addr:$server_port;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
}
}
}
Of course one could use a configuration translator, but I find it essential to know what and why is inside my prod configuration. I also managed to make Nginx with pagespeed module working, although it is not performing exactly as Apache with mod_pagespeed does. Especially CSS and JS compression and merging into as single file. Will have to look deeper into it.