Transition to nginx: part 1, converting Horde webmail

Status
Not open for further replies.
N

netchild

Guest
I am a longtime Apache user. It may be that I touched Apache 1.2 for the first time. Recently I decided to check out nginx. So I decided to do it on my own webmail system. The end result is, I replaced apache+mod_php with nginx+php-fpm there, and so far it does not look like I want to go back (it feels faster on direct compare, same server, either Apache or nginx started to compare the speed, pure subjective “measurement”, no numbers).

The long story now.

The webmail system uses horde. There I had Apache 2.4 (prefork mpm) and php 5.6 via mod_php. With nginx I used php-fpm. I used the same php flags and values in php_fpm like I used with mod_php. I configured less php-fpm max-processes than I had allowed apache+mod_php to use. As nginx is not spawning processes for each connection, I have less processes and also less memory allocated as a result. Converting the rewrite rules and mod_rewrite based blacklisting took a while (and I have not converted all blacklists I had before). So yes, this is not really comparing apples with apples (I could have tried a different mpm for Apache, and I could have used an fcgi based php approach instead of mod_php, I could have moved the rewrite rules out from .htaccess files to the main config).

The result was on first login that the pages appeared noticeable faster. I directly switched back to Apache to confirm. This was over a WLAN connection. A little bit later I had the same impression when I tested this over a slow DSL link (2 MBit/s).

Here the important parts of the Apache config:
Code:
[INDENT]ExpiresActive On
ExpiresDefault "now plus 3 hours"
ExpiresByType image/* "now plus 2 months"
ExpiresByType text/javascript "now plus 2 months"
ExpiresByType application/x-javascript "now plus 2 months"
ExpiresByType text/css "now plus 2 months"

SetEnvIfNoCase Request_URI ".gif$" cache_me=1
SetEnvIfNoCase Request_URI ".png$" cache_me=1
SetEnvIfNoCase Request_URI ".jpg$" cache_me=1
SetEnvIfNoCase Request_URI ".jpeg$" cache_me=1
SetEnvIfNoCase Request_URI ".ico$" cache_me=1
SetEnvIfNoCase Request_URI ".css$" cache_me=1[/INDENT]

[INDENT]# Allow caching on media files
<IfModule mod_headers.c>
Header merge Cache-Control "public" env=cache_me
  <IfModule ssl_module.c>
    Header add Strict-Transport-Security "max-age=15768000"
  </IfModule>
</IfModule>[/INDENT]

[INDENT]<Location />
# Insert filter
SetOutputFilter DEFLATE

# Netscape 4.x has some problems...
BrowserMatch ^Mozilla/4 gzip-only-text/html

# Netscape 4.06-4.08 have some more problems
BrowserMatch ^Mozilla/4.0[678] no-gzip

# MSIE masquerades as Netscape, but it is fine
BrowserMatch bMSIE !no-gzip !gzip-only-text/html
# Don't compress images
SetEnvIfNoCase Request_URI
.(?:gif|jpe?g|png|gz|bz2|zip)$ no-gzip dont-vary

# Make sure proxies don't deliver the wrong content
Header append Vary User-Agent env=!dont-vary
</Location>[/INDENT]

[INDENT]SetEnvIfNoCase Request_URI ".js$" cache_me=1[/INDENT]

[INDENT]Alias /Microsoft-Server-ActiveSync /usr/local/www/horde/rpc.php
RedirectPermanent /.well-known/carddav /horde/rpc.php[/INDENT]

[INDENT]AcceptPathInfo on[/INDENT]

And here most parts of my nginx.conf suitable for Horde, including the rewrite rules from .htaccess files:
Code:
[INDENT]worker_processes  1;

error_log  <file>;

events {
        worker_connections      1024;
        use                     kqueue;
}


http {
        include    mime.types;
        default_type  application/octet-stream;

        access_log  <file>;

        sendfile        on;
        keepalive_timeout       15;
        client_body_timeout     300;
        client_header_timeout   12;
        send_timeout        300;
        client_body_in_file_only clean;
        client_body_buffer_size 128k;
        client_max_body_size 10M;

        gzip on;
        gzip_min_length 1000;
        gzip_types       text/plain text/xml text/css application/xml application/xhtml+xml application/rss+xml application/javascript application/x-javascript;
        gzip_disable     "msie6";

        include blacklist.conf;

        server {
                listen     443 ssl spdy;
                server_name  <hostname>;

                ssl_certificate         <file>;
                ssl_certificate_key     <file>;

                ssl_session_cache       shared:SSL:10m;
                ssl_session_timeout     15m;[/INDENT]

[INDENT]                ssl_ciphers     <ciper_list>;[/INDENT]

[INDENT]                ssl_prefer_server_ciphers  on;

                # optional: see https://www.owasp.org/index.php/List_of_useful_HTTP_headers
                add_header                        strict-transport-security "max-age=31536000";
                add_header                        x-frame-options          "sameorigin";
                add_header                        x-xss-protection        "1; mode=block";
                add_header                        x-content-type-options        "nosniff";

                root                            /usr/local/www/horde;
                index                              index.php;

                charset utf8;

                access_log  <logfile>;[/INDENT]

[INDENT]                if ($bad_client) { return 403; }

                location / {
                        location /Microsoft-Server-ActiveSync {
                                alias                   /usr/local/www/horde/rpc.php;
                                fastcgi_split_path_info ^(.+.php)(/.+)$;
                                fastcgi_keep_conn       on;
                                include                 fastcgi_params;
                                fastcgi_param           SCRIPT_FILENAME /usr/local/www/horde/rpc.php;
                                fastcgi_pass            unix:/var/run/php.fcgi;
                        }

                        location /autodiscover/autodiscover.xml {
                                alias                   /usr/local/www/horde/rpc.php;
                                fastcgi_split_path_info ^(.+.php)(/.+)$;
                                fastcgi_keep_conn       on;
                                include                 fastcgi_params;
                                fastcgi_param           SCRIPT_FILENAME /usr/local/www/horde/rpc.php;
                                fastcgi_pass            unix:/var/run/php.fcgi;
                        }

                        location /Autodiscover/Autodiscover.xml {
                                alias                   /usr/local/www/horde/rpc.php;
                                fastcgi_split_path_info ^(.+.php)(/.+)$;
                                fastcgi_keep_conn       on;
                                include                 fastcgi_params;
                                fastcgi_param           SCRIPT_FILENAME /usr/local/www/horde/rpc.php;
                                fastcgi_pass            unix:/var/run/php.fcgi;
                        }

                        location ^~ /(static|themes)/ {
                                expires                 1w;
                                add_header              Cache-Control public;
                        }[/INDENT]

[INDENT]                        location ^~ /services/ajax.php {
                                fastcgi_split_path_info ^(.+.php)(/.+)$;
                                fastcgi_keep_conn       on;
                                include                 fastcgi_params;
                                fastcgi_param           SCRIPT_FILENAME $document_root$fastcgi_script_name;
                                fastcgi_pass            unix:/var/run/php.fcgi;
                        }

                        location ~ .php {
                                # Zero-day exploit defense.
                                # http://forum.nginx.org/read.php?2,88845,page=3
                                # Won't work properly (404 error) if the file is not stored on this server, which is entirely possible with php-fpm/php-fcgi.
                                # Comment the 'try_files' line out if you set up php-fpm/php-fcgi on another machine.  And then cross your fingers that you won't get hacked.
                                try_files $uri =404;

                                fastcgi_split_path_info ^(.+.php)(/.+)$;
                                fastcgi_keep_conn       on;
                                fastcgi_index           index.php;
                                include                 fastcgi_params;
                                fastcgi_param           SCRIPT_FILENAME $document_root$fastcgi_script_name;
                                fastcgi_pass            unix:/var/run/php.fcgi;
                        }

                        try_files                          $uri $uri/ /rampage.php?$args;
                }[/INDENT]

[INDENT]        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
                root   /usr/local/www/nginx-dist;
        }

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
                location ~ /.ht {
                        deny all;
                }
                location ~ /(config|lib|locale|po|scripts|templates)/ {
                        deny all;
                }
                location ^~ /rpc/ {
                        if (!-e $request_filename){
                                rewrite ^(.*)$ /rpc/index.php/$1 break;
                        }
                }
                location ^~ /kronolith/feed/ {
                        if (!-e $request_filename){
                                rewrite ^(.*)$ /kronolith/feed/index.php?c=$1 break;
                        }
                }[/INDENT]

[INDENT]                location ^~ /content/ {
                        if (!-e $request_filename){
                                rewrite ^(.*)$ /content/index.php break;
                        }
                }
                location ^~ /whups/(queue|query)/ {
                        if (!-e $request_filename){
                                rewrite ^/([0-9]+)/?$ /whups/queue/index.php?id=$1;
                        }
                        rewrite ^/([0-9]+)/rss/?$ /whups/queue/rss.php?id=$1;
                        rewrite ^/([a-zA-Z0-9_]+)/?$ /whups/queue/index.php?slug=$1;
                        rewrite ^/([a-zA-Z0-9_]+)/rss/?$ /whups/queue/rss.php?slug=$1;
                }
                location ^~ /whups/ticket/ {
                        if (!-e $request_filename){
                                rewrite ^/([0-9]+)/?$ /whups/ticket/index.php?id=$1;
                        }
                        rewrite ^/([0-9]+)/rss/?$ /whups/ticket/rss.php?id=$1;
                        rewrite ^/([0-9]+)/([a-z]+)(.php)?$ /whups/ticket/$2.php?id=$1 break;
                }
                location ^~ /.well-known/carddav {
                        return 301 https://webmail.Leidinger.net/rpc.php;
                }
                location ^~ /admin/ {
                        allow <local>;
                        deny all;
                }
                location ~ /test.php$ {
                        allow <local>;
                        deny all;
                }

                # Media: images, icons, video, audio, HTC, archives
                location ~* .(?:jpe?g|gif|png|ico|cur|gz|bz2|tbz|tgz|svg|svgz|mp4|ogg|ogv|webm|htc|css|js|pdf|zip|rar|tar|txt|pl|conf)$ {
                        try_files $uri =404;

                        expires 1w;
                        access_log off;
                        add_header Cache-Control "public";
                }
        }
}[/INDENT]

Share/Save

Related Posts:

xL5KKGWVOlY


Continue reading...
 
Status
Not open for further replies.
Back
Top