Switching to nginx and php-fpm, so LAMP becomes LEMP

About two and a half years ago i ordered a virtual server for private purposes at Server4you. That was quite a long time ago and in the meantime you can get the same server for less money or a better server for the same price 😉
As migrating from an old productline to a new one isn’t possible at Server4you I decided to order a new server and migrate all my services to it so that i can quit the old machine afterwards.

And here we go:
LAMP (Linux, Apache, MySQL and PHP) is quite common and i also used this setup (Apache with mod_php) for hosting some small websites on my old server. The planned migration made me think about alternatives and I crawled through many blogposts about NGINX – a webserver which gains more and more popularity in our days (see this survey for more details).
Therefor i decided to give it a try and that’s where LEMP comes from (NGINX is pronounced as Engine-X)

Another new thing i wanted to try out is the integration of PHP in a different way. A project called PHP-FPM (FastCGI Process Manager) adds some new features to the ’normal‘ FastCGI implementation. It’s more or less a patch for the PHP sourcecode and it seems like it will go directly to the PHP core with PHP version 5.3.3.

After a bit of compilation and writing some scripts to automate this for future use all the websites (mostly WordPress) run on my LEMP setup. To get SEO-friendly URLs with WordPress on nginx is a bit more tricky than before, because .htaccess files are not beeing parsed by nginx, but the effort is really worth it.

Here is a related snippet from my nginx configuration file for this blog (slightly modified):

server {
listen 80;
server_name www.schmalenegger.com;

access_log /logs/schmalenegger.com_access.log;
error_log /logs/schmalenegger.com_error.log;

location / {

root /var/www/schmalenegger.com/;
index index.php index.html;

# Basic version of WordPress parameters, supporting nice permalinks.
include /etc/nginx/wordpress_params.regular;
}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9999;
fastcgi_index index.php;
include /etc/nginx/fastcgi_params;
include /etc/nginx/fastcgi_params.default;
fastcgi_param SCRIPT_FILENAME /var/www/schmalenegger.com/$fastcgi_script_name;
}
}

And this is the content from /etc/nginx/wordpress_params.regular:

# WordPress pretty URLs:
if (-f $request_filename) {
break;
}
if (-d $request_filename) {
break;
}
rewrite ^(.+)$ /index.php?q=$1 last;

To be honest, I didn’t measure the differences between the performances of both setups, but I can really feel, that the webpages are being loaded much faster than before and also the memory consumption of nginx is absolutly awesome. So I’m quite happy with this new setup, but sometimes there are still some pitfalls to deal with.

Recovering a lost root password for MySQL

Once in a while (hopefully not to often) you need to recover the root password of a mysql database. Here is a quick guide how I do this normally:

1. Stop the running database (if it isn’t stopped already)
/etc/init.d/mysql stop
2. Start the database with the ’skip-grant-tables‘ option
mysqld_safe –skip-grant-tables &
3. Open the mysql console
mysql -u root
4. Set a new password for root (replace yournewpassword with a password of your choice)
mysql> UPDATE user SET Password=PASSWORD('yournewpassword') WHERE user = 'root';
5. Make the changes work immediately
mysql> FLUSH PRIVILEGES;
6. Stop the database again
kill /path/to/mysql.pid || killall mysqld
7. Start it up again the usual way
/etc/init.d/mysql start

That’s it 🙂

Connecting to MSSQL databases with PHP from Linux

I needed to get some data from existing MSSQL databases with PHP. Connecting to such servers is a bit more tricky than mysql, because the mssql extension from php needs also a correctly configured TDS installation. But we’re lucky, there is an opensource implementation of the tds protocoll called FreeTDS. If you don’t want to use tds you can also try to get it to work with ODBC, but ODBC is very slow and that’s why it’s also not part of this blog post.

So here we go…

1. Installation of FreeTDS:
– Get the latest release of FreeTDS from here: http://freetds.org/ (the time i write this it’s 0.82)
– Extract and compile it:

tar xzvf freetds-stable.tgz
cd freetds-0.82/
./configure --prefix=/opt/freetds --with-tdsver=8.0
make
make install

– Edit /opt/freetds/etc/freetds.conf and add your MSSQL server like this:

[MSSQLserver]
host = hostname or ip
port = 1433
tds version = 8.0

MSSQLserver is used in your php code afterwards, so it might be a good idea to think of an appropriate name.

2. Installation of PHP
– Get the latest release of PHP from here: http://www.php.net/downloads.php
– Extract and compile it:

tar xjvf php-5.3.0.tar.bz2
cd php-5.3.0/
./configure --prefix=/opt/php --with-apxs2 --with-mssql=/opt/freetds
make
make install

This is a very limited version of PHP just to show the required options in order to get PHP to work with MSSQL. If you have additional requirements like mysql-support or gd processing stuff you need to add those options to the configure call.

After that you need to tell Apache to load the appropriate module (libphp5.so). Add the following line to your httpd.conf file:

LoadModule php5_module /usr/lib/httpd/modules/libphp5.so

The location of the module may vary.

If everything went fine, you can now start to ‚CRUD‘ your MSSQL data. Have fun…

NIC bonding (aka NIC teaming) with Debian Lenny

In order to move our Nagios installation from a virtual server to a dedicated hardware machine i installed Debian Lenny on a HP Proliant DL 380 G5. This server has two integrated NICs which can easily be used together as a network bond. So if one way to or from the server failes, the machine is still available through the other card.

All the necessary requirements such as the bonding module and stuff are available in the debain standard kernel (the time i wrote this: 2.6.26-2-amd64)

What’s still left to do is to install the ifenslave package:

apt-get install ifenslave-2.6

and to modify some configuration files
/etc/modprobe.d/arch/i386 or /etc/modprobe.d/arch/i386 (depending on your architecture):

alias bond0 bonding
options bonding mode=1 miimon=100 downdelay=200 updelay=200

Mode 1 (also called: active-backup) means, that only one interface is active. The other one comes only into play, when the first (active) card fails. So this mode is only for fault tolerance and not for loadbalancing, but the configuration of this mode is very simple, because it doesn’t require additional switch configuration.

Edit /etc/network/interfaces and configure the bond0 interface:

auto bond0
iface bond0 inet static
address 10.10.0.25
netmask 255.255.255.0
gateway 10.10.0.1
up /sbin/ifenslave bond0 eth0 eth1
down /sbin/ifenslave -d bond0 eth0 eth1

Don’t configure any additional network settings for eth0 and eth1!

For testing purposes you can now load the bonding module (will also be done automatically when the servers boots):

modprobe bonding

and restart your network:

/etc/init.d/networking restart

Now you should be able to ping the server from another host and plug/unplug the cables of the two integrated NICs while the server always answers the ping requests.

Terminal not fully functional when using rxvt-unicode-256color

After reading some interesting articles about rxvt-unicode (often called urxvt) I wanted to try it out myself on my Archbox. Installation is quite simple via pacman and further customization can be done be modifying the .Xdefaults fine in your home directory.

If you install the rxvt-unicode-256color package the TERM variable will be set to rxvt-256color and that’s a problem when connecting to the debian boxes, because the ncurses package does not have a valid entry for this under /lib/terminfo.
When using less, man and I assume some other tools too, you’ll get the following error message:


WARNING: terminal is not fully functional
- (press RETURN)

To avoid this, you can add the following line to your .bashrc file in your home folder to set the TERM variable to rxvt-unicode which is included in the debian ncurses package:


case "$TERM" in
rxvt-256color)
TERM=rxvt-unicode
;;
esac

Check installed gems via „gem server“

If you quickly want to check which gems you’ve installed via rubygems you can start the integrated gem server by invoking hte following command:


gem server

After that step fire up you browser and got to http://localhost:8808

You should see something like this:

Installed gems seen via "gem server"

Tunneling Rsync through SSH for ABS updates

As I told on my previous post I’m currently using Archlinux here at work. Archlinux has beside it’s ’normal‘ package management system pacman (similar to apt-get) a ports-like application-repository called the ‚Arch Build System‘ (ABS).

In order to use the ABS software repository and to be able to install software from it, you need to sync the whole package tree to your local disk. This doesn’t contain the full packages with all tarballs and stuff – it’s only some Meta-information. The necessary files needed for a package installation will be downloaded on request when installing the software.

Updating the ABS-tree is being done by rsync. The problem is that I don’t have the possibility to connect to the internet by something other the http(s) and ssh, but I haven’t found a solution yet to tell abs to use rsync over ssh for this step.

So my workaround for this is the following:

– Tunnel the rsync requests to the Arch servers via ssh (this needs root priviledges)

ssh -l johndoe -L 873:rsync.archlinux.org:873 yoursshserver.cooldomain.com

– Edit /etc/abs.conf and replace the value for SYNCSERVER with ‚localhost‘

– Run abs

It’s working very fine, but I have to admit that you need a ssh-server to connect to in the internet or at least a linux-box (of course any other ssh-able server will fit too) accesible via dyndns.

Speeding up Arch Linux

Currently I’m using Arch Linux on my desktop-machine at work. As I’m still at the evaluation phase i read trough some forums, wikis and blogs about Arch Linux.
One very interesting article I found was this one: http://www.cywhale.de/arch-linux-optimieren-booten-in-16-sekunden/
It describes how the booting time can be speeded up with some nice tricks. I did not all steps described there, but only the few changes i made saved me 19 seconds and my arch-machine now boots to the KDE logon-screen in 13 seconds.

Before the optimization:

bootchart_slow

After:

bootchart

Migration finished

As I wrote in the last post i was thinking about migrating back to wordpress. The steps are almost done. I don’t use categories anymore and the few links i had were added manually after the db-migration. What’s still left to do is to look for a nice theme and install some nifty plugins.

Thoughts about migrating (back) from Drupal to WordPress

Here’s something I found on this webpage related to a Drupal2Wordpress database migration:

prerequisites:

  • A fresh and clean installation of WordPress
  • Drupal database name: drupal (no table-suffix)
  • WordPress database name: wordpress (table-suffix ‚wp_‘)

Fire up the mysql cli:

USE wordpress;
DELETE FROM wp_posts ;
DELETE FROM wp_comments;
INSERT INTO wp_posts( ID, post_author, post_date, post_content, post_title, post_excerpt, post_name, post_modified )
SELECT a.nid, 1, FROM_UNIXTIME(a.created), b.body, a.title, b.teaser, concat('OLD',a.nid), FROM_UNIXTIME(a.changed)
FROM drupal.node as a, drupal.node_revisions as b
WHERE a.nid = b.nid AND (a.type='blog' OR a.type='page' OR a.type='story' OR a.type='forum');
INSERT INTO wp_comments ( comment_post_ID, comment_date, comment_content, comment_parent )
SELECT nid, FROM_UNIXTIME(timestamp), concat(subject,' ', comment), thread FROM drupal.comments ;

For the last part I wrote a perl-script, because the statement needs to iterate over all posts and calculate the related amount of comments. For getting this to work the user who runs the script needs to be able to login without a password to mysql. This can e.g. be achieved by a .my.cnf file in the home directory of the user.

#!/usr/bin/perl

@postids = echo "select ID from wp_posts" | mysql wordpress;

foreach (@postids) {
if ($_ == "ID") { next }
print $_;
system "echo 'UPDATE wp_posts SET comment_count = (SELECT count(*) from wp_comments where comment_post_ID = $_) where ID = $_;' | mysql wordpress";
system "echo 'SELECT comment_count from wp_posts where ID = $_;' | mysql wordpress";
}

I wrote this in a very short amount of time and I know it’s very dirty, but it works 🙂

Things that are still missing:

  • User migration
  • Post and Comment Formating
  • Categories