diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index d2ee6bd20874fa957938979d47a6ced8ba2e9bf1..2dad551ff408e55a126216ec5658ed60ebd59ec7 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -42,7 +42,6 @@ prep-deploy:
            TF_VAR_flavor="m1.large"
            openstack volume create --snapshot xdmod-staging-volume-snap --size 150 $TF_VAR_data_volume
       elif [ "$TARGET_ENV" = "production" ]; then
-           TF_VAR_data_volume="xdmod-staging-volume"
            TF_VAR_flavor="m1.xlarge"
       else
            echo "Unknown TARGET_ENV: $TARGET_ENV"
@@ -50,6 +49,7 @@ prep-deploy:
       fi
       echo "TF_VAR_data_volume=${TF_VAR_data_volume}" | tee -a $CI_PROJECT_DIR/vars.env
       echo "TF_VAR_flavor=${TF_VAR_flavor}" | tee -a $CI_PROJECT_DIR/vars.env
+      echo "BUILD_DATE=${BUILD_DATE}" | tee -a $CI_PROJECT_DIR/vars.env
   artifacts:
     reports:
       dotenv: vars.env
@@ -109,7 +109,6 @@ tf-apply:
     reports:
       dotenv: vars.env
 
-
 staging-post-deploy:
   environment:
     name: staging
@@ -133,6 +132,48 @@ staging-post-deploy:
   rules:
     - if: '$TARGET_ENV == "staging"'
 
+production-deploy:
+  environment:
+    name: production
+  stage: deploy
+  tags: [build]
+  script:
+    - export prod_instance_id=$(openstack floating ip show $prod_floating_ip -c port_details -f value | awk -F', ' '{print $2}' | awk -F"'" '{print $2}')
+    - export prod_volume=$(openstack server show $prod_instance_id -c volumes_attached -f value | awk -F"'" '{print $4}')
+    - echo "Detaching prod_volume_id=${prod_volume} from prod_instance_id=${prod_instance_id}"
+    - |
+      eval $(ssh-agent -s)
+      chmod 400 "${SSH_PRIV_KEY}"
+      ssh-add "${SSH_PRIV_KEY}"
+      mkdir ~/.ssh
+      chmod 700 ~/.ssh
+    - ssh -o StrictHostKeyChecking=no $SSH_USERNAME@$prod_floating_ip sudo systemctl stop mariadb
+    - ssh -o StrictHostKeyChecking=no $SSH_USERNAME@$prod_floating_ip sudo umount /var/lib/mysql && df -h
+    - openstack server remove volume $prod_instance_id $prod_volume
+    - openstack server stop $prod_instance_id
+
+    - export staging_volume=$(openstack server show $instance_id -c volumes_attached -f value | awk -F"'" '{print $4}')
+    - echo "Detaching staging_volume_id=${staging_volume} from staging_instance_id=${instance_id}"
+    - ssh -o StrictHostKeyChecking=no $SSH_USERNAME@$staging_floating_ip sudo systemctl stop mariadb
+    - ssh -o StrictHostKeyChecking=no $SSH_USERNAME@$staging_floating_ip sudo umount /var/lib/mysql && df -h
+    - openstack server remove volume $instance_id $staging_volume
+
+    - echo "Attach prod volume $xdmod-prod-vol-$BUILD_DATE to staging instance $instance_id"
+    - openstack volume snapshot create --volume $prod_volume xdmod-prod-data-vol-snapshot-$BUILD_DATE
+    - openstack volume create --snapshot xdmod-prod-data-vol-snapshot-$BUILD_DATE --size 150 xdmod-prod-vol-$BUILD_DATE
+    - openstack server add volume $instance_id xdmod-prod-vol-$BUILD_DATE --device /dev/vdb
+
+    - echo "swap the floating IP between prod and staging instances"
+    - openstack server remove floating ip $prod_instance_id $prod_floating_ip
+    - openstack server remove floating ip $instance_id $staging_floating_ip
+    - openstack server add floating ip $instance_id $prod_floating_ip
+
+    - ssh -o StrictHostKeyChecking=no $SSH_USERNAME@$prod_floating_ip sudo mount /dev/vdb1 /var/lib/mysql
+    - ssh -o StrictHostKeyChecking=no $SSH_USERNAME@$prod_floating_ip sudo systemctl start mariadb
+
+  when: manual
+  rules:
+    - if: '$TARGET_ENV != "dev"'
 
 clean-up:
   stage: cleanup