To optimize the performance of our discoverize portals we decided to try out the PageSpeed Module. Since we already have a little experience with NGINX, we decided to install NGINX(version 1.8.0) with the PageSpeed Module (version on our CentOS 6 and CentOS 7 servers.


  1. use guide: https://developers.google.com/speed/pagespeed/module/build_ngx_pagespeed_from_source
    1. ngx_pagespeed was not saved as .zip file, but without file extension – adjust the unzip command accordingly
    2. if needed add other modules to the NGINX configuration before installing NGINX, for instance the ngx_http_ssl_module:
        ./configure --add-module=$HOME/ngx_pagespeed-release-${NPS_VERSION}-beta --with-http_ssl_module
    3. If you install with the http_ssl_module you may have to install OpenSSL libraries first. yum install openssl will probably not suffice, yum install openssl-devel will be needed (you may wonder why ./configure states that OpenSSL is not available even though it is installed – what it really needs is openssl-devel).
    4. if only over-installing nginx, do not forget to restart the nginx service (reload will do nothing)
  2. create NGINX init script: https://www.nginx.com/resources/wiki/start/topics/examples/redhatnginxinit/
    1. adjust folder paths in that script:
      1. nginx="/usr/local/nginx/sbin/nginx" (line 22)
      2. NGINX_CONF_FILE="/usr/local/nginx/conf/nginx.conf" (line 25)
    2. give init script sufficient rights: rwxr-xr-x
  3. create log rotation script: http://www.scalescale.com/tips/nginx/how-to-rotate-nginx-logs/


There is no uninstall parameter in make for NGINX. Just remove the folders and files: sudo rm -f -R /usr/local/nginx && rm -f /usr/local/sbin/nginx && rm -rf /etc/init.d/nginx


  1. configure NGINX as proxy for web site
    1. there are many guides out there, for instance: https://www.nginx.com/resources/admin-guide/reverse-proxy/
    2. proxy_set_header has to be set, so backend server knows which application should reply
    3. proxy_http_version has to be set to 1.1 – otherwise only parts of page may be transferred
  2. enable the module: https://developers.google.com/speed/pagespeed/module/configuration
    1. use tmpfs for the caching folder: https://developers.google.com/speed/pagespeed/module/faq#tmpfs 
  3. configure filters for PageSpeed Module: https://developers.google.com/speed/pagespeed/module/config_filters
    1. let PageSpeed take care of compressing the response: do not activate gzip, PageSpeed will automatically configure it

    2. try out the filters which are not automatically enabled with the RewriteLevel CoreFilters

All in all it is not an easy task to get the PageSpeed Module working, but in the end it is surely easier and faster to let it optimize your web site responses instead of implementing all the different optimizations.

Since our backend server are Windows server we briefly considered using the IISpeed wrapper for the PageSpeed Module, but went with NGINX. Maybe IISpeed is easier to install and to configure. If you have experience using IISpeed, I would like to read a comment about ist usability.


I had another small odyssey when I transferred our TeamCity installation to our new server.

Without an external database

If you are not using an external database the process is pretty easy:

  1. Use the UI to backup the TeamCity data
  2. Install TeamCity on the new server
  3. Copy the backup data to the new TeamCity Data Directory (usually "C:\ProgramData\JetBrains\TeamCity")
  4. Set the projects from hidden to visible in the administration area.

With an external database

If you, like we, use an external SQL database for TeamCity the migration is a totally different ball game.

  1. I backed up the data again with the UI like above.
  2. For restoring I used this documentation.

I ran into a few problems:

  • It was imperative to not startup the site before running the maintainDB command.
  • I needed to allow TCP/IP connections to the SQL instance.
  • I had some problems with my Java installation (ClassNotFoundException jdbc.SQLServerDriver - it seemed the additional 32bit installation caused the problems). These two articles helped me.
  • I also ran into some problems to get the TeamCity projects on the new server running:
    • I had to adjust the MSBuild versions.
    • For npm I had to manually create a folder because of a ENOENT error.
    • For grunt I had to add C:\Users\[username]\AppData\Roaming\npm to global PATH, and execute “npm install -g grunt-cli” there.


Don’t do it! Ok, do it, but only if it is really necessary. (You will probably run into a lot of problems!)

Our old server started to get old. The processor chip, RAM and HDD was outdated. We ordered a new server which is faster, has more RAM and a SSD. On our new server Monitoring is faster, TeamCity configurations run faster, web sites are being delivered faster, and the server UI is much more responsive. In the end the server change was good, but the move took quite some time!

We moved from a Windows Server 2008 R2 with IIS 7.5 to a Windows Server 2012 R2 with IIS 8.5.

Approach One: move data and configuration separately

This did not work for me this time. You copy all the data in the wwwroot directory to the new server. Then you export the IIS configuration on the old server and import it on the new server. There are a few blog posts talking about this. But you may corrupt your IIS configuration like I did. Make sure to backup the initial configuration to be able to restore it. IIS also has a history itself (C:\inetpub\history). If all fails you will have to uninstall the IIS feature and install it anew.

Approach Two: move data and configuration together

You can use Web Deploy to move all your sites and their IIS configuration to the new server (needs to be installed on both servers). I first tried it using the UI, but always ran into problem when importing. Command line syntax to the rescue! It gave me better error feedback. The command I used at the end:

C:\Program Files\IIS\Microsoft Web Deploy V3>msdeploy.exe -verb:sync -source:package=C:\_backups\IIS\IIS_PA1.zip,machineconfig32.netfxversion=2,machineconfig64.netfxversion=2,rootwebconfig32.netfxversion=2,rootwebconfig64.netfxversion=2,encryptPassword=teamaton -dest:webserver,machineconfig32.netfxversion=2,machineconfig64.netfxversion=2,rootwebconfig32.netfxversion=2,rootwebconfig64.netfxversion=2

Here you can read more about the sync verb, provider package and webserver, and encryptPassword.

Here are the problems I ran into, and how I circumvented them:

  • Dynamic IP Restrictions module is an extension in IIS 7.5, but a feature in IIS 8.5 (Web Server –> Security –> “IP and Domain Restrictions”). Therefore I needed to uninstall the extension on IIS 7.5 and only then export with Web Deploy.
  • Frameworks do not match: "The versions of the .NET Framework Configuration Provider (machineConfig64) are different on the source (2.0) and destination (4.0)." Phu, this was a tough one – I tried very many things unsuccessfully. In the end I used option 1 in this article, because option 2 never worked – even though most proposed solutions on the internet use this option 2.
  • Then I ran into the error 0x800f0922 which I fixed with this solution.
  • As usual I ran into the error “Service unavailable” after the import. This is usually an indicator that some feature is missing in the IIS. I needed to install the URL Rewrite Module.
  • A few DLLs were missing on the target machine. I had to compare the machine.configs and adjust them as needed.

Problems with WordPress web site

First I tried to transfer the WordPress blog like the other sites. Move its IIS configuration, the wwwroot folder and its MySQL database. That did not give me the desired result, and gave me quite a few headaches:

  • Web Deploy makes changes to .NET Framework config files (for instance machine.config and web.config) – I had to copy them from other server.
  • Using the PHP Manager for IIS did not help.
  • FastCGI could not be loaded because of version problems.

Probably the best way to migrate a WordPress site is using the Duplicator extension. Just two caveats: you will need to give USERS folder rights (other sites usually need rights to be given to IIS_IUSRS). And “Select Advanced Options and select the manual unzip process“ should be done in step 1 of “Run the Duplicator Installer”.

Migrate SQL databases

We migrated from SQL Server 2008 to SQL Server 2014. First thing I forgot was to ensure that the new instance is installed with “Mixed Authentication” (it allows Windows + SQL logins). I copied the databases according to this article. I only changed the level to 120, which corresponds to SQL Server 2014. Then I had to copy users with their passwords. I did it by creating a procedure.

One of our TeamCity configurations runs unit tests based on Entity Framework 6.0. It need to be able to create a database on the fly, but I always got System.Data.SqlClient.SqlException : CREATE DATABASE permission denied in database 'master'. Turns out the login NT AUTHORITY\SYSTEM needs the dbcreator Server Role.