diff --git a/playbooks/deploy_exporters_vhosts.yml b/playbooks/deploy_exporters_vhosts.yml index 9eba203..feb72e1 100644 --- a/playbooks/deploy_exporters_vhosts.yml +++ b/playbooks/deploy_exporters_vhosts.yml @@ -3,6 +3,11 @@ become: true vars: group: cn-homepage.svc.plus + domains: + - cn-homepage.svc.plus + - cn-artifact.svc.plus + - www.svc.plus + - artifact.svc.plus roles: - roles/vhosts/common/ - roles/vhosts/node_exporter/ @@ -12,6 +17,11 @@ become: true vars: group: global-homepage.svc.plus + domains: + - global-homepage.svc.plus + - global-artifact.svc.plus + - www.svc.plus + - artifact.svc.plus roles: - roles/vhosts/common/ - roles/vhosts/node_exporter/ diff --git a/playbooks/deploy_openresty_vhosts.yml b/playbooks/deploy_openresty_vhosts.yml index 15edca8..3b4a76e 100644 --- a/playbooks/deploy_openresty_vhosts.yml +++ b/playbooks/deploy_openresty_vhosts.yml @@ -9,6 +9,18 @@ - name: cn-artifact.svc.plus ssl_certificate: /etc/ssl/svc.plus.pem ssl_certificate_key: /etc/ssl/svc.plus.rsa.key + - name: www.svc.plus + template: geo_redirect.conf.j2 + cn_target: cn-homepage.svc.plus + global_target: global-homepage.svc.plus + ssl_certificate: /etc/ssl/svc.plus.pem + ssl_certificate_key: /etc/ssl/svc.plus.rsa.key + - name: artifact.svc.plus + template: geo_redirect.conf.j2 + cn_target: cn-artifact.svc.plus + global_target: global-artifact.svc.plus + ssl_certificate: /etc/ssl/svc.plus.pem + ssl_certificate_key: /etc/ssl/svc.plus.rsa.key roles: - roles/vhosts/common/ - roles/vhosts/OpenResty/ @@ -23,6 +35,18 @@ - name: global-artifact.svc.plus ssl_certificate: /etc/ssl/svc.plus.pem ssl_certificate_key: /etc/ssl/svc.plus.rsa.key + - name: www.svc.plus + template: geo_redirect.conf.j2 + cn_target: cn-homepage.svc.plus + global_target: global-homepage.svc.plus + ssl_certificate: /etc/ssl/svc.plus.pem + ssl_certificate_key: /etc/ssl/svc.plus.rsa.key + - name: artifact.svc.plus + template: geo_redirect.conf.j2 + cn_target: cn-artifact.svc.plus + global_target: global-artifact.svc.plus + ssl_certificate: /etc/ssl/svc.plus.pem + ssl_certificate_key: /etc/ssl/svc.plus.rsa.key roles: - roles/vhosts/common/ - roles/vhosts/OpenResty/ diff --git a/playbooks/roles/vhosts/OpenResty/tasks/main.yml b/playbooks/roles/vhosts/OpenResty/tasks/main.yml index ad99d7f..e5f6c82 100644 --- a/playbooks/roles/vhosts/OpenResty/tasks/main.yml +++ b/playbooks/roles/vhosts/OpenResty/tasks/main.yml @@ -5,25 +5,59 @@ - gnupg - apt-transport-https state: present - update_cache: yes + update_cache: true - name: Import OpenResty GPG key - command: >- - bash -c 'curl -fsSL https://openresty.org/package/pubkey.gpg | gpg --dearmor -o /usr/share/keyrings/openresty.gpg' + shell: | + curl -fsSL https://openresty.org/package/pubkey.gpg | \ + gpg --dearmor -o /usr/share/keyrings/openresty.gpg args: creates: /usr/share/keyrings/openresty.gpg +# yamllint disable rule:line-length - name: Add OpenResty apt repository apt_repository: repo: "deb [signed-by=/usr/share/keyrings/openresty.gpg] http://openresty.org/package/ubuntu jammy main" filename: openresty state: present +# yamllint enable rule:line-length - name: Install OpenResty apt: name: openresty state: present - update_cache: yes + update_cache: true + +- name: Install GeoIP dependencies + apt: + name: luarocks + state: present + update_cache: true + +- name: Install lua-resty-maxminddb + command: "luarocks install lua-resty-maxminddb" + args: + creates: /usr/local/openresty/site/lualib/resty/maxminddb.lua + +- name: Ensure GeoIP database directory exists + file: + path: /usr/share/GeoIP + state: directory + mode: "0755" + +# yamllint disable rule:line-length +- name: Download GeoLite2 Country database + get_url: + url: https://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz + dest: /usr/share/GeoIP/GeoLite2-Country.mmdb.gz +# yamllint enable rule:line-length + +- name: Decompress GeoLite2 Country database + unarchive: + src: /usr/share/GeoIP/GeoLite2-Country.mmdb.gz + dest: /usr/share/GeoIP/ + remote_src: true + creates: /usr/share/GeoIP/GeoLite2-Country.mmdb - name: Ensure sites-available directory exists file: @@ -38,7 +72,8 @@ - name: Deploy vhost configurations template: - # Use item.template if provided; otherwise default to the unified site template + # Use item.template if provided; + # otherwise default to the unified site template src: "{{ item.template | default('site.conf.j2') }}" dest: "/usr/local/openresty/nginx/conf/sites-available/{{ item.name }}.conf" loop: "{{ domain | default([]) }}" @@ -47,7 +82,7 @@ - name: Enable and start OpenResty systemd: name: openresty - enabled: yes + enabled: true state: started - name: Verify OpenResty core API diff --git a/playbooks/roles/vhosts/OpenResty/templates/geo_redirect.conf.j2 b/playbooks/roles/vhosts/OpenResty/templates/geo_redirect.conf.j2 new file mode 100644 index 0000000..887470b --- /dev/null +++ b/playbooks/roles/vhosts/OpenResty/templates/geo_redirect.conf.j2 @@ -0,0 +1,45 @@ +lua_package_path "/usr/local/openresty/lualib/?.lua;;"; + +server { + listen 443 ssl http2; + server_name {{ item.name }}; + + ssl_certificate {{ item.ssl_certificate }}; + ssl_certificate_key {{ item.ssl_certificate_key }}; + + location / { + access_by_lua_block { + local region = ngx.var.cookie_region + if region == "CN" then + return ngx.redirect("https://{{ item.cn_target }}" .. ngx.var.request_uri, 302) + elseif region == "GLOBAL" then + return ngx.redirect("https://{{ item.global_target }}" .. ngx.var.request_uri, 302) + end + + local geoip = require("resty.maxminddb") + local reader, err = geoip.new("/usr/share/GeoIP/GeoLite2-Country.mmdb") + if not reader then + ngx.log(ngx.ERR, "failed to open MaxMind DB: ", err) + ngx.header["Set-Cookie"] = "region=GLOBAL; Path=/; Max-Age=3600" + return ngx.redirect("https://{{ item.global_target }}" .. ngx.var.request_uri, 302) + end + + local res, err = reader:lookup(ngx.var.remote_addr) + if err then + ngx.log(ngx.ERR, "failed to lookup IP: ", err) + ngx.header["Set-Cookie"] = "region=GLOBAL; Path=/; Max-Age=3600" + return ngx.redirect("https://{{ item.global_target }}" .. ngx.var.request_uri, 302) + end + + local country = res and res.country and res.country.iso_code or "XX" + + if country == "CN" then + ngx.header["Set-Cookie"] = "region=CN; Path=/; Max-Age=3600" + return ngx.redirect("https://{{ item.cn_target }}" .. ngx.var.request_uri, 302) + else + ngx.header["Set-Cookie"] = "region=GLOBAL; Path=/; Max-Age=3600" + return ngx.redirect("https://{{ item.global_target }}" .. ngx.var.request_uri, 302) + end + } + } +}