Skip to content

Deployment

Guy King edited this page Dec 4, 2021 · 38 revisions

Prerequisites

  • Ownership of a <domain>, e.g. abc.com
  • GitHub + CircleCI account
  • GCP account

Overview

  • Git host (GitHub) integrated with CI provider (CircleCI)
  • Changes in master branch in Git host trigger jobs in CI pipeline
  • Infrastructure as code (GCP Deployment Manager)
  • All requests go to https://www.<domain>

Initial run

Transfer the nameserver from your existing DNS registrar to Cloudflare

  • Create a Cloudflare account and login
  • Add a site <domain> -> Select the free plan -> Import the DNS settings -> Click "Continue"
  • Follow the steps to change your nameservers, i.e. in the domain registrar console, remove the current namerservers and replace them with the Cloudflare nameservers
  • Wait for the change to propagate, e.g. wait for all checks to turn green on a DNS checker
  • Click "Check nameservers" in Cloudflare
  • Refresh the browser. If the transfer is complete, you will see "Great news! Cloudflare is now protecting your site" or similar

Perform DNS verification so Google knows you are the domain owner

  • Login to Google Search Console using your GCP credentials
  • Click add property and enter <domain>
  • In Cloudflare -> DNS, add a TXT record for <domain> using the value given in the previous step (if there is already a TXT record for <domain>, update the existing record's value)
  • Wait for the change to propagate
  • Click verify in Google Seach Console, should get an "Ownership verified" confirmation

Point CNAME records to Google Cloud Storage

  • In Cloudflare -> DNS, create two CNAME records (again if they are already there, update them):
    • Name www and content c.storage.googleapis.com
    • Name <domain> and content c.storage.googleapis.com
    • If there is an A record pointing to <domain>, delete it
  • Wait for the www change to propagate (whilst waiting, continue the steps below)
  • Alternatively, instead of using an online DNS checker (which does not seem reliable), can go to the www.<domain> and <domain> in a browser - a The specified bucket does not exist error means it has propagated

Complete Cloudflare configuration

  • Under SSL/TLS, select Flexible (seems to be the default)
  • For www HTTP to www HTTPS, go to "Rules" and create a page rule:
    • For "If the URL matches" URL, enter www.<my-domain>/*
    • For "Then the settings are", enter Always use HTTPS
  • For root domain HTTP to www HTTPS and root domain HTTPS to www HTTPS, go to "Rules" and create a page rule:
    • For "If the URL matches" URL, enter <my-domain>/*
    • For "Then the settings are", enter Forwarding URL with "Destination URL" https://www.<my-domain>/$1 and "Status code" 301 - Permanent Redirect

GCP

  • Enable Cloud Resource Manager API
  • Enable Cloud Deployment Manager V2 API
  • Enable IAM Service Account Credentials API
  • Enable Identity and Access Management (IAM) API
  • Add the Google APIs service account to the list of verified domain owners in https://www.google.com/webmasters/verification/details?hl=en&domain=<domain> (this service account exists by default, and is of the form [PROJECT_NUMBER]@cloudservices.gserviceaccount.com)
  • Add the roles below to the principal [PROJECT_NUMBER]@cloudservices.gserviceaccount.com in IAM:
    • Role Administrator
    • Security Admin
  • Create a service account test-website-ci-identity with role Service Account Token Creator
  • Create a JSON key for the above service account and cat path/to/json | base64 | tr -d "\n"
  • Copy the output from previous command to CircleCI variable GCP_IDENTITY_SERVICE_ACCOUNT_KEY
  • In CircleCI -> Project Settings -> Advanced -> Dynamic Config, enable "use of setup workflows"
  • Create a service account temp with role owner and permission allowing service account test-website-ci-identity access
  • In .circleci/.config.yml, set:
    • GCP_PROJECT_ID
    • DOMAIN
    • GCP_REGION
    • STATIC_DIR
  • Trigger pipeline via commit and push after making below changes to .circleci/config.yml:
    • Set INITIAL_RUN to "true"
    • Set GCP_RESOURCE_SERVICE_ACCOUNT_EMAIL equal to the service account email of temp
    • Approve the hold-create-resources job in CircleCI
  • Delete temp service account
  • Check <domain> and www.<domain> are up (without scheme, with scheme equal to http, and with scheme equal to https)

Subsequent runs

  • Ensure in .circleci/config.yml that:
    • INITIAL_RUN equals "false"
    • GCP_RESOURCE_SERVICE_ACCOUNT_EMAIL equals "${GCP_RESOURCE_SERVICE_ACCOUNT}@${GCP_PROJECT_ID}.iam.gserviceaccount.com"
  • Updates to master branch in GitHub should deploy automatically to production
  • SSL certificates should auto-renew before expiry

Cleanup

  • Remove files from bucket
  • Delete all related resources in Deployment Manager
  • Remove CircleCI environment variable GCP_IDENTITY_SERVICE_ACCOUNT_KEY
  • In CircleCI -> Project Settings -> Advanced -> Dynamic Config, disable "use of setup workflows"
  • Delete service account test-website-ci-identity
  • Disable Cloud Resource Manager API
  • Disable Cloud Deployment Manager V2 API
  • Disable IAM Service Account Credentials API
  • Disable Identity and Access Management (IAM) API
  • Remove roles from the default API service account:
    • Role Administrator
    • Security Admin
  • Remove <domain> from Cloudflare
  • Remove <domain> property from Google Search Console:
    • Select property <domain>
    • Settings (on left sidebar) -> Remove Property
  • Unverify the Google APIs service account at https://www.google.com/webmasters/verification/details?hl=en&domain=<domain>
  • Transfer nameserver back to original registrar