Rewrite WordPress and ZenPhoto for Nginx

Web October 15th, 2008

Nginx also supports URL rewrite, not compatible to Apache’s mod_rewrite, but more intuitive and more powerful imho. The only problem is most applications, WordPress and ZenPhoto for this specific case do include the mod_rewrite code snippet and/or may update the .htaccess for your convenience.

Thanks to the Slicehost community, the port of mod_rewrite rules perfectly covers WordPress and SuperCache. Here are some minor modification to craft for more general usage:

# the blog dir, aka where index.php is
set $blog_dir ”;
# the wordpress dir where all wp-* stays
set $wordpress_dir ‘/wordpress’;
include wordpress.rewrite;

In nginx.conf, define wordpress_dir and blog_dir, these two variables are equivalent to WordPress address (URL) and Blog address (URL) stripped off the host information. Then we can replace the hard-coded /blog path by using $wordpress_dir or $blog_dir:

2d1
<
26c25
< set $supercache_file /blog/wp-content/cache/supercache/$http_host/$1index.html;
---
> set $supercache_file $wordpress_dir/wp-content/cache/supercache/$http_host/$1index.html;
36c35
< rewrite . /blog/index.php last;
---
> rewrite ^(.*)$ $blog_dir/index.php?q=$1 last;

Here is my zenphoto.rewrite, it seems sivel’s more concise. Either of these should work.

HOWTO: Serve virtual host with Nginx

Web September 6th, 2008

As the limited memory budget, and I plan to host multiple website in the VPS, I decided to take a less versatile, but lightweight Apache alternative, the Nginx made by the polar bear.

There is no RPM in the repository I have enlisted, so let’s fallback the old-school way:

# remove the blocking glibc-dummy-centos-4 package, then get the toolchain:
yum remove glibc-dummy-centos-4
yum -y install gcc openssl-devel
# Now it is time to build the nginx:
./configure –prefix=/opt/nginx –with-http_ssl_module –with-http_stub_status_module
make && sudo make install

Then get the PHP with FastCGI support, and the lighttpd-fastcgi for the fastcgi loader.

yum install php-cli php-mysql lighttpd-fastcgi

Here is the nginx.conf that server.

user nobody;
worker_processes 2;
pid logs/nginx.pid;
error_log logs/error.log;

events {
worker_connections 2048;
use epoll;
}

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

log_format main ‘$remote_addr - $remote_user [$time_local] $request ‘
‘”$status” $body_bytes_sent “$http_referer” ‘
‘”$http_user_agent” “$http_x_forwarded_for”‘;

access_log logs/access.log main;
client_header_timeout 3m;
client_body_timeout 3m;
send_timeout 3m;

client_header_buffer_size 1k;
large_client_header_buffers 4 4k;

gzip on;
gzip_min_length 1100;
gzip_buffers 4 8k;
gzip_types text/plain;
gzip_static on;

output_buffers 1 32k;
postpone_output 1460;

sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 75 20;

server {
#REVIEW: how to redirect https? using re?
server_name www.kunxi.org;
rewrite ^(.*) http://kunxi.org$1 permanent;
}

server {
# kunxi’s gallery
listen 80;
server_name gallery.kunxi.org;
root /home/webadmin/$host;
access_log logs/$host.log main;

location / {
root /home/webadmin/$host;
index index.html index.htm index.php;
include zenphoto.rewrite;
}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
}

# deny access to .htaccess files.
location ~ /\.ht {
deny all;
}
}

server {
# kunxi’s sites
listen 80;
server_name kunxi.org *.kunxi.org;
root /home/webadmin/$host;

error_page 404 $document_root/404.html;
error_page 500 502 503 504 $document_root/50x.html;
access_log logs/$host.log main;

location / {
root /home/webadmin/$host;
index index.html index.htm index.php;

# the blog dir, aka where index.php is
set $blog_dir ”;
# the wordpress dir where all wp-* stays
set $wordpress_dir ‘/wordpress’;

include wordpress.rewrite;
}

# rewrite the /files/
#
location /files/ {
alias /home/webadmin/static.kunxi.org/;
}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
}

# deny access to .htaccess files.
#
location ~ /\.ht {
deny all;
}
}
}

Some highlights of the configuration:
Rewrite www.kunxi.org to kunxi.org, yes, we support no-www!

server {
#REVIEW: how to redirect https? using re?
server_name www.kunxi.org;
rewrite ^(.*) http://kunxi.org$1 permanent;
}

And this wildcards will cover all sub-domains powered by PHP:

server_name kunxi.org *.kunxi.org;
root /home/webadmin/$host;
… ….

Home-brewed nginx and fastcgi init scripts to make it works after the reboot:

chkconfig –add nginx
chkconfig –add fcgi-php
service start nginx
service start fcgi-php

Tips and Traps:
Nginx supports 0 downtime upgrade, so if your nginx.conf is wrong, the server would ignore it and suck up the complain. Make sure stop the nginx service and start nginx during debugging rewrite rules.

fcgi-php seems to have problem to parse localhost, so I use 127.0.0.1 instead.

The rewrite rule for WordPress and ZenPhoto are explained here and here. (TODO).

Move to the new VPS, Yummy

Web September 4th, 2008

I finally ride the trend of VPS, yes, I just bought Economy VPS COS4×64 with 512M RAM, 200G HD and 350G bandwidth. The host is visualized via virtuozzo, and loaded with CentOS 4.4.

The package management of RPM is quite lacking, so the first thing is to get YUM working:

rpm -Uvh http://mirror.centos.org/centos/4/os/x86_64/CentOS/RPMS/yum-2.4.3-4.el4.centos.noarch.rpm
rpm -Uvh http://mirror.centos.org/centos/4/os/x86_64/CentOS/RPMS/python-elementtree-1.2.6-5.el4.centos.x86_64.rpm
rpm -Uvh http://mirror.centos.org/centos/4/os/x86_64/CentOS/RPMS/python-sqlite-1.1.7-1.2.1.x86_64.rpm
rpm -Uvh http://mirror.centos.org/centos/4/os/x86_64/CentOS/RPMS/sqlite-3.3.6-2.x86_64.rpm
rpm -Uvh http://mirror.centos.org/centos/4/os/x86_64/CentOS/RPMS/python-sqlite-1.1.7-1.2.1.x86_64.rpm
rpm -Uvh http://mirror.centos.org/centos/4/os/x86_64/CentOS/RPMS/python-urlgrabber-2.9.8-2.noarch.rpm
rpm -Uvh http://mirror.centos.org/centos/4/os/x86_64/CentOS/RPMS/yum-metadata-parser-1.0-8.el4.centos.x86_64.rpm
rpm -Uvh http://mirror.centos.org/centos/4/os/x86_64/CentOS/RPMS/yum-2.4.3-4.el4.centos.noarch.rpm
yum update

Since I have been spoiled by Gentoo’s portage, the upgrade of CentOS makes little sense to me: wipe off the disk, then reinstall the OS. The upgrade from CentOS 4 to CentOS is quite hair-rising, and I was scared off by the tech support. So I would stick to CentOS 4 right now.

The next step is to configure the repository:

wget -P /etc/yum.repos.d http://jpackage.org/jpackage.repo
wget -P /etc/yum.repos.d http://centos.karan.org/kbsingh-CentOS-Extras.repo
wget -P /etc/yum.repos.d http://centos.karan.org/kbsingh-CentOS-Misc.repo
wget -P /etc/yum.repos.d http://www.sipfoundry.org/pub/sipX/3.2/sipx-centos.repo
wget -P /etc/yum.repos.d http://dev.centos.org/centos/4/CentOS-Testing.repo

And manually add the following repos as well

# /etc/yum.repos.d/dag.repo
[dag]
name=Dag RPM Repository for Red Hat Enterprise Linux
baseurl=http://apt.sw.be/redhat/el$releasever/en/$basearch/dag
gpgcheck=1
enabled=1

# /etc/yum.repos.d/utterramblings.repo
[utterramblings]
name=Jason’s Utter Ramblings Repo
baseurl=http://www.jasonlitka.com/media/EL$releasever/$basearch/
enabled=1
gpgcheck=1
gpgkey=http://www.jasonlitka.com/media/RPM-GPG-KEY-jlitka

[dries]
name=Extra Fedora rpms dries - $releasever - $basearch
baseurl=http://ftp.belnet.be/packages/dries.ulyssis.org/redhat/el4/en/i386/dries/RPMS
gpgcheck=1
enabled=1

[atrpms]
name=Fedora Core $releasever - $basearch - ATrpms
baseurl=http://dl.atrpms.net/fc$releasever-$basearch/atrpms/stable
gpgkey=http://ATrpms.net/RPM-GPG-KEY.atrpms
gpgcheck=1enabled=1

Import the GPG keys as well:

rpm –import http://centos.karan.org/RPM-GPG-KEY-karan.org.txt
rpm –import http://dries.ulyssis.org/rpm/RPM-GPG-KEY.dries.txt
rpm –import http://dag.wieers.com/packages/RPM-GPG-KEY.dag.txt
rpm –import http://ATrpms.net/RPM-GPG-KEY.atrpms

And accelerate YUM by cache the meta data locally:

yum makecache

With YUM, it is much easier to start the engine.

Reverse mashup

Web September 3rd, 2008

I barely remember when was the last time I updated Gelman. This project starts as an exercise to practice my Django + dojo skills, and also to manage my eBook collection, I were stuck in UI design which I suck and the authentication/registration which I takes little interest in.

What if we take a different approach to avoid the reinvention of the wheel? Let’s take an online eBook management Web2.0 application, for example LibraryThing, to manage the Read, Reading, Wish to Read list, if an electronic copy is available, it will be inserted into the LibraryThing search/detail page, and we can add it to Reading list for quick access later. We just mashup our web service into LibraryThing!

This application can be decomposed to two parts:

  • A Web service to CRUD eBook collection hosted in home-brew server
  • Firefox Add-on or GreaseMonkey user script for mashup
  • A web service client to automate importing books
  • Find your favorite app, then mash it up!

A more portable solution to glue the pieces is to leave the mashup in the server side, using a proxy server to insert all the mashup data.

As all comments, tags, reading history has been hosted in the cloud, it is essential to do something against the raining day:

  • Big name may endorse the availability. I would seriously consider Shelfari only after it is acquired by Amazon
  • Open API is the key. This is the trend, the web site could not lock on the user by closing itself, the users may cold feet in the first place. Douban, the leader in the Chinese market, did an excellent job to open its platform.

I am working on an prototype of the RESTful web service using Django, stay in tune.

Ubiquity - Lowering the threshold for Web mashup

Web August 28th, 2008

Mozilla Lab recently released Ubiquity, it aims to lower the threshold for Web mashup. The following clips demonstrates how Ubiquity works in action:


Ubiquity for Firefox from Aza Raskin on Vimeo.

The 0.1 version is pretty much the prototype, but still quite inspiring. As more and more application have migrated from the desktop to the cloud, some may consider to replicate the OS to WebOS, others try to glue different pieces together to stop reinventing the wheel. Ubiquity takes the second approach, and seems quite promising.

As a die-hard command line user, I really love the simplicity of Ubiquity. And hopefully the following features may emerge later:

  • Wrap another command add prologue and epilogue, glue several commands together for a new functionality.
  • Pipe or we could do this in-place by using Pipe.
  • Drag-n-drop from the Ubiquity to the web page, and vice versa.
  • Nohup, fg, bg and screen full job controls for a quick response for BIG jobs, goes too far?

Any idea of new commands that make your life easier?