Migration from Apache to Nginx

 

11-Jan-2012: initial release.
18-Jan-2013: adjusted for Slackware

 

Introduction.

Nginx is the second most used web server and it’s market share is still increasing. It has a different design then the most used Apache server. Because of that it is faster and can handle more load. There is no article about the Apache server on this site, but I assume you have a running Apache server and want to switch to Nginx. In this article I will explain how to do this migration. If you only have one single server, you can skip a lot of steps here, all these steps are only useful if you don’t want possible long downtimes on your server.

The steps to migrate your web server are:

  1. Install fcgiwrap, spawnfcgi, fcgi and nginx.
  2. Copy virtual hosts setup to port 81.
  3. Start new servers and test.
  4. Proxy the virtual hosts with Apache.
  5. Adjust other software.
  6. Final switch.
  7. Cleanup.

This procedure is written on a Slackware system, but the migration process is the same on any system. There are just small differences in package names, script and path names etc.

 

1. Install fcgiwrap, spawn-fcgi, fcgi and nginx.

On a normal Apache web server you will most likely already have PHP and MySQL installed. When you migrate from Apache to Nginx you should not need to change anything in these two packages. Besides the nginx server package, you may need to install the fcgiwrap packages. You need the standard php package if you use PHP somewhere, and fcgiwrap, fcgi and spawn-fcgi if you have CGI scripts. Look at the other articles how to configure php-fpm.

[important]My nginx package uses /etc/rc.d/rc.httpd as init script just as in the original httpd package. So before you install the nginx package, rename rc.httpd (Apache version) to rc.httpd.apache. Or if you don’t do that, after nginx is installed the nginx init script is called /etc/rc.d/rc.httpd.new. Whatever you do, make sure you have them both during the migration process.[/important]

 

 

2. Copy virtual hosts setup to port 81.

The complete configuration details for both web server packages will not be discussed here, see the official documentation for that. Next is just an example of a Apache virtual host:

# fido.mbse.eu
#
<VirtualHost [2001:1af8:feb8:7e95::202]:80 0.0.0.0:80>
    ServerAdmin webmaster@mbse.eu
    DocumentRoot /srv/http/fido
    ServerName fido.mbse.eu
    ErrorLog /var/log/httpd/fido_error.log
    CustomLog /var/log/httpd/fido_access.log combined
    <Directory /srv/http/fido>
        DirectoryIndex index.html index.htm
        Options Indexes FollowSymLinks
        Order deny,allow
        Allow from all
    </Directory>
</VirtualHost>

And this is the same host configured in nginx:

    # fido.mbse.eu
    #
    server {
        listen          [2001:1af8:feb8:7e95::202]:81;
        listen          10.126.149.3:81;
        listen          [::1]:81;
        listen          127.0.0.1:81;
        server_name     fido.mbse.eu;
        error_log       /var/log/nginx/fido_error.log;
        access_log      /var/log/nginx/fido_access.log main;
        root            /srv/http/fido;

        location / {
            index       index.html index.htm;
        }
    }

Note that I also let the server listen on the localhost addresses, we need that for step 4.

 

3. Start new server and test.

All the virtual hosts are configured to listen to port 81 instead of the usual port 80. We can now start the new server and test it.

root@web04:~# /etc/rc.d/init.d/fcgiwrap start
Starting fcgiwrap for user: apache
root@web04:~# /etc/rc.d/rc.php-fpm start
Starting php-fpm  done
root@web04:~# /etc/rc.d/rc.httpd.new start
Starting Nginx server daemon...
root@web04:~#

 

In your browser use url’s like http://www.mbse.eu:81 to connect to port 81. Note that you might need to open port 81 in your firewall if you want to test this from the Internet. I would only test from your internal network, the next step allows testing from the Internet without a firewall change.

 

4. Proxy the virtual hosts with Apache.

Apache still listens on port 80 for all our virtual hosts and we keep that so for a while. The next step is to configure Apache so that it will reverse proxy each virtual host to the nginx server. So, Apache just acts as a gateway and nginx will serve the pages. First make sure that proxy support is enabled in Apache, in /etc/httpd/conf/httpd.conf enable the next lines:

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
LoadModule proxy_http_module modules/mod_proxy_http.so

 

Now change one virtual host in /etc/httpd/conf/extra/httpd-vhosts.conf  from:

# fido.mbse.eu
#
<VirtualHost [2001:1af8:feb8:7e95::202]:80 0.0.0.0:80>
    ServerAdmin webmaster@mbse.eu
    DocumentRoot /srv/http/fido
    ServerName fido.mbse.eu
    ErrorLog /var/log/httpd/fido_error_log
    CustomLog /var/log/httpd/fido_access_log combined
    <Directory /srv/http/fido>
        DirectoryIndex index.html index.htm
        Options Indexes FollowSymLinks
        Order deny,allow
        Allow from all
    </Directory>
</VirtualHost>

to this:

# fido.mbse.eu
#
<VirtualHost [2001:1af8:feb8:7e95::202]:80 0.0.0.0:80>
    ProxyPass / http://localhost:81/
    ProxyPassReverse / http://localhost:81/
    ProxyPreserveHost On
    ProxyRequests off
    ServerName fido.mbse.eu
    ErrorLog /var/log/httpd/fido_error_log
    CustomLog /var/log/httpd/fido_access_log combined
</VirtualHost>

 

Next restart Apache:

root@web04:~# /etc/rc.d/rc.httpd.apache reload
Reloading Apache Web Server
root@web04:~#

 

Now the server http://fido.mbse.eu should be served by nginx and proxied by Apache. Test this from your internal network, but also from the Internet.

 

5. Adjust other software.

There are several packages that do things with web logfiles, they now point to /var/log/httpd and should be changed to /var/log/nginx. With our setup, the layout of all *access.log files are the same as Apache combined setting. The packages you might need to change are ossec, logwatch and webalizer.

If you use net-snmp and watch the running processes you need to remove httpd and add the new processes, for example use the following lines in /etc/snmp/snmpd.conf:

proc  php-fpm           50      2
proc  nginx             2       2
proc  fcgiwrap          1       1

 

If you have .htaccess files that do redirection to other url’s, you need to configure these into nginx.conf, for example:

rewrite ^(/files/local/)(.*)$ /files/$2 permanent;

 

On my fido site this rewrites http://fido.mbse.eu/files/local/somedir to http://fido.mbse.eu/files/somedir.

If you have things like webalizer, it is a good idea to let apache proxy for nginx for at least 24 hours so that the information in the logfiles won’t be interrupted. However, during this period in the nginx logfiles is the localhost ip written instead of the client ip address.

 

6. Final switch.

If everything works, make a backup of /etc/nginx/conf/nginx.conf and change the running config file to use port 80 instead of port 81. Then stop apache and reload nginx:

root@web04:~# /etc/rc.d/rc.httpd.apache stop
Stopping Apache Web Server
root@web04:~# /etc/rc.d/rc.httpd.new reload
Reloading Nginx configuration...
root@web04:~#

Now you should test every site again.

 

7. Cleanup.

Remove the apache package with the removepkg httpd command after a few days and the migration is complete. You should also make sure the nginx init script is now called rc.httpd.