Hosting static site with App Engine, Cloud Build and Hugo

Table Of Contents ↓

So once in a while I try new platform to host my blog. So far i’ve tried Heroku+Jekyll, VPS+Nginx, Netlify+Hugo.

Every option has its Cons and Pros but this post is about: App Engine + Cloud Build + Hugo.


Note: if you’re looking for the simplest setup it’s the Netlify, IMO.

App Engine + Cloud Build

satisfies the requirements above:

There are some cons as well:


  1. create a GCP project or use an existing one.
  2. configure domain and TLS. Google’s managed domains are auto provisioned with Free TLS certificates.
  3. set the daily spend quotas, just to be safe…
  4. configure IAM permissions so Cloud Build is capable deploying App Engine apps: find [email protected] and add “App Engine Admin”, “App Engine Deployer” roles.
  5. configure App Engine for the static app see App.yaml below
  6. create a build trigger for a connected source repository
  7. edit the build trigger and specify the path to the cloudbuild.yaml in your source repository. In my case it’s deploy/cloudbuild.yaml
  8. configure site comilation step; see the cloudbuild.yaml below
  9. configure App Engine deployment step; see the cloudbuild.yaml below


  1. git push origin
  2. ???
  3. Profit!!!



A runtime suitable for static content.

runtime: python27
api_version: 1
threadsafe: true
instance_class: F1
# disable automatic scaling to avoid incurring costs
  target_cpu_utilization: 0.65
  min_instances: 0
  max_instances: 1
  min_pending_latency: 30ms  # default value
  max_pending_latency: automatic
  max_concurrent_requests: 50

# See the reference for more details

## static content routing
- url: /
  static_files: public/index.html
  upload: public/*

# hugo generates pages in directories so check for index.html first
- url: /(.*)/
  static_files: public/\1/index.html
  upload: public/*

- url: /
  static_dir: public/

  - file: default_error.html


Build steps using Hugo to compile the site.

  _HUGO_VERSION: "0.52"

  - '$PROJECT_ID/hugo-${_HUGO_VERSION}:latest'
# the step needed only only when creating/updating Hugo image
- id: 'budil hugo img'
  name: ''
  args: [
            '--build-arg', 'HUGO_VERSION=${_HUGO_VERSION}',
            '-t', '$PROJECT_ID/hugo-${_HUGO_VERSION}:latest',
            '--cache-from', '$PROJECT_ID/hugo-${_HUGO_VERSION}:latest',
            '-f', 'deploy/hugo.Dockerfile', 'deploy/'

- id: 'hugo build site'
  name: '$PROJECT_ID/hugo-${_HUGO_VERSION}:latest'
  entrypoint: 'sh'
    - -c
    - |
      hugo -s ./src
      mv public/ deploy/

- id: 'gcloud deploy app'
  dir: deploy/
  args: ['--project=$PROJECT_ID', 'app', 'deploy', 'app.yaml']

  machineType: 'N1_HIGHCPU_32'

timeout: '120s'


Required to build hugo docker image.

FROM alpine:3.5 as build

ENV HUGO_BINARY=hugo_${HUGO_VERSION}_Linux-64bit.tar.gz

# Install Hugo
RUN set -x && \
  apk add --update wget ca-certificates && \
  wget -q${HUGO_VERSION}/${HUGO_BINARY} && \
  tar xzf ${HUGO_BINARY} && \
  rm -r ${HUGO_BINARY} && \
  mv hugo /usr/bin && \
  apk del wget ca-certificates && \
  rm /var/cache/apk/*

ENTRYPOINT ["/usr/bin/hugo"]

GCP Free Quotas

Read More
Testing MongoDB queries with Golang
Monotonic Time, or Perfect model vs Imperfect Reality
read or add one↓