Pylons and nginx

Check out the new site at https://rkblog.dev.

Edit project *ini file (developement.ini by default) and change [server:main] to:
[server:main]
use = egg:PasteScript#flup_fcgi_thread
host = 0.0.0.0
port = 8080
- If you don't have flup then install it:
easy_install flup
- Edit /etc/nginx/nginx.conf to something like this:
user  apache apache;

worker_processes  2;

error_log /var/log/nginx/error_log info;

events {
	worker_connections  1024;
	use epoll;
}

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

	log_format main
		'$remote_addr - $remote_user [$time_local] '
        	'"$request" $status $bytes_sent '
		'"$http_referer" "$http_user_agent" '
		'"$gzip_ratio"';

	client_header_timeout	10m;
	client_body_timeout	10m;
	send_timeout		10m;

	connection_pool_size		256;
	client_header_buffer_size	1k;
	large_client_header_buffers	4 2k;
	request_pool_size		4k;

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

	output_buffers	1 32k;
	postpone_output	1460;

	sendfile	on;
	tcp_nopush	on;
	tcp_nodelay	on;

	keepalive_timeout	75 20;

	ignore_invalid_headers	on;
	index index.html;

	server {
		listen 80;
		server_name localhost;
		location / {
			# host and port to fastcgi server
			fastcgi_pass 127.0.0.1:8080;
			fastcgi_param PATH_INFO $fastcgi_script_name;
			fastcgi_param REQUEST_METHOD $request_method;
			fastcgi_param QUERY_STRING $query_string;
			fastcgi_param CONTENT_TYPE $content_type;
			fastcgi_param CONTENT_LENGTH $content_length;
			fastcgi_param  SERVER_ADDR        $server_addr;
			fastcgi_param  SERVER_PORT        $server_port;
			fastcgi_param  SERVER_NAME        $server_name;
			fastcgi_param  SERVER_PROTOCOL    $server_protocol;
			fastcgi_pass_header Authorization;
			fastcgi_intercept_errors off;
			}
		access_log	/var/log/nginx/localhost.access_log main;
		error_log	/var/log/nginx/localhost.error_log;
		}
	}
}
Where non default is this part:
location / {
# host and port to fastcgi server
fastcgi_pass 127.0.0.1:8080;
fastcgi_param PATH_INFO $fastcgi_script_name;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_pass_header Authorization;
fastcgi_intercept_errors off;
}
fastcgi_pass 127.0.0.1:8080; - paster fastcgi is running on port 8080/localhost.
- Done, launch paster and nging:
paster serve --reload development.ini 
/etc/something/nginx start
- http://localhost/ should show you your pylons project

Reverse Proxy and Pylons

To use nginx as a reverse proxy / load balancer we need a pylons application up and running on a normal server (developement server, pylons+fastcg+cherokee/lighttpd etc.). And we have to be able to launch few processes on different ports for the same application. For example we will use pylons default server.
- Edit developement.ini and copy [server:main] and [app:main] with their settings as [server:main2] and [app:main2]. Change port for the second one. Example:
[server:main]
use = egg:Paste#http
host = 0.0.0.0
port = 8080

[app:main]
dsn = sqlite://@localhost/termdb
use = egg:searchengine
myghty_data_dir = %(here)s/data/templates
cache_data_dir = %(here)s/data/cache
session_data_dir = %(here)s/data/sessions
session_key = searchengine
session_secret = somesecret

[server:main2]
use = egg:Paste#http
host = 0.0.0.0
port = 8081

[app:main2]
dsn = sqlite://@localhost/termdb
use = egg:searchengine
myghty_data_dir = %(here)s/data/templates
cache_data_dir = %(here)s/data/cache
session_data_dir = %(here)s/data/sessions
session_key = searchengine
session_secret = somesecret
Edit /etc/nginx/nginx.conf to:
user  apache apache;

worker_processes  2;

error_log /var/log/nginx/error_log info;

events {
	worker_connections  1024;
	use epoll;
}

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

	log_format main
		'$remote_addr - $remote_user [$time_local] '
        	'"$request" $status $bytes_sent '
		'"$http_referer" "$http_user_agent" '
		'"$gzip_ratio"';

	client_header_timeout	10m;
	client_body_timeout	10m;
	send_timeout		10m;

	connection_pool_size		256;
	client_header_buffer_size	1k;
	large_client_header_buffers	4 2k;
	request_pool_size		4k;

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

	output_buffers	1 32k;
	postpone_output	1460;

	sendfile	on;
	tcp_nopush	on;
	tcp_nodelay	on;

	keepalive_timeout	75 20;

	ignore_invalid_headers	on;
	index index.html;

 upstream pylons {
        server 127.0.0.1:8080;
        server 127.0.0.1:8081;
    }

	server {
		listen 80;
		server_name localhost;
		location / {
			proxy_pass  http://pylons;
			proxy_redirect  default;
			}
		access_log	/var/log/nginx/localhost.access_log main;
		error_log	/var/log/nginx/localhost.error_log;
		}
	}
}
There are two interesting elements:
 upstream pylons {
        server 127.0.0.1:8080;
        server 127.0.0.1:8081;
    }
 upstream LABEL {
        server IP:PORT;
        server IP:PORT;
        server IP:PORT;
    }
Upstream defines set of servers on which the requests will be split. In our basic setup we have one cherokee, running on port 8000. Next we have:
location / {
	proxy_pass  http://pylons;
	}
location / {
	proxy_pass  http://LABEL;
	}
Will redirect the trafic on / to set of servers defined in one of upstream blocks.
- Start pylons servers:
paster serve --reload development.ini
paster serve --reload development.ini --server-name=main2
- Start nginx and visit http://localhost/ - your site should run without any problems.
RkBlog

Web development, 14 July 2008


Check out the new site at https://rkblog.dev.
Comment article
Comment article RkBlog main page Search RSS Contact