- 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.
