You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Current »




Rails app Setup

Development Branches in Rails app

branchpurpose & usage
dev
  • primary develop goes to this branch
  • configure github to default PRs to this branch
main
  • branch associated with production deployment
  • PRs to this branch are made when a set of code living in the dev branch is ready to be promoted to production
  • create a PR for the current dev and select to merge it into main


App Configs

secrets.rb

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

/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


/config/database.yml

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']}

EB Extensions

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. _REPO_/_APP_/.ebextensions/01_fits_download.config)

    Example .ebextensions/01_fits_download.config
    sources:
      /opt/fits: https://s3.amazonaws.com/_AWS_APPNAME_/fits-1.2.0.zip
    
    container_commands:
      01_symlink_fits:
        command: ln -sf /opt/fits/fits-1.2.0/fits.sh /usr/bin/fits.sh
      02_chmod_fits:
        command: chmod a+x /opt/fits/fits-1.2.0/*.sh
  • create script files on the AWS machine in directory /opt/elasticbeanstalk/hooks/appdeploy/pre which to run BEFORE the deploy

    Example .ebextensions/02_db_seed_task.config
    files:
      "/opt/elasticbeanstalk/hooks/appdeploy/pre/13_db_seed.sh": 
        mode: "000755"
        owner: root
        group: root
        content: | 
          #!/usr/bin/env bash
          set -xe
    
          EB_SCRIPT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k script_dir)
          EB_APP_STAGING_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k app_staging_dir)
          EB_APP_USER=$(/opt/elasticbeanstalk/bin/get-config container -k app_user)
          EB_SUPPORT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k support_dir)
    
          . $EB_SUPPORT_DIR/envvars
    
          RAKE_TASK="db:seed"
    
          . $EB_SCRIPT_DIR/use-app-ruby.sh
    
          cd $EB_APP_STAGING_DIR
    
          if su -s /bin/bash -c "bundle exec $EB_SCRIPT_DIR/check-for-rake-task.rb $RAKE_TASK" $EB_APP_USER; then
                  if [ "$RAILS_SKIP_SEEDS" = "true" ]; then
                          echo "Skipping database migrations (RAILS_SKIP_SEEDS=true)."
                  else
                          su -s /bin/bash -c "leader_only bundle exec rails db:seed" $EB_APP_USER
                  fi
          else
                  echo "No $RAKE_TASK task in Rakefile, skipping database seed."
          fi
  • create script files on the AWS machine in directory /opt/elasticbeanstalk/hooks/appdeploy/post which to run AFTER the deploy

    Example .ebextensions/solr_reindex.config
    commands:
      create_post_dir:
        command: "mkdir -p /opt/elasticbeanstalk/hooks/appdeploy/post"
        ignoreErrors: true
    files:
      "/opt/elasticbeanstalk/hooks/appdeploy/post/01_solr_reindex.sh":
        mode: "000755"
        owner: root
        group: root
        content: |
          #!/usr/bin/env bash
          . /opt/elasticbeanstalk/support/envvars
    
          EB_APP_DEPLOY_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k app_deploy_dir)
          EB_APP_PID_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k app_pid_dir)
          EB_APP_USER=$(/opt/elasticbeanstalk/bin/get-config container -k app_user)
          EB_SCRIPT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k script_dir)
          EB_SUPPORT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k support_dir)
    
          . $EB_SUPPORT_DIR/envvars
          . $EB_SCRIPT_DIR/use-app-ruby.sh
    
          cd $EB_APP_DEPLOY_DIR
    
          if [ "$RAILS_SOLR_REINDEX" = "true" ]; then
                  echo "Starting solr reindex."
                  su -s /bin/bash -c "bundle exec rails solr:reindex" $EB_APP_USER
          else
                  echo "Skipping solr reindex (RAILS_SOLR_REINDEX=false)."
          fi
  • run a yum package

    .ebextensions/git.config
    option_settings:
      - option_name: BUNDLE_DISABLE_SHARED_GEMS
        value: "1"
      - option_name: BUNDLE_PATH
        value: "vendor/bundle"
    
    packages:
      yum:
        git: []


Configs that all rails apps on AWS will need include...

filenamepurpose
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
option_settings:
  - option_name: BUNDLE_DISABLE_SHARED_GEMS
    value: "1"
  - option_name: BUNDLE_PATH
    value: "vendor/bundle"

packages:
  yum:
    git: []
nginx.config

runs service nginx reload so that changes to nginx (like the https rule below) are actually applied

.ebextensions/nginx.config
files:
    "/etc/nginx/conf.d/proxy.conf" :
        mode: "000755"
        owner: root
        group: root
        content: |
            client_max_body_size 500M;

container_commands:
  01_reload_nginx:
    command: "service nginx reload"
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
files:  "/tmp/45_nginx_https_rw.sh":
    owner: root
    group: root
    mode: "000644"
    content: |
      #! /bin/bash

      CONFIGURED=`grep -c "return 301 https" /opt/elasticbeanstalk/support/conf/webapp_healthd.conf`

      if [ $CONFIGURED = 0 ]
        then
          sed -i '/listen 80;/a \ if ($http_x_forwarded_proto = "http") { return 301 https://$host$request_uri; }\n' /opt/elasticbeanstalk/support/conf/webapp_healthd.conf
          logger -t nginx_rw "https rewrite rules added"
          service nginx restart
          exit 0
      else
         logger -t nginx_rw "https rewrite rules already set"
         exit 0
      fi

container_commands:
  00_appdeploy_rewrite_hook:
    command: cp -v /tmp/45_nginx_https_rw.sh /opt/elasticbeanstalk/hooks/appdeploy/enact
  01_configdeploy_rewrite_hook:
    command: cp -v /tmp/45_nginx_https_rw.sh /opt/elasticbeanstalk/hooks/configdeploy/enact
  02_rewrite_hook_perms:
    command: chmod 755 /opt/elasticbeanstalk/hooks/appdeploy/enact/45_nginx_https_rw.sh /opt/elasticbeanstalk/hooks/configdeploy/enact/45_nginx_https_rw.sh
  03_rewrite_hook_ownership:
    command: chown root:users /opt/elasticbeanstalk/hooks/appdeploy/enact/45_nginx_https_rw.sh /opt/elasticbeanstalk/hooks/configdeploy/enact/45_nginx_https_rw.sh



Jenkins & Elasticbeanstalk (EB) Deployment

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



integrationstagingproductionDescription/Comments

Jenkins Setup

project nameproject_name_intproject_name_stgproject_name_prod
deploy triggerauto-deploy when dev branch changesauto-deploy when main changesmanually deploy from main
parametersName:   sha
Type:     String
Default: dev
Description: The branch or commit sha to deploy from github.
Name:   sha
Type:     String
Default: main
Description: The branch or commit sha to deploy from github.


Elastic Beanstalk Setup

application nameproject_name_intproject_name_stgproject_name_prod

Machine Setup

typical initial
machine size
t2.larget2.larget2.medium
database nameDATABASE_NAME_PREFIX + '_' + RACK_ENV
e.g. my_app_integration
DATABASE_NAME_PREFIX + '_' + RACK_ENV
e.g. my_app_staging
DATABASE_NAME_PREFIX
e.g. my_app

Standard Rails Related Configs 1

BUNDLE_DISABLE_SHARED_GEMS111"bundle install" will always install the gems into a local directory instead of using system-wide installed gems
BUNDLE_PATHvendor/bundlevendor/bundlevendor/bundlewhere gems will be installed
BUNDLE_WITHOUTtesttest:development:integrationtest:development:integrationgem groups to ignore
RACK_ENVintegrationstagingproductionthe rails environment to use
RAILS_SERVE_STATIC_FILEStruetruetrueallow access to files in public directory when true (default=false)
RAILS_SKIP_ASSET_COMPILATIONfalsefalsefalsew/o this the assets will not compile
RAILS_SKIP_MIGRATIONSfalsefalsefalsetypically set to false to run migrations with every deploy
SECRET_KEY_BASECopy 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

Standard Database Related Configs

DATABASE_HOST


set by sysopts based on databases location
DATABASE_NAME_PREFIXyour_app_nameyour_app_nameyour_app_name
DATABASE_RAILS_USERyour_app_db_useryour_app_db_useryour_app_db_user
DATABASE_RAILS_USER_PWyour_app_db_user_pwyour_app_db_user_pwyour_app_db_user_pw




Footnotes

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


commandexampledescription
eb use _EB_APP_NAME_eb use my-app-intconnect to a specific EB machine
MUST DO BEFORE USING OTHER COMMANDS
eb printenveb printenvlists EB configurations
eb setenv _NAME_=_VALUE_eb setenv RACK_ENV=integrationset 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

AWS changes

  • 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)

integrationstagingproductionDescription/Comments
S3_BUCKET_PROJECT_NAME-data-int_PROJECT_NAME-data-stg_PROJECT_NAME-data-prod
S3_BUCKET_DOMAINhttp://_PROJECT_NAME-data-int.s3-website-us-east-1.amazonaws.comhttp://_PROJECT_NAME-data-stg.s3-website-us-east-1.amazonaws.comhttp://_PROJECT_NAME-data-prod.s3-website-us-east-1.amazonaws.com
S3_BUCKET_REGIONus-east-1us-east-1us-east-1
S3_KEY_IDIAM user access key IDIAM user access key IDIAM user access key ID
S3_SECRET_KEYIAM user secret access keyIAM user secret access keyIAM user secret access key


  • No labels