It may be a good idea to enable some parts of your application based on a user country. You could do this on an application level:

require 'geoip'

# Controller code...
before_action do
  fail NotAllowed unless Country.allowed?(request.remote_ip)
end

But why would you want to store non-business logic like this in your app? ;) There’s a much better solution: you can use the Nginx GeoIP Module.

To do so, you need to have Nginx compiled with a ngx_http_geoip_module. Run:

nginx -V

to see Nginx details. Look for –with-http_geoip_module. If you have it, you can use the GeoIP database with your Nginx instance.

Install the GeoIp database:

sudo apt-get install geoip-database libgeoip1
# you can also download it from here: http://geolite.maxmind.com

it will be stored in /usr/share/GeoIP/.

Now you need to edit /etc/nginx/nginx.conf file. Put following code in the http section:

geoip_country /usr/share/GeoIP/GeoIP.dat;
map $geoip_country_code $allowed_country {
  default no;
  PL yes;
  US yes;

We decided to blacklist every country except Poland and USA. Full list of countries and their appropriate codes can be found here. Of course instead of whitelisting you could always blacklist:

geoip_country /usr/share/GeoIP/GeoIP.dat;
map $geoip_country_code $allowed_country {
  default yes;
  PL no;
  US no;

This code won’t block anything. It will just assign a yes/no value to a $geoip_country_code variable. You can then use it in your server block to allow/disallow access to certain parts of your application:

server {
  server_name  www.yourdomain.com;
  client_max_body_size 32M;
  keepalive_timeout 5;

  # Some other settings here

  error_page 403 /403.html;

  location /admin {
    if ($allowed_country = no) {
      return 403;
    }

    if (-f $request_filename) {
      break;
    }

    if (!-f $request_filename) {
      proxy_pass proxypasstargetsomewhere;
      break;
    }
  }
}