AWS Elastic Beanstalk Django template
container_commands:
01_mergedb:
command: "python manage.py makemigrations --no-input --merge"
02_syncdb:
command: "python manage.py migrate --no-input"
03_create_super_user:
command: "python manage.py create_default_super_user"
04_migrate_all:
command: "python manage.py collectstatic --no-input"
option_settings:
aws:elasticbeanstalk:container:python:staticfiles:
"/static/": "staticfiles/"
aws:elasticbeanstalk:container:python:
WSGIPath: config/wsgi.py
AWSTemplateFormatVersion: '2010-09-09'
Description: "A Beanstalk web stack for hosting a Django application"
Parameters:
AppEnvironment:
Description: The business environment
Default: "production"
Type: String
AllowedValues:
- "production"
- "staging"
AppName:
Description: "Optional ElasticBeanstalk application name (i.e. EB Physical ID). Leave blank to create a new AWS::ElasticBeanstalk::Application, or else enter an existing app's name."
Type: String
Default: ""
# TODO: move connection information out of (leaky) environment and into S3 connection string file
EnvDbDjangoHostname:
Description: RDS database host URL
Type: String
Default: cms-db.mytomorrows.com
EnvDbDjangoPort:
Description: RDS port
Type: String
Default: "5432"
EnvDbDjangoName:
Description: RDS schema name
Type: String
EnvDbDjangoUsername:
Description: RDS app user name
Type: String
MaxLength: '32'
MinLength: '8'
Default: oltproot
EnvDbDjangoPassword:
Description: RDS app user password
Type: String
MaxLength: '256'
MinLength: '8'
NoEcho: 'true'
EnvDjangoDebug:
Description: Django Debug flag
Type: String
Default: 'False'
EnvDjangoSettings:
Description: Django environment
Type: String
Default: 'config.settings.staging'
EnvDjangoAWSID:
Description: IAM access ID
Type: String
EnvDjangoAWSSecret:
Description: IAM secret access key
Type: String
NoEcho: 'true'
EnvDjangoS3Bucket:
Description: S3 bucket address
Type: String
Default: 'storage.django.mytomorrows.com'
EnvDjangoS3BucketJobs:
Description: S3 bucket address to uploads jobs CV
Type: String
Default: 'jobs.upload'
EnvDjangoCaptchaId:
Description: Google Captcha ID
Type: String
EnvDjangoCaptchaSecret:
Description: Google Captcha secret
Type: String
Mappings:
AppEnvironmentMap:
production:
env: "Site-Production"
domain: "site"
djangoEnv: "config.settings.production"
staging:
env: "Site-Staging"
domain: "site-staging"
djangoEnv: "config.settings.staging"
Conditions:
ShouldCreateNewEBApp: !Equals [!Ref AppName, ""]
Resources:
DjangoApp:
Condition: ShouldCreateNewEBApp # only create a new app if an existing app name was not supplied as a parameter
Type: AWS::ElasticBeanstalk::Application
Properties:
ApplicationName: Website
Description: "myTomorrows new site"
DjangoAppVersion:
Type: AWS::ElasticBeanstalk::ApplicationVersion
Properties:
ApplicationName: !If [ShouldCreateNewEBApp, !Ref DjangoApp, !Ref AppName]
Description: "Version 1.0.0"
SourceBundle:
# Note: the expected global EB deploy bucket on S3 should be setup in a separate CF template
S3Bucket: !ImportValue CrowdsourcingS3DeployBucket # TODO: rename and relaunch S3 bucket
S3Key: website.zip
DjangoConfiguration:
Type: AWS::ElasticBeanstalk::ConfigurationTemplate
Properties:
ApplicationName: !If [ShouldCreateNewEBApp, !Ref DjangoApp, !Ref AppName]
Description: "ElasticBeanstalk configuration settings"
SolutionStackName: "64bit Amazon Linux 2017.03 v2.4.1 running Python 3.4"
OptionSettings:
- Namespace: aws:autoscaling:asg
OptionName: MinSize
Value: 1
- Namespace: aws:autoscaling:asg
OptionName: MaxSize
Value: 1
- Namespace: aws:elasticbeanstalk:environment
OptionName: EnvironmentType
Value: LoadBalanced # for non-production or to save money, use 'SingleInstance' instead
# Secrets and dynamic state entered as CF params and stored for the Beanstalk EC2 ENV
# TODO: get secrets from KMS to not store in plaintext ENV variable
- Namespace: aws:elasticbeanstalk:application:environment
OptionName: DATABASE_HOST
Value: !Ref EnvDbDjangoHostname
- Namespace: aws:elasticbeanstalk:application:environment
OptionName: DATABASE_PORT
Value: !Ref EnvDbDjangoPort
- Namespace: aws:elasticbeanstalk:application:environment
OptionName: DATABASE_USER
Value: !Ref EnvDbDjangoUsername
- Namespace: aws:elasticbeanstalk:application:environment
OptionName: DATABASE_PASSWORD
Value: !Ref EnvDbDjangoPassword
- Namespace: aws:elasticbeanstalk:application:environment
OptionName: DATABASE_DBNAME
Value: !Ref EnvDbDjangoName
- Namespace: aws:elasticbeanstalk:application:environment
OptionName: DJANGO_SETTINGS_MODULE
Value: !Join ["", [!FindInMap [AppEnvironmentMap, !Ref AppEnvironment, "djangoEnv"]]]
- Namespace: aws:elasticbeanstalk:application:environment
OptionName: DJANGO_DEBUG
Value: !Ref EnvDjangoDebug
- Namespace: aws:elasticbeanstalk:application:environment
OptionName: DJANGO_AWS_ACCESS_KEY_ID
Value: !Ref EnvDjangoAWSID
- Namespace: aws:elasticbeanstalk:application:environment
OptionName: DJANGO_AWS_SECRET_ACCESS_KEY
Value: !Ref EnvDjangoAWSSecret
- Namespace: aws:elasticbeanstalk:application:environment
OptionName: DJANGO_AWS_STORAGE_BUCKET_NAME
Value: !Ref EnvDjangoS3Bucket
- Namespace: aws:elasticbeanstalk:application:environment
OptionName: DJANGO_AWS_STORAGE_BUCKET_NAME_JOBS
Value: !Ref EnvDjangoS3BucketJobs
- Namespace: aws:elasticbeanstalk:application:environment
OptionName: DJANGO_GOOGLE_CAPTCHA_ID
Value: !Ref EnvDjangoCaptchaId
- Namespace: aws:elasticbeanstalk:application:environment
OptionName: DJANGO_GOOGLE_CAPTCHA_SECRET
Value: !Ref EnvDjangoCaptchaSecret
# configure load balancer options for SSL certificate attachment
- Namespace: aws:elb:listener:443
OptionName: InstanceProtocol
Value: HTTP
- Namespace: aws:elb:listener:443
OptionName: InstancePort
Value: 80
- Namespace: aws:elb:listener:443
OptionName: ListenerEnabled
Value: true
- Namespace: aws:elb:listener:443
OptionName: ListenerProtocol
Value: HTTPS
- Namespace: aws:elb:listener:443
OptionName: SSLCertificateId
Value: !Ref DjangoSslCertificate
- Namespace: aws:elb:listener:80
OptionName: ListenerEnabled
Value: false
DjangoSslCertificate:
Type: "AWS::CertificateManager::Certificate"
Properties:
DomainName: "*.mytomorrows.com"
Tags:
- Key: Name
Value: Django SSL Certificate
DjangoEnv:
Type: AWS::ElasticBeanstalk::Environment
Properties:
ApplicationName: !If [ShouldCreateNewEBApp, !Ref DjangoApp, !Ref AppName]
Description: "AWS Elastic Beanstalk Environment running Python Search API in Django"
EnvironmentName: !Join ["", [!FindInMap [AppEnvironmentMap, !Ref AppEnvironment, "env"]]]
TemplateName: !Ref DjangoConfiguration
VersionLabel: !Ref DjangoAppVersion
DjangoDNS:
Type: AWS::Route53::RecordSet
Properties:
HostedZoneName: 'mytomorrows.com.'
Comment: A Record subdomain for EC2 app instance
Name: !Join [".", [!FindInMap [AppEnvironmentMap, !Ref AppEnvironment, "domain"], "mytomorrows.com"]]
Type: CNAME
TTL: '300'
ResourceRecords:
- !GetAtt DjangoEnv.EndpointURL
Outputs:
DjangoDomain:
Value: !GetAtt DjangoEnv.EndpointURL
DjangoDNS:
Value: !Ref DjangoDNS
packages:
yum:
libjpeg-turbo-devel: []
libpng-devel: []
libffi-devel: []
openssl-devel: []