diff --git a/.gitignore b/.gitignore
index 755b605549d85e74d41a649a0ce9bad1516bcf08..725dd6c63cbcbc71752581eab7f38460e372deaa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@
 /deps
 erl_crash.dump
 *.ez
+*.tar
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 659dd7ed4d7cb5fcc678f7780704cc034bea2997..894aca70144e835a8aa8df4abf3a4be7760da716 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,28 +1,29 @@
 before_script:
-  - banner "Environment"
-  - env | sort
-  - docker info
   - git config --global url.https://.insteadOf git://
   - mkdir -p ~/.hex
   - printf "{key,<<\"$HEX_KEY\">>}.\n{username,<<\"$HEX_USERNAME\">>}.\n" > ~/.hex/hex.config
-  - mix hex.info
 
 stages:
-  - compile
   - test
-
-compile:
-  stage: compile
-  script:
-    - mix deps.get
-    - mix compile
-  tags:
-    - armv7l
+  - publish
 
 test:
   stage: test
   script:
     - mix deps.get
     - mix test
-  tags:
-    - armv7l
+
+hex_publish:
+  stage: publish
+  only:
+    - /^\d+[.]\d+[.]\d+$/ # Only publish HEAD tagged with semantic version
+  script:
+    - mix hex.publish --force
+
+aws_publish:
+  stage: publish
+  only:
+    - /^\d+[.]\d+[.]\d+$/ # Only publish HEAD tagged with semantic version
+  script:
+    - aws s3 cp plug_geoip2-$CI_BUILD_REF_NAME.tar s3://s3.erlang.ninja/plug_geoip2/
+    - aws s3 cp s3://s3.erlang.ninja/plug_geoip2/plug_geoip2-$CI_BUILD_REF_NAME.tar s3://s3.erlang.ninja/plug_geoip2/plug_geoip2-latest.tar