Skip to content

Commit 6360b73

Browse files
dhhjeromedalbertskipkayhil
authored
Kamal 2 compatible configuration (rails#52883)
* Prepare deploy.yml for new Kamal 2 options * Use Kamal 2 secrets instead of .env * With Kamal 2 being default, and Cloudflare being common, this is the better production default * Add default far-future expiry for Thruster * Just while we are waiting for Kamal 2 to drop * Update for new secrets location * Latest turbo-rails * Dont use Redis for Action Cable when we have Solid Cable * Remote config changed too * Add a kamal alias for sqlite db console when appropriate * No longer relevant Thruster does this now * No longer relevant either Thruster territory * No longer relevant * Update railties/lib/rails/generators/app_base.rb Co-authored-by: Jerome Dalbert <[email protected]> * Proxy branch was merged * Update railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt Co-authored-by: Hartley McGuire <[email protected]> * Use beta1 * Redis only recommended when solid is skipped * Use the Kamal 2 beta1 * Use Kamal 2 beta2 --------- Co-authored-by: Jerome Dalbert <[email protected]> Co-authored-by: Hartley McGuire <[email protected]>
1 parent 2ccd3bf commit 6360b73

File tree

9 files changed

+76
-53
lines changed

9 files changed

+76
-53
lines changed

Gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ gem "dartsass-rails"
2424
gem "solid_cache"
2525
gem "solid_queue"
2626
gem "solid_cable"
27-
gem "kamal", require: false
27+
gem "kamal", ">= 2.0.0.beta2", require: false
2828
gem "thruster", require: false
2929
# require: false so bcrypt is loaded only when has_secure_password is used.
3030
# This is to avoid Active Model (and by extension the entire framework)

Gemfile.lock

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,8 @@ GEM
161161
dante (> 0.1.5)
162162
base64 (0.2.0)
163163
bcrypt (3.1.20)
164-
bcrypt_pbkdf (1.1.0)
164+
bcrypt_pbkdf (1.1.1)
165+
bcrypt_pbkdf (1.1.1-x86_64-darwin)
165166
beaneater (1.1.3)
166167
benchmark (0.3.0)
167168
bigdecimal (3.1.8)
@@ -210,7 +211,7 @@ GEM
210211
delayed_job (>= 3.0, < 5)
211212
digest-crc (0.6.5)
212213
rake (>= 12.0.0, < 14.0.0)
213-
dotenv (2.8.1)
214+
dotenv (3.1.4)
214215
drb (2.2.1)
215216
ed25519 (1.3.0)
216217
erubi (1.13.0)
@@ -308,16 +309,16 @@ GEM
308309
railties (>= 6.0.0)
309310
json (2.7.1)
310311
jwt (2.7.1)
311-
kamal (1.5.2)
312+
kamal (2.0.0.beta2)
312313
activesupport (>= 7.0)
313314
base64 (~> 0.2)
314315
bcrypt_pbkdf (~> 1.0)
315316
concurrent-ruby (~> 1.2)
316-
dotenv (~> 2.8)
317+
dotenv (~> 3.1)
317318
ed25519 (~> 1.2)
318319
net-ssh (~> 7.0)
319-
sshkit (~> 1.21)
320-
thor (~> 1.2)
320+
sshkit (>= 1.23.0, < 2.0)
321+
thor (~> 1.3)
321322
zeitwerk (~> 2.5)
322323
kramdown (2.4.0)
323324
rexml
@@ -369,7 +370,6 @@ GEM
369370
msgpack (1.7.2)
370371
multi_json (1.15.0)
371372
multipart-post (2.3.0)
372-
mutex_m (0.2.0)
373373
mysql2 (0.5.6)
374374
net-http-persistent (4.0.2)
375375
connection_pool (~> 2.2)
@@ -396,6 +396,7 @@ GEM
396396
nokogiri (1.16.7-x86_64-linux)
397397
racc (~> 1.4)
398398
os (1.1.4)
399+
ostruct (0.6.0)
399400
parallel (1.24.0)
400401
parser (3.3.1.0)
401402
ast (~> 2.4.1)
@@ -574,12 +575,12 @@ GEM
574575
mini_portile2 (~> 2.8.0)
575576
sqlite3 (2.0.0-x86_64-darwin)
576577
sqlite3 (2.0.0-x86_64-linux-gnu)
577-
sshkit (1.22.2)
578+
sshkit (1.23.1)
578579
base64
579-
mutex_m
580580
net-scp (>= 1.1.2)
581581
net-sftp (>= 2.1.2)
582582
net-ssh (>= 2.8.0)
583+
ostruct
583584
stackprof (0.2.25)
584585
stimulus-rails (1.3.0)
585586
railties (>= 6.0.0)
@@ -602,7 +603,7 @@ GEM
602603
tomlrb (2.0.3)
603604
trailblazer-option (0.1.2)
604605
trilogy (2.7.0)
605-
turbo-rails (1.5.0)
606+
turbo-rails (2.0.7)
606607
actionpack (>= 6.0.0)
607608
activejob (>= 6.0.0)
608609
railties (>= 6.0.0)
@@ -663,7 +664,7 @@ DEPENDENCIES
663664
jbuilder
664665
jsbundling-rails
665666
json (>= 2.0.0, != 2.7.0)
666-
kamal
667+
kamal (>= 2.0.0.beta2)
667668
launchy
668669
libxml-ruby
669670
listen (~> 3.3)

railties/lib/rails/generators/app_base.rb

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -623,10 +623,10 @@ def css_gemfile_entry
623623
end
624624

625625
def cable_gemfile_entry
626-
return if options[:skip_action_cable]
627-
628-
comment = "Use Redis adapter to run Action Cable in production"
629-
GemfileEntry.new("redis", ">= 4.0.1", comment, {}, true)
626+
if !options[:skip_action_cable] && options[:skip_solid]
627+
comment = "Use Redis adapter to run Action Cable in production"
628+
GemfileEntry.new("redis", ">= 4.0.1", comment, {}, true)
629+
end
630630
end
631631

632632
def bundle_command(command, env = {})
@@ -730,8 +730,7 @@ def run_kamal
730730
bundle_command "binstubs kamal"
731731
bundle_command "exec kamal init"
732732

733-
remove_file ".env"
734-
template "env.erb", ".env.erb"
733+
template "kamal-secrets.tt", ".kamal/secrets", force: true
735734
template "config/deploy.yml", force: true
736735
end
737736

railties/lib/rails/generators/rails/app/templates/Gemfile.tt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ gem "bootsnap", require: false
3232
<% unless options.skip_kamal? -%>
3333

3434
# Deploy this application anywhere as a Docker container [https://kamal-deploy.org]
35-
gem "kamal", require: false
35+
gem "kamal", ">= 2.0.0.beta2", require: false
3636
<% end -%>
3737
<% unless options.skip_thruster? -%>
3838

railties/lib/rails/generators/rails/app/templates/config/deploy.yml.tt

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ servers:
1313
# - 192.168.0.1
1414
# cmd: bin/jobs
1515

16+
# Enable SSL auto certification via Let's Encrypt (and allow for multiple apps on one server).
17+
# Set ssl: false if using something like Cloudflare to terminate SSL (but keep host!).
18+
proxy:
19+
ssl: true
20+
host: app.example.com
21+
1622
# Credentials for your image host.
1723
registry:
1824
# Specify the registry server, if you're not using Docker Hub
@@ -23,8 +29,7 @@ registry:
2329
password:
2430
- KAMAL_REGISTRY_PASSWORD
2531

26-
# Inject ENV variables into containers (secrets come from .env).
27-
# Remember to run `kamal env push` after making changes!
32+
# Inject ENV variables into containers (secrets come from .kamal/secrets).
2833
env:
2934
secret:
3035
- RAILS_MASTER_KEY
@@ -51,6 +56,16 @@ env:
5156
# DB_HOST: 192.168.0.2
5257
<% end -%>
5358

59+
# Aliases are triggered with "bin/kamal <alias>". You can overwrite arguments on invocation:
60+
# "bin/kamal logs -r job" will tail logs from the first server in the job section.
61+
aliases:
62+
console: app exec --interactive --reuse "bin/rails console"
63+
shell: app exec --interactive --reuse "bash"
64+
logs: app logs -f
65+
<% if sqlite3? -%>
66+
dbc: app exec --interactive --reuse "sqlite3 storage/production.sqlite3"
67+
<% end -%>
68+
5469
<% unless skip_storage? %>
5570
# Use a persistent storage volume for sqlite database files and local Active Storage files.
5671
# Recommended to change this to a mounted volume path that is backed up off server.
@@ -63,27 +78,25 @@ volumes:
6378
# version inside the asset_path.
6479
asset_path: /rails/public/assets
6580

81+
# Configure the image builder.
82+
builder:
83+
arch: amd64
84+
85+
# # Build image via remote server (useful for faster amd64 builds on arm64 computers)
86+
# remote: ssh://docker@docker-builder-server
87+
#
88+
# # Pass arguments and secrets to the Docker build process
89+
# args:
90+
# RUBY_VERSION: <%= ENV["RBENV_VERSION"] || ENV["rvm_ruby_string"] || "#{RUBY_ENGINE}-#{RUBY_ENGINE_VERSION}" %>
91+
# secrets:
92+
# - GITHUB_TOKEN
93+
# - RAILS_MASTER_KEY
94+
6695
# Use a different ssh user than root
6796
# ssh:
6897
# user: app
6998

70-
# Configure builder setup (defaults to multi-arch images).
71-
# builder:
72-
# # Build same-arch image locally (use for x86->x86)
73-
# multiarch: false
74-
#
75-
# # Build diff-arch image via remote server
76-
# remote:
77-
# arch: amd64
78-
# host: ssh://[email protected]
79-
#
80-
# args:
81-
# RUBY_VERSION: <%= ENV["RBENV_VERSION"] || ENV["rvm_ruby_string"] || "#{RUBY_ENGINE}-#{RUBY_ENGINE_VERSION}" %>
82-
# secrets:
83-
# - GITHUB_TOKEN
84-
# - RAILS_MASTER_KEY
85-
86-
# Use accessory services (secrets come from .env).
99+
# Use accessory services (secrets come from .kamal/secrets).
87100
# accessories:
88101
# db:
89102
# image: mysql:8.0

railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
require "active_support/core_ext/integer/time"
2+
13
Rails.application.configure do
24
# Settings specified here will take precedence over those in config/application.rb.
35

@@ -20,16 +22,12 @@ Rails.application.configure do
2022
# key such as config/credentials/production.key. This key is used to decrypt credentials (and other encrypted files).
2123
# config.require_master_key = true
2224

23-
# Disable serving static files from `public/`, relying on NGINX/Apache to do so instead.
24-
# config.public_file_server.enabled = false
25+
# Cache assets for far-future expiry since they are all digest stamped.
26+
config.public_file_server.headers = { "cache-control" => "public, max-age=#{1.year.to_i}" }
2527

2628
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
2729
# config.asset_host = "http://assets.example.com"
2830

29-
# Specifies the header that your server uses for sending files.
30-
# config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache
31-
# config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX
32-
3331
<%- unless skip_active_storage? -%>
3432
# Store uploaded files on the local file system (see config/storage.yml for options).
3533
config.active_storage.service = :local
@@ -44,7 +42,7 @@ Rails.application.configure do
4442
<%- end -%>
4543
# Assume all access to the app is happening through a SSL-terminating reverse proxy.
4644
# Can be used together with config.force_ssl for Strict-Transport-Security and secure cookies.
47-
# config.assume_ssl = true
45+
config.assume_ssl = true
4846

4947
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
5048
config.force_ssl = true

railties/lib/rails/generators/rails/app/templates/env.erb.tt

Lines changed: 0 additions & 5 deletions
This file was deleted.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Secrets defined here are available for reference under registry/password, env/secret, builder/secrets,
2+
# and accessories/*/env/secret in config/deploy.yml. All secrets should be pulled from either
3+
# password manager, ENV, or a file. DO NOT ENTER RAW CREDENTIALS HERE! This file needs to be safe for git.
4+
5+
# Example of extracting secrets from 1password (or another compatible pw manager)
6+
# SECRETS=$(kamal secrets --adapter 1password --from Vault/Item Section1/KAMAL_REGISTRY_PASSWORD Section2/RAILS_MASTER_KEY)
7+
# KAMAL_REGISTRY_PASSWORD=$(kamal secrets extract KAMAL_REGISTRY_PASSWORD ${SECRETS})
8+
# RAILS_MASTER_KEY=$(kamal secrets extract RAILS_MASTER_KEY ${SECRETS})
9+
10+
# Use a GITHUB_TOKEN if private repositories are needed for the image
11+
# GITHUB_TOKEN=$(gh config get -h github.com oauth_token)
12+
13+
# Grab the registry password from ENV
14+
KAMAL_REGISTRY_PASSWORD=$KAMAL_REGISTRY_PASSWORD
15+
16+
# Improve security by using a password manager. Never check config/master.key into git!
17+
RAILS_MASTER_KEY=$(cat config/master.key)

railties/test/generators/app_generator_test.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ def test_generator_defaults_to_puma_version
462462
end
463463

464464
def test_action_cable_redis_gems
465-
run_generator
465+
run_generator [destination_root, "--skip-solid"]
466466
assert_file "Gemfile", /^# gem "redis"/
467467
end
468468

@@ -645,7 +645,7 @@ def test_inclusion_of_kamal_files
645645
run_generator_instance
646646

647647
assert_file "config/deploy.yml"
648-
assert_file ".env.erb"
648+
assert_file ".kamal/secrets"
649649
end
650650

651651
def test_kamal_files_are_skipped_if_required
@@ -656,7 +656,7 @@ def test_kamal_files_are_skipped_if_required
656656
assert_empty @bundle_commands.grep("exec kamal init")
657657

658658
assert_no_file "config/deploy.yml"
659-
assert_no_file ".env.erb"
659+
assert_no_file ".kamal/secrets"
660660
end
661661

662662
def test_inclusion_of_kamal_storage_volume

0 commit comments

Comments
 (0)