Nginx limit proxy Nginx module to create your own hosting service
Project hosted by
Get Nginx Limit Proxy at SourceForge.net. Fast, secure and Free Open Source software downloads

Example Content bellow can be also found in example.txt located in /doc/ directory of local and main serversource

Imagine you need to set following server:

you own domain my_domain.com, there you have movies.my_domain.com hosting static movies, application.my_domain.com hosting some dynamic content and some_name.my_domain.com hosting site for your user.

You want to set 30GB per month, 1GB per hour and 800mb per quarter for user downloading movies from movies.my_domain.com or using application.my_domain.com. additionally, you want to make sure that movies.my_domain.com wont eat more then 100GB per month.

For some_name.my_domain.com, you want him to use no more then 10mb/s of you total bandwidth.


First, you need to configure your nginx modules. Because you need traffic filtering, you will need both module and filter.

movies.my_domain.com need to have something to distinguish users. It doesn't matter, what it is, as long as you are able to set it into $limit_proxy_xuid variable.

Imagine we use ?id=123 as user index, and if it's not specyfied, -1 is used and underlying application will generate new user index and redirect.

In location configuration of nginx we would set:
	location ~ /* {
		set $limit_proxy_xuid "-1"; # default value (if not found)

		if ($query_string ~* "id=(\d+)" ) {
			set  $limit_proxy_xuid  $1; # if matched
		}

It is vital for $limit_proxy_xuid to have length smaller then 256 characters. Otherwise, it will be truncated.

You probably will need to write some autoredirect on nginx level to make sure that $limit_proxy_xuid is set to valid value.

Now, we set out module
		limit_proxy;
		limit_proxy_check_server_timeout 2000; #default timeout
		limit_proxy_check_server_ip 127.0.0.1; #default (local) ip
		limit_proxy_check_server_port 8002; #default port
		limit_proxy_connections_limit 1000; #no more then 1000 parallel connections
and filter
		traffic on;
		traffic_check_server_timeout 2000; #use same server as module
		traffic_check_server_ip 127.0.0.1;
		traffic_check_server_port 8002;


If you would like to use some module, set it before limit_proxy derective, for example:
	location ~ /* {
		#empty_gif;
		set $limit_proxy_xuid "-1";

		if ($query_string ~* "id=(\d+)" ) {
			set  $limit_proxy_xuid  $1;
		}

		proxy_pass http://backend;

		limit_proxy;
		limit_proxy_check_server_timeout 2000;
		limit_proxy_check_server_ip 127.0.0.1;
		limit_proxy_check_server_port 8002;
		limit_proxy_connections_limit 1000;

		traffic on;
		traffic_check_server_timeout 2000;
		traffic_check_server_ip 127.0.0.1;
		traffic_check_server_port 8002;
	}


For movies.my_domain.com we would need to set some traffic zone. In it's virtual server configuration, we can use something like this:
	location ~ /* {
		#empty_gif;
		set $limit_proxy_xuid "-1";

		if ($query_string ~* "id=(\d+)" ) {
			set  $limit_proxy_xuid  $1;
		}
		limit_proxy_traffic_zone 1 10m 0; #in zone "1", bandwidth is 10mb/s. Zero is unused

		limit_proxy;
		limit_proxy_check_server_timeout 2000;
		limit_proxy_check_server_ip 127.0.0.1;
		limit_proxy_check_server_port 8002;
		limit_proxy_connections_limit 1000;

		traffic on;
		traffic_check_server_timeout 2000;
		traffic_check_server_ip 127.0.0.1;
		traffic_check_server_port 8002;
	}


Now, we need to set local (limit) server. It should be set on same machine as nginx. If it's not, just set limit_proxy_check_server_ip and traffic_check_server_ip to other IP. Domain may not be used there.

In config of local server, you will need to set

	main_server_address "10.166.0.1" # IP (or domain) of main server
	main_server_port    8015 # and it's port
	
	local_server_name   "my_local_server_1" #need to be unique if you are using more then one local server
	local_server_port   8002 #same as port set in nginx limit_proxy_check_server_port/traffic_check_server_port


worker_threads 2 # total amount of worker threads. Should be about same as amount of CPU cores in your system.

Additionally, you may set logs or daemonize option

Then, we need to set master server.
	main_server_port    8015 # where should it bind, same as main_server_port from local servers
	rules_file "rules.txt" # from where should it load rules
	db_prefix "./db/" # where should it store databases. This directory must exists
	
	update_interval 300 # 5 minutes should be sufficient to synchronize database


Finally we need to set rules file. It will look like this:
	#	default policy, it will probably be never hit, just set it to 
	#	ALLOW without traffic zone

	*	*			ALLOW	255

	#	application.my_domain.com do not use bandwidth limit, but use total traffic limits.
	#	We also need to set garbage collection mechanizm. It will delete users 
	#	older then 5h. This parameter is important to undestand:
	
	#	If the user is not found in local database, he will be allowed and server will
	#	ask master server to fetch user data from hard drive. On the other hand,
	#	if you set timeout to very big value, your servers will probably consume
	#	huge amount of memory.

	
	*	"application.my_domain.com" CHECK 255 	5h	1g	100m	50m
	

	#	movies.my_domain.com must additionally check their total usage. 
	#	It will look like this:

	*	"movies.my_domain.com"  MIXED 	1	5h	30g	1g	800m	1000g	1000g	1000g 

	#	Finally, for some_name.my_domain.com, we wan't to use bandwidth, which we already set
	#	in nginx. 

	*	"some_name.my_domain.com"	ALLOW	1 #this will use zone #1 

Now, everything should work. If we would like to add another entry, we can either restart master server or send SIGUSR1 to it. Second option is better, as hard drive database won't be reloaded.

Please note that if hard drive database is too big (>2GB) server might take long time to boot.