Jets Config: Project, Bootstrap, Deploy

The config/jets folder has your Jets settings. It tells Jets how to deploy.

Config Jets Files

Here’s an summary of the config/jets files.

File Description
config/jets/project.rb Project settings like project name. The project name is a part of the stack name to deploy. IE: project=demo => stack=demo-dev gets to deploy to AWS.
config/jets/bootstrap.rb Bootstrap settings are used for the jets deploy initial bootstrap deployment. This phase creates the s3 bucket and codebuild remote runner which will be used to deploy your project. The remote runner provides a consistent build environment, CPU architecture, raw horsepower, and internet speed. See: Remote Runner.
config/jets/deploy.rb This is where the main deploy settings live. It tells the jets remote runner how it should deploy. These are the settings you’ll probably update the most.

Config Project

The project.rb is always loaded earliest. It has simple configurations are loaded super early in the Jets boot process.

config/jets/project.rb

Jets.project.configure do
  config.name = "demo"
end

The project.rb has the project name. The jets init command infers the name from the parent folder. Change it to demo if it’s not already.

The project name will be part of the stack name to deploy. IE: project=demo => stack=demo-dev gets to deploy to AWS.

Config Bootstrap

The bootstrap.rb has configurations that loaded next for the Jets bootstrap process. The bootstrap phase is the first phase of the Jets deploy process.

config/jets/bootstrap.rb

Jets.bootstrap.configure do
  config.codebuild.project.env.vars = {
    BUNDLE_GITHUB__COM: "SSM:/#{ssm_env}/BUNDLE_GITHUB__COM",
    DOCKER_PASS: "SSM:/#{ssm_env}/DOCKER_PASS",
    DOCKER_USER: "SSM:/#{ssm_env}/DOCKER_USER",
    # Use your own docker host
    # DOCKER_HOST: "SSM:/#{ssm_env}/DOCKER_HOST",
    # JETS_SSH_KEY: "SSM:/#{ssm_env}/JETS_SSH_KEY",
    # JETS_SSH_KNOWN: "SSM:/#{ssm_env}/JETS_SSH_KNOWN"
  }
end

The ssm_env helper returns dev for JETS_ENV=dev and prod for JETS_ENV=prod. You should create these SSM values:

/dev/BUNDLE_GITHUB__COM
/dev/DOCKER_PASS
/dev/DOCKER_USER

Environment variable BUNDLE_GITHUB__COM allow the jets remote process to git clone and install private gems in your Gemfile. See: Remote Runner Private Repos

The DOCKER_PASS and DOCKER_USER env vars can be use to log into docker. You should set them to log into DockerHub, so it allows DockerHub docker pull without running into the rate limit. For more info see: CodeBuild Remote Docker.

It is recommended to use your own remote Docker Host with the env var DOCKER_HOST to speed up builds. See: Remote Docker Host

After jets init, you’ll adjust boostrap.rb. It’s not updated much afterward.

Related: SSM CLI Cheatsheet

Config Deploy

The deploy.rb contains the most options and will be the settings you’ll likely adjust most. It tells the Jets Remote Runner how to build and deploy your project to Serverless AWS Lambda. Here’s a starter example:

config/jets/deploy.rb

Jets.deploy.configure do
  # Scaling https://docs.rubyonjets.com/docs/config/concurrency/
  config.lambda.controller.provisioned_concurrency = 1  # costs money, always running lambda
  config.lambda.controller.reserved_concurrency = 25    # free and limits scaling

  # CloudFront Lambda URL https://docs.rubyonjets.com/docs/routing/lambda/cloudfront/distribution/
  config.lambda.url.cloudfront.enable = true
  config.lambda.url.cloudfront.cert.arn = acm_cert_arn("domain.com", region: "us-east-1")
  config.lambda.url.cloudfront.route53.enable = true

  # Release phase https://docs.rubyonjets.com/docs/hooks/remote/release/
  config.release.phase.command = "bundle exec rails db:migrate"
end

Config Env Files

Jets supports dotenv files in the config/jets/env files. They are designed for deployment and introduce a few extra features like SSM parameter store support. For more info: Env Files

Config Dev vs Prod

You can also use separate config files for dev and prod. Here’s an example.

config/jets/deploy/dev.rb

Jets.deploy.configure do
  config.lambda.url.cloudfront.enable = true
  config.lambda.url.cloudfront.cert.arn = acm_cert_arn(domain: "dev.example.com", region: "us-east-1")
end

config/jets/deploy/prod.rb

Jets.deploy.configure do
  config.lambda.url.cloudfront.enable = true
  config.lambda.url.cloudfront.cert.arn = acm_cert_arn(domain: "example.com", region: "us-east-1")
end

Load Order

The config files load in the following order:

config/jets/project.rb
config/jets/bootstrap.rb
config/jets/deploy.rb

Client vs Remote Loading

Understanding when jets loads config/jets files can be useful.

  • The project.rb and bootstrap.rb are loaded on the client-side jets deploy.
  • The project.rb, bootstrap.rb, and deploy.rb are all loaded on the remote-side jets-remote deploy.

To add clarity, when you run

jets deploy

That handles the client-side deploy. The jets deploy loads project.rb and bootstrap.rb. Then jets deploy starts up a remote runner and ultimately calls.

jets-remote deploy

The remote-side deploy loads all 3 config files: project.rb, bootstrap.rb, and deploy.rb.

Separate of Concerns

Jets only loads deploy.rb on the remote runner to separate concerns. The design allows separate limited AWS IAM permissions for the client vs remote jets deploy. This is particularly helpful when using jets helpers for a more human-readable config. Example:

config/jets/deploy.rb

Jets.deploy.configure do
  config.lambda.url.cloudfront.enable = true
  config.lambda.url.cloudfront.cert.arn = acm_cert_arn(domain: "example.com", region: "us-east-1")
end

IE: The acm_cert_arn helper requires AWS Cert Manager IAM permissions, which only need to be granted to the remote runner vs on the lightweight jet local client.

These separate projects.rb, bootstrap.rb, and deploy.rb configs allow Jets to control load order finely. This is particularly useful for some items that must be loaded extremely early in the boot process, like project.rb. This removes the need for clunky double parsing that existed in previous versions before Jets 6.