- Introduction
- Getting Started
- Taking it down
- License
This module creates a VPC with the following resources to quickly get you up and running with Zappa:
- RDS Postgres Cluster
- ElastiCache Redis Cluster
- NAT Instance
- Custom Domain for the API Gateway
- Cloudfront Distribution
- Bastion Host
- Internal DNS records
- Associated security groups
It is based on following guides:
- https://github.com/Miserlou/Zappa/blob/master/README.md
- https://edgarroman.github.io/zappa-django-guide/walk_core/
- https://edgarroman.github.io/zappa-django-guide/walk_domain/
Please see them for the motivations behind this module.
After the vpc module is run the output similar to the one below will be generated:
bastion_public_ip = 34.34.34.34
default_security_group_id = sg-bcbcbcbc
lambda_subnet_ids = [
subnet-d1111111,
subnet-cc222222,
subnet-00000000
]
nat_private_ips = [
10.10.11.55
]
postgres_cname = postgres.internal
postgres_password = <password>
redis_cname = redis.internal
This module is split into two parts as Zappa needs to be deployed after the VPC is created but before the custom domain and CloudFront distribution are created. Which gives us three phases:
- Create the VPC and internal resources
- Deploy the Zappa application
- Create the custom domain and CloudFront distribution
The instructions below will walk you through deploying a Django application with terraform and Zappa.
This guide requires that you have terraform and the aws cli configured and working. See:
- https://www.terraform.io/intro/getting-started/install.html
- https://docs.aws.amazon.com/cli/latest/userguide/installing.html
You will at least need to set the following:
$ export AWS_ACCESS_KEY_ID="anaccesskey"
$ export AWS_SECRET_ACCESS_KEY="asecretkey"
$ export AWS_DEFAULT_REGION="us-east-1"
To verify:
$ aws ec2 describe-vpcs
Copy the files in the examples to a location for editing:
mkdir -p <yourproject>/terraform/vpc
cp -R examples/vpc/simple/* <yourproject>/terraform/vpc
cp -R examples/cloudfront <yourproject>/terraform
This module assumes you are using a Route53 hosted zone for DNS. If you are not using Route53 you must create a zone and copy the resulting records to your authoritative source.
Edit:
module "vpc" {
source = "github.com/dpetzold/terraform-aws-zappa/vpc"
name = "lambda"
aws_key_name = "lambda"
aws_key_location = "${file(./private-key)}"
}
The name
variable is used to name the vpc and the resources in it. The
aws_key_*
variables are required to for ssh access to the bastion and NAT
instances.
https://console.aws.amazon.com/ec2/v2/home?region=us-east-1#KeyPairs:sort=keyName
Download the PEM file to a location accessible to the module.
$ cd vpc
$ terraform init
$ terraform plan
$ terraform apply
Edit your ssh configuration file to provide access to the EC2 instances:
Host bastion
Hostname <bastion-public-ip>
User ubuntu
IdentityFile <pathtopemfile>
Host nat1
Hostname <nat-private-ip>
User ubuntu
IdentityFile <pathtopemfile>
ProxyJump bastion
$ scp <sqlfile> bastion:
$ ssh bastion
$ pg_restore -h postgres.internal -U postgres -W -C -d postgres <sqlfile>
CloudFront is configured to pass the Host field via the X-Forwarded-Host header. It is required by Django for host header validation and the sites framework. Update the settings file so the forwarded field is used.
USE_X_FORWARDED_HOST = True
Update the Zappa settings file with the subnet ids and default security group from the terraform output.
{
"prod": {
"django_settings": "config.settings.production",
"aws_region": "us-east-1",
"runtime": "python3.6",
"s3_bucket": "lambda-example-com",
"domain": "api.example.com",
"aws_environment_variables": {
"BROKER_URL": "redis://redis.internal:6379/4",
"CELERY_RESULT_URL": "redis://redis.internal:6379/5",
"DATABASE_URL": "postgres://postgres:<dbpassword>@postgres.internal/postgres",
"DJANGO_AWS_REGION": "us-east-1",
"DJANGO_SETTINGS_MODULE": "config.settings.production"
},
"vpc_config": {
"SubnetIds": [
"subnet-d1111111",
"subnet-cc222222",
"subnet-00000000"
],
"SecurityGroupIds": [
"sg-bcbcbcbc"
]
}
}
}
Then run:
zappa deploy prod
https://console.aws.amazon.com/acm/home?region=us-east-1#/
$ aws apigateway get-rest-apis --query 'items[0].id'
"8vpos55555"
Edit:
module "lambda" {
source = "github.com/dpetzold/terraform-aws-zappa/cloudfront"
domain_names = ["example.com"]
stage_name = "prod"
api_id = "yourapiid"
}
The domain_names
variable is used to create the CloudFront distribution and
it is the key used to pull the SSL certificate. A CloudFront distribution is
created for each specified domain. This would be used if you have many domains
pointed to a single Django application. The stage_name
and api_id
variables are used when creating the custom domain. The custom domain is named
api
and is tertiary to the first domain name. For example, api.example.com.
It is what the CloudFront distribution will point to.
$ cd cloudfront
$ terraform init
$ terraform plan
$ terraform apply
It can take up to 15 minutes for the CloudFront distribution to provision.
To destroy the resources created run the following:
$ cd cloudfront
$ terraform destroy
$ cd ../..
$ zappa undeploy prod
$ cd terraform/vpc
$ terraform destroy
This code is released under the Apache 2.0 License. Please see LICENSE and for more details.