How to 302 redirect based on geo-ip in nginx

I want my all my users have the fastest loading speed when visiting my website chinesefoodlab.com, so it is better to use server in the same location as users. However, all websites hold by server in China mailand needs ICP file and my chinesefoodlab.com cannot finish ICP filing in China cause it contains “chinese” characters. So I registered another domain cnfoodlab.com and finished ICP filing. I want to use chinesefoodlab.com as main domain, so I need to redirect users from China mainland to cnfoodlab.com to give them the best service. And this tutorial is to record how to do it.

How to 302 redirect based on geo-ip in nginx

Download free geo-ip database from maxmind.com

  1. Register an account in maxmind.com

  2. Then you will receive an email which says “A New MaxMind License Key Was Generated For Your Account”, you can login to your account portal using the link in this email.

  3. Download Config file in account portal, which should like this:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # GeoIP.conf file for `geoipupdate` program, for versions >= 3.1.1.
    # Used to update GeoIP databases from https://www.maxmind.com.
    # For more information about this config file, visit the docs at
    # https://dev.maxmind.com/geoip/updating-databases.

    # `AccountID` is from your MaxMind account.
    AccountID 1234567

    # `LicenseKey` is from your MaxMind account.
    LicenseKey 4s1fax_4usdfassdsafdsakjukfdQROnc_sav

    # `EditionIDs` is from your MaxMind account.
    EditionIDs GeoLite2-ASN GeoLite2-City GeoLite2-Country

    Save this conf file to ~/GeoIP.conf on your server.

  4. Log in your server as root.

    1
    2
    3
    4
    sudo add-apt-repository ppa:maxmind/ppa
    sudo apt update
    sudo apt install geoipupdate
    geoipupdate -f GeoIP.conf

    Then there should be three geo-ip database downloaded in /usr/share/GeoIP

    GeoLite2-ASN.mmdb GeoLite2-City.mmdb GeoLite2-Country.mmdb

Configure nginx redirection

Log in your server as root

1
vim /etc/nginx/conf.d/99_geoip2_global.conf
1
2
3
4
5
6
7
8
9
10
11
12
# --- Free country database ---
# If you used DB-IP Lite, just swap the filename below.
geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
# expose the two-letter ISO code as $geo_country_code
$geo_country_code country iso_code;
}

# 1 = Mainland China, 0 = everywhere else
map $geo_country_code $redirect_cn {
default 0;
CN 1;
}
1
vim /etc/nginx/sites-available/example.com
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# Redirect all HTTP traffic to HTTPS
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;

# Logs for redirect traffic
access_log /var/log/nginx/example.redirect.access.log;
error_log /var/log/nginx/example.redirect.error.log;

# Mainland‑China visitors → ICP‑licensed host
if ($redirect_cn) {
return 302 https://cnfoodlab.com$request_uri;
}

return 301 https://example.com$request_uri;
}

# Redirect www to non‑www and serve HTTPS
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.example.com;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

# Mainland‑China visitors → ICP‑licensed host
if ($redirect_cn) {
return 302 https://cnfoodlab.com$request_uri;
}

# Logs for www→non‑www redirects
access_log /var/log/nginx/example.www-redirect.access.log;
error_log /var/log/nginx/example.www-redirect.error.log;

return 301 https://example.com$request_uri;
}

# Serve Flutter Web App with HTTPS
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

# Mainland‑China visitors → ICP‑licensed host
if ($redirect_cn) {
return 302 https://cnfoodlab.com$request_uri;
}

# Application logs
access_log /var/log/nginx/example.access.log;
error_log /var/log/nginx/example.error.log;

root /home/sync-user/example/html;
index index.html;

location / {
try_files $uri $uri/ /index.html;
}
}

Reference

  1. https://dev.maxmind.com/geoip/updating-databases/
  2. https://github.com/maxmind/geoipupdate