This is the simplest possible Wagtail site on Google Cloud, using App Engine Flexible and Cloud SQL.
- A project has been created in the Google Cloud Platform Console
- Billing has been enabled for your project
- The Cloud SQL API has been enabled
These steps are detailed in the Google Cloud documentation.
git clone https://github.com/torchbox/wagtail-appengine-demo
cd wagtail-appengine-demo
virtualenv env
source env/bin/activate
sudo apt-get install libmysqlclient-dev
pip install -r requirements.txt
Create a new Cloud SQL instance, using MySQL:
gcloud sql instances create wagae \
--assign-ip \
--database-version=MYSQL_5_7 \
--region=europe-west2 \
--gce-zone=europe-west2-c \
--storage-size=50 \
--storage-type=HDD \
--tier=db-f1-micro
Adjust region, zone storage and machine size (tier) options as necessary. While PostgreSQL is a more common option for Django and Wagtail developers, it is currently only available in beta on Google Cloud SQL.
Create a new user and database, substituting a secure password for
[DB_PASSWORD]
:
gcloud sql users create wagtail % --instance=wagae --password=[DB_PASSWORD]
gcloud sql databases create wagtail --instance=wagae
Fetch the instance connection name for the database you created:
gcloud sql instances describe wagae --format='value(connection_name)'
your-project-id:europe-west2:wagae
We will refer to this as [CONNECTION_NAME]
later.
GCS will be used to store static assets and uploaded media. Create two new buckets, using a common prefix. Note that bucket names must be globally unique - you may want to use your project ID as the prefix.
gsutil mb gs://my-wagtail-site-static
gsutil mb gs://my-wagtail-site-media
Configure CORS headers on the static bucket so fonts can be loaded from the site's domain, and make the contents of both buckets readable by default:
gsutil cors set cors.json gs://my-wagtail-site-static
gsutil defacl set public-read gs://my-wagtail-site-static
gsutil defacl set public-read gs://my-wagtail-site-media
Create a file called wagae/settings/local.py
, and add your site-specific
settings:
DB_CONNECTION_NAME = '[CONNECTION_NAME]'
DB_PASSWORD = '[DB_PASSWORD]'
GS_BUCKET_PREFIX = '[BUCKET_PREFIX]'
GS_PROJECT_ID = '[GCP_PROJECT_ID]'
SECRET_KEY = '[SECRET_KEY]'
[GCP_PROJECT_ID]
is the name of your GCP project. [BUCKET_PREFIX]
is the
common prefix of the two GCS buckets you created, e.g. my-wagtail-site
.
[SECRET_KEY]
can be generated by running python generate_key.py
.
Run Cloud SQL Proxy in a new shell (press '+' in the header of your Cloud Shell):
cloud_sql_proxy -instances="[CONNECTION_NAME]=tcp:3306"
Replace [CONNECTION_NAME]
with the connection name.
Create Wagtail's database tables and an initial user:
./manage.py migrate
./manage.py createsuperuser
Collect the static files locally and upload them:
./manage.py collectstatic --noinput
gsutil -m rsync -R static/ gs://my-wagtail-site-static/
./manage.py runserver 0.0.0.0:8080
Click on the 'Web preview' button in the header of your Cloud Shell. You should be able to log in to the Wagtail admin interface, using the user details you have just created.
Edit app.yaml
, setting [CONNECTION_NAME]
to the Cloud SQL database connection
name.
Then deploy the application:
gcloud app deploy
- Once you know the production domain for your site, specify this in
ALLOWED_HOSTS
andBASE_URL
. - Update the origin in cors.json and rerun
gsutil cors set cors.json
- Increase
SECURE_HSTS_SECONDS
(e.g. to 2592000, which is 30 days) after testing - Change the
^admin/
entrypoint to a less guessable alternative
Run two (clustered) instances of Wagtail: one for editors, with firewalled access to the domain; one from a read-only replica of the database, with the admin UI disabled (remove url(r'^admin/', include(wagtailadmin_urls)),
from urls.py
).
Use wagtail-bakery to export the pages and assets at page publish time. Upload incremental changes to a CDN, e.g. using Firebase hosting. This approach provides the highest levels of performance and security, but more 'dynamic' features (e.g. search, form submissions, server-side A/B testing and personalisation) may become harder to implement. See wagtail-netlify for a similar process using an alternative static hosting provider.
While it is possible to run Wagtail on App Engine Standard, we don't recommend this. App Engine Standard currently only supports Python 2.7, which will not be supported in the imminent releases of Django 2.0 and Wagtail 2.0.
Wagtail sends email notifications to authors and editors, e.g. to prompt reviews when pages have been submitted for moderation. The Google App Engine documentation suggests three third party providers of secure SMTP services:
- https://cloud.google.com/appengine/docs/flexible/python/sending-emails-with-mailgun
- https://cloud.google.com/appengine/docs/flexible/python/sending-emails-with-mailjet
- https://cloud.google.com/appengine/docs/flexible/python/sending-emails-with-sendgrid
Wagtail supports three backends for full-text search, each of which can power both the admin UI and public-facing search. These are Elasticsearch, PostgreSQL FTS and a simple database search. For simplicity's sake, this demo uses the latter. For more performant and feature-rich search, we currently recommend the Elasticsearch backend. Elasticsearch is available on Google Cloud either as a Cloud Launcher App or through Elastic.co's service.