-
Notifications
You must be signed in to change notification settings - Fork 0
AWS EB: Best Practices for Rails app using AWS Elastic Beanstalk
Prerequisite: Relies on a multi-server deployment environment being set up. See Multi-Server Deployment Strategy.
Edit /config/secrets.rb and set/change the following to match...
integration:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
staging:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
/config/environments
should include an environment file for each deployment
- integration.rb should be very close to production.rb and possibly identical
- staging.rb == production.rb
Update database names to use the following convention for integration, staging, and production, respectively.
database: <%= "#{ENV['DATABASE_NAME_PREFIX']}_integration
database: <%= "#{ENV['DATABASE_NAME_PREFIX']}_staging
database: <%= "#{ENV['DATABASE_NAME_PREFIX']}
The configs in the app's .ebextensions directory can be used to perform actions on the AWS machine. The actions you can take include...
- run a command immediately (ex.
.ebextensions/01_fits_download.config
) - create script files on the AWS machine in directory
/opt/elasticbeanstalk/hooks/appdeploy/pre
which to run BEFORE the deploy (ex..ebextensions/02_db_seed_task.config
) - create script files on the AWS machine in directory
/opt/elasticbeanstalk/hooks/appdeploy/post
which to run AFTER the deploy (ex..ebextensions/solr_reindex.config
) - run a yum package (ex.
.ebextensions/git.config
)
Configs that all rails apps on AWS will need include...
| filename | purpose | examples
| git.config | can be used to run bundler such that gems are installed in app's /vendor/bundle directory instead of the default shared location for the machine | .ebextensions/git.config
|
| nginx.config | runs service nginx reload so that changes to nginx (like the https rule below) are actually applied | .ebextensions/nginx.config
|
| nginx-redirect-to-https.config | Applies https rewrite rules so that https is not only enabled, but requests are forced onto https. Must be combined with a load balancer (nginx), a load balancer listener on port 443, and a certificate in ACM to enable the listener. | .ebextensions/nginx-redirect-to-https.config
|
3 deployment processes are setup to go to 3 EB machines
- integration - tied to dev branch to verify latest code works on AWS
- staging - tied to main to verify code targeted for production will work on AWS
- production - the live production app
integration | staging | production | |
---|---|---|---|
project name | project_name_int | project_name_stg | project_name_prod |
deploy trigger | auto-deploy when dev branch changes | auto-deploy when main changes | manually deploy from main |
parameters | Name: sha | Name: sha | |
Type: String | Type: String | ||
Default: dev | Default: main | ||
Description: The branch or commit sha to deploy from github. | Description: The branch or commit sha to deploy from github. |
integration | staging | production | Description/Comments | |
---|---|---|---|---|
application name | project_name_int | project_name_stg | project_name_prod |
integration | staging | production | |
---|---|---|---|
typical initial machine size | t2.large | t2.large | t2.medium |
database name | DATABASE_NAME_PREFIX + '_' + RACK_ENV e.g. exhibits_integration | DATABASE_NAME_PREFIX + '_' + RACK_ENV e.g. exhibits_staging | DATABASE_NAME_PREFIX e.g. exhibits |
Sysops staff can change the configuration parameters through the UI on tab Configurations -> Software -> Modify. For developers, you can change the configuraitons through the UI, but will get a permissions error when you save. But developers can do this using the EB CLI.
integration | staging | production | Description/Comments | |
---|---|---|---|---|
BUNDLE_DISABLE_SHARED_GEMS | 1 | 1 | 1 | "bundle install" will always install the gems into a local directory instead of using system-wide installed gems |
BUNDLE_PATH | vendor/bundle | vendor/bundle | vendor/bundle | where gems will be installed |
BUNDLE_WITHOUT | test | test:development:integration | test:development:integration | gem groups to ignore |
RACK_ENV | integration | staging | production | the rails environment to use |
RAILS_SERVE_STATIC_FILES | true | true | true | allow access to files in public directory when true (default=false) |
RAILS_SKIP_ASSET_COMPILATION | false | false | false | w/o this the assets will not compile |
RAILS_SKIP_MIGRATIONS | false | false | false | typically set to false to run migrations with every deploy |
SECRET_KEY_BASE | Copy results of SecureRandom.hex(64) as the value. | Copy results of SecureRandom.hex(64) as the value. | Copy results of SecureRandom.hex(64) as the value. |
$ irb
>> require 'securerandom'
=> true
>> SecureRandom.hex(64)
=> "A_LONG_RANDOM_KEY"
>> exit
integration | staging | production | Description/Comments | |
---|---|---|---|---|
DATABASE_HOST | set by sysopts based on databases location | |||
DATABASE_NAME_PREFIX | your_app_name | your_app_name | your_app_name | |
DATABASE_RAILS_USER | your_app_db_user | your_app_db_user | your_app_db_user | |
DATABASE_RAILS_USER_PW | your_app_db_user_pw | your_app_db_user_pw | your_app_db_user_pw |
command | example | description |
---|---|---|
eb use EB_APP_NAME | eb use myproj-int | connect to a specific EB machine MUST DO BEFORE USING OTHER COMMANDS |
eb printenv | eb printenv lists | EB configurations |
eb setenv NAME=VALUE | eb setenv RACK_ENV=integration | set an environment variable |
##Setting up s3 data
###Rails app
- install carrierwave gem
- install carrierwave-aws gem
- add config/initializers/carrierwave.rb
if ENV['S3_KEY_ID'].present?
CarrierWave.configure do |config|
config.storage = :aws
config.aws_bucket = ENV['S3_BUCKET']
config.aws_acl = 'bucket-owner-full-control'
config.aws_credentials = {
access_key_id: ENV['S3_KEY_ID'],
secret_access_key: ENV['S3_SECRET_KEY'],
region: ENV['S3_BUCKET_REGION']
}
end
end
- setup s3 buckets and enable web site hosting for each one, in the us-east-1 region
- create an IAM user with permissions to access the three buckets, and restrict access to the buckets only to that user; generate a credential set to insert into configs
- add the following configurations to the AWS project (int, stg, and prod)
integration | staging | production | Description/Comments | |
---|---|---|---|---|
S3_BUCKET | PROJECT-NAME-data-int | PROJECT-NAME-data-stg | PROJECT-NAME-data-prod | |
S3_BUCKET_DOMAIN | http://_PROJECT_NAME-data-int.s3-website-us-east-1.amazonaws.com | http://_PROJECT_NAME-data-stg.s3-website-us-east-1.amazonaws.com | http://_PROJECT_NAME-data-prod.s3-website-us-east-1.amazonaws.com | |
S3_BUCKET_REGION | us-east-1 | us-east-1 | us-east-1 | |
S3_KEY_ID | IAM user access key ID | IAM user access key ID | IAM user access key ID | |
S3_SECRET_KEY | IAM user secret access key | IAM user secret access key | IAM user secret access key |