diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..6778b85 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,47 @@ +name: Build + +on: + workflow_dispatch: + push: + branches: + - master + +jobs: + build: + name: Build & deploy + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1 + + - name: Login to Docker Hub + uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef #v3.6.0 + with: + username: ${{ secrets.ACR_USERNAME }} + password: ${{ secrets.ACR_PASSWORD }} + registry: cratecache.azurecr.io/new-black + + # Switch to a different builder + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f #3.12.0 + + # Determine the run number + - name: Set the run number + id: commit-id + run: | + echo "build_number=$GITHUB_RUN_NUMBER" >> $GITHUB_ENV + + # Build the production image + - name: Build production image + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 #v6.18.0 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: true + target: release + build-args: | + MAXMIND_LICENSE_KEY=${{ secrets.MAXMIND_LICENSE_KEY }} + tags: | + cratecache.azurecr.io/new-black/eva-whoami:latest + cratecache.azurecr.io/new-black/eva-whoami:${{ env.build_number }} + builder: ${{ steps.buildx.outputs.name }} diff --git a/Dockerfile b/Dockerfile index b00f5e3..18c5278 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,6 +19,12 @@ RUN sed 's/GeoLite2-Country_[0-9]*.tar.gz/GeoLite2-Country.tar.gz/g' -i GeoLite2 RUN sha256sum -c GeoLite2-Country.tar.gz.sha256 RUN tar xvf GeoLite2-Country.tar.gz --strip 1 +RUN wget "${MAXMIND_BASE_URL}edition_id=GeoLite2-City&suffix=tar.gz" -O GeoLite2-City.tar.gz +RUN wget "${MAXMIND_BASE_URL}edition_id=GeoLite2-City&suffix=tar.gz.sha256" -O GeoLite2-City.tar.gz.sha256 +RUN sed 's/GeoLite2-City_[0-9]*.tar.gz/GeoLite2-City.tar.gz/g' -i GeoLite2-City.tar.gz.sha256 +RUN sha256sum -c GeoLite2-City.tar.gz.sha256 +RUN tar xvf GeoLite2-City.tar.gz --strip 1 + FROM alpine:3.23 as release LABEL name="ipinfo.tw" RUN mkdir -p /run/nginx/ /usr/share/GeoIP/ diff --git a/README.md b/README.md index cd17d1e..786c299 100644 --- a/README.md +++ b/README.md @@ -55,12 +55,12 @@ Use any http(s) client to explore the server, e.g. https://ipinfo.tw, - `wget -qO- https://ipinfo.tw` - `curl https://ipinfo.tw` -Without any specified URI, the server will return IP address, country, AS, and user agent. +Without any specified URI, the server will return IP address, country, timezone, AS, and user agent. If you prefer to receive a machine-readable result, use path `/json` (without trailing slash), e.g. `https://ipinfo.tw/json`, the result will look like: ```json -{"ip":"3.115.123.234","country_code":"JP","country_name":"Japan","asn":"16509","as_desc":"Amazon.com, Inc.","user_agent":"curl/7.58.0"} +{"ip":"3.115.123.234","country_code":"JP","country_name":"Japan","timezone":"Asia/Tokyo","asn":"16509","as_desc":"Amazon.com, Inc.","user_agent":"curl/7.58.0"} ``` #### Endpoints @@ -75,6 +75,7 @@ You can also specify the following URI to retrieve certain info: - `asn`: AS number - `as_desc`: AS description - `user_agent`: User agent string +- `timezone`: Timezone based on the city (e.g Europe/Amsterdam) Examples: @@ -97,6 +98,9 @@ HK $ curl https://ipinfo.tw/country_name South Korea +$ curl https://ipinfo.tw/timezone +Europe/Amsterdam + $ curl https://ipinfo.tw/as AS16509 / Amazon.com, Inc. diff --git a/k8s/deployment.yaml b/k8s/deployment.yaml new file mode 100644 index 0000000..dc25cdc --- /dev/null +++ b/k8s/deployment.yaml @@ -0,0 +1,39 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: eva-whoami + name: eva-whoami + namespace: platform-tools +spec: + progressDeadlineSeconds: 600 + replicas: 2 + revisionHistoryLimit: 10 + selector: + matchLabels: + app: eva-whoami + strategy: + rollingUpdate: + maxSurge: 25% + maxUnavailable: 25% + type: RollingUpdate + template: + metadata: + labels: + app: eva-whoami + spec: + containers: + - image: cratecache.azurecr.io/new-black/eva-whoami + imagePullPolicy: Always + name: whoami + ports: + - containerPort: 8080 + protocol: TCP + resources: {} + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + terminationGracePeriodSeconds: 30 diff --git a/k8s/ingress.yaml b/k8s/ingress.yaml new file mode 100644 index 0000000..51397e6 --- /dev/null +++ b/k8s/ingress.yaml @@ -0,0 +1,29 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + cert-manager.io/acme-challenge-type: dns01 + cert-manager.io/cluster-issuer: letsencrypt-prod-dns + kubernetes.io/ingress.class: nginx + generation: 2 + labels: + name: eva-whoami + name: eva-whoami + namespace: platform-tools +spec: + ingressClassName: nginx + rules: + - host: whoami.on-eva.io + http: + paths: + - backend: + service: + name: eva-whoami + port: + number: 8080 + path: / + pathType: ImplementationSpecific + tls: + - hosts: + - whoami.on-eva.io + secretName: eva-whoami-tls diff --git a/k8s/service.yaml b/k8s/service.yaml new file mode 100644 index 0000000..157fb56 --- /dev/null +++ b/k8s/service.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + service.beta.kubernetes.io/azure-load-balancer-resource-group: rg-prod-eva + labels: + component: eva-whoami + name: eva-whoami + namespace: platform-tools +spec: + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - name: whoami + nodePort: 31514 + port: 8080 + protocol: TCP + targetPort: 8080 + selector: + app: eva-whoami + sessionAffinity: None + type: LoadBalancer diff --git a/nginx/conf.d/geoip2.conf b/nginx/conf.d/geoip2.conf index 50051de..630fbd8 100644 --- a/nginx/conf.d/geoip2.conf +++ b/nginx/conf.d/geoip2.conf @@ -11,3 +11,8 @@ geoip2 /usr/share/GeoIP/GeoLite2-ASN.mmdb { $ip_aso source=$remote_addr autonomous_system_organization; $ip_as_build_epoch metadata build_epoch; } + +geoip2 /usr/share/GeoIP/GeoLite2-City.mmdb { + auto_reload 1d; + $ip_time_zone source=$remote_addr location time_zone; +} diff --git a/nginx/conf.d/ipinfo.conf b/nginx/conf.d/ipinfo.conf index a21c46e..7eee71d 100644 --- a/nginx/conf.d/ipinfo.conf +++ b/nginx/conf.d/ipinfo.conf @@ -50,6 +50,9 @@ server { location = /user_agent { return 200 "$http_user_agent\n"; } + location = /timezone { + return 200 "$ip_time_zone\n"; + } location ~* ^/index.htm(l)?$ { rewrite ^(.*)$ /; } @@ -58,7 +61,7 @@ server { } location = /json { default_type application/json; - return 200 "{\"ip\":\"$remote_addr\",\"country_code\":\"$ip_country_code\",\"country_name\":\"$ip_country_name\",\"asn\":\"$ip_asn\",\"as_desc\":\"$ip_aso\",\"user_agent\":\"$http_user_agent\"}\n"; + return 200 "{\"ip\":\"$remote_addr\",\"country_code\":\"$ip_country_code\",\"country_name\":\"$ip_country_name\",\"timezone\":\"$ip_time_zone\",\"asn\":\"$ip_asn\",\"as_desc\":\"$ip_aso\",\"user_agent\":\"$http_user_agent\"}\n"; } location = /build_epoch { default_type application/json; diff --git a/nginx/conf.d/realip.conf b/nginx/conf.d/realip.conf index 7ab572d..906263a 100644 --- a/nginx/conf.d/realip.conf +++ b/nginx/conf.d/realip.conf @@ -1,4 +1,5 @@ -real_ip_header X-Real-IP; -set_real_ip_from 10.0.0.0/8; -set_real_ip_from 172.16.0.0/12; -set_real_ip_from 192.168.0.0/16; +real_ip_header X-Forwarded-For; +real_ip_recursive on; +set_real_ip_from 10.0.0.0/8; +set_real_ip_from 172.16.0.0/12; +set_real_ip_from 192.168.0.0/16; \ No newline at end of file