kamal 2.0.0.rc4 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 84140bdc487da680b06d12d90b50f7f5e31e55fefb5be7c029ab0883d31086b6
4
- data.tar.gz: c88fb136bef3f989a13efaba8628080b10bb4cc3f7e5606aa24e0627e9764d58
3
+ metadata.gz: f7358f4d2dd4e267e0fccab45df538facb5f1cfb598cee5561495139e3b06f62
4
+ data.tar.gz: 6bc6d6e32693cba5af10dba86aefe0af00e48fee214eee1b9483a892f0a30d0d
5
5
  SHA512:
6
- metadata.gz: a5a316c076f50f0052790589b7ecc43f62c671043dd806f57c0b7eac8d9c7f56fa6b5d2d1e651deb5c8ec1475aad453084637ffcf59aa8557267ca15e9798992
7
- data.tar.gz: ca73bc0883121188cc94df733264ee41a8f3d778a443dfde6d472a7e609168725bbfbc6d613c891a095c1a81eb4f5e9368c07eaa5532ad8bf286464578ac03f0
6
+ metadata.gz: 3629d4180a4f0350fc28f9488dbf516f79a8c6fe0e64854a56e88b4846d0f855e0e9621f3695958db12104342ef1bee90cdfc93d2b5a32583973862c71e8eba4
7
+ data.tar.gz: 2dbd756cf617c2afc9b70603a9da9991c83f6d7fb6cf2e0be59c07d29b65ba53d84ea875727c1b888cde0889458099c24451eed3c406017548891815329eb289
data/lib/kamal/cli/app.rb CHANGED
@@ -68,7 +68,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
68
68
  version = capture_with_info(*app.current_running_version, raise_on_non_zero_exit: false).strip
69
69
  endpoint = capture_with_info(*app.container_id_for_version(version)).strip
70
70
  if endpoint.present?
71
- execute *app.remove(target: endpoint), raise_on_non_zero_exit: false
71
+ execute *app.remove, raise_on_non_zero_exit: false
72
72
  end
73
73
  end
74
74
 
@@ -203,7 +203,7 @@ class Kamal::Cli::App < Kamal::Cli::Base
203
203
  run_locally do
204
204
  info "Following logs on #{KAMAL.primary_host}..."
205
205
 
206
- KAMAL.specific_roles ||= [ "web" ]
206
+ KAMAL.specific_roles ||= [ KAMAL.primary_role.name ]
207
207
  role = KAMAL.roles_on(KAMAL.primary_host).first
208
208
 
209
209
  app = KAMAL.app(role: role, host: host)
@@ -21,6 +21,13 @@ class Kamal::Cli::Secrets < Kamal::Cli::Base
21
21
  return_or_puts value, inline: options[:inline]
22
22
  end
23
23
 
24
+ desc "print", "Print the secrets (for debugging)"
25
+ def print
26
+ KAMAL.config.secrets.to_h.each do |key, value|
27
+ puts "#{key}=#{value}"
28
+ end
29
+ end
30
+
24
31
  private
25
32
  def adapter(adapter)
26
33
  Kamal::Secrets::Adapters.lookup(adapter)
@@ -18,6 +18,8 @@ servers:
18
18
  proxy:
19
19
  ssl: true
20
20
  host: app.example.com
21
+ # kamal-proxy connects to your container over port 80, use `app_port` to specify a different port.
22
+ # app_port: 3000
21
23
 
22
24
  # Credentials for your image host.
23
25
  registry:
@@ -5,8 +5,8 @@ module Kamal::Commands::App::Proxy
5
5
  proxy_exec :deploy, role.container_prefix, *role.proxy.deploy_command_args(target: target)
6
6
  end
7
7
 
8
- def remove(target:)
9
- proxy_exec :remove, role.container_prefix, *role.proxy.remove_command_args(target: target)
8
+ def remove
9
+ proxy_exec :remove, role.container_prefix
10
10
  end
11
11
 
12
12
  private
@@ -3,32 +3,32 @@
3
3
  # Accessories can be booted on a single host, a list of hosts, or on specific roles.
4
4
  # The hosts do not need to be defined in the Kamal servers configuration.
5
5
  #
6
- # Accessories are managed separately from the main service - they are not updated
7
- # when you deploy and they do not have zero-downtime deployments.
6
+ # Accessories are managed separately from the main service they are not updated
7
+ # when you deploy, and they do not have zero-downtime deployments.
8
8
  #
9
9
  # Run `kamal accessory boot <accessory>` to boot an accessory.
10
10
  # See `kamal accessory --help` for more information.
11
11
 
12
12
  # Configuring accessories
13
13
  #
14
- # First define the accessory in the `accessories`
14
+ # First, define the accessory in the `accessories`:
15
15
  accessories:
16
16
  mysql:
17
17
 
18
18
  # Service name
19
19
  #
20
- # This is used in the service label and defaults to `<service>-<accessory>`
21
- # where `<service>` is the main service name from the root configuration
20
+ # This is used in the service label and defaults to `<service>-<accessory>`,
21
+ # where `<service>` is the main service name from the root configuration:
22
22
  service: mysql
23
23
 
24
24
  # Image
25
25
  #
26
- # The Docker image to use, prefix with a registry if not using Docker hub
26
+ # The Docker image to use, prefix it with a registry if not using Docker Hub:
27
27
  image: mysql:8.0
28
28
 
29
29
  # Accessory hosts
30
30
  #
31
- # Specify one of `host`, `hosts` or `roles`
31
+ # Specify one of `host`, `hosts`, or `roles`:
32
32
  host: mysql-db1
33
33
  hosts:
34
34
  - mysql-db1
@@ -38,12 +38,12 @@ accessories:
38
38
 
39
39
  # Custom command
40
40
  #
41
- # You can set a custom command to run in the container, if you do not want to use the default
41
+ # You can set a custom command to run in the container if you do not want to use the default:
42
42
  cmd: "bin/mysqld"
43
43
 
44
44
  # Port mappings
45
45
  #
46
- # See https://docs.docker.com/network/, especially note the warning about the security
46
+ # See https://docs.docker.com/network/, and especially note the warning about the security
47
47
  # implications of exposing ports publicly.
48
48
  port: "127.0.0.1:3306:3306"
49
49
 
@@ -52,20 +52,22 @@ accessories:
52
52
  app: myapp
53
53
 
54
54
  # Options
55
- # These are passed to the Docker run command in the form `--<name> <value>`
55
+ #
56
+ # These are passed to the Docker run command in the form `--<name> <value>`:
56
57
  options:
57
58
  restart: always
58
59
  cpus: 2
59
60
 
60
61
  # Environment variables
61
- # See kamal docs env for more information
62
+ #
63
+ # See kamal docs env for more information:
62
64
  env:
63
65
  ...
64
66
 
65
67
  # Copying files
66
68
  #
67
69
  # You can specify files to mount into the container.
68
- # The format is `local:remote` where `local` is the path to the file on the local machine
70
+ # The format is `local:remote`, where `local` is the path to the file on the local machine
69
71
  # and `remote` is the path to the file in the container.
70
72
  #
71
73
  # They will be uploaded from the local repo to the host and then mounted.
@@ -78,13 +80,13 @@ accessories:
78
80
  # Directories
79
81
  #
80
82
  # You can specify directories to mount into the container. They will be created on the host
81
- # before being mounted
83
+ # before being mounted:
82
84
  directories:
83
85
  - mysql-logs:/var/log/mysql
84
86
 
85
87
  # Volumes
86
88
  #
87
89
  # Any other volumes to mount, in addition to the files and directories.
88
- # They are not created or copied before mounting
90
+ # They are not created or copied before mounting:
89
91
  volumes:
90
92
  - /path/to/mysql-logs:/var/log/mysql
@@ -12,15 +12,15 @@
12
12
  aliases:
13
13
  console: app exec -r console -i "rails console"
14
14
  # You can now open the console with:
15
+ #
15
16
  # ```shell
16
17
  # kamal console
17
18
  # ```
18
19
 
19
20
  # Configuring aliases
20
21
  #
21
- # Aliases are defined in the root config under the alias key
22
+ # Aliases are defined in the root config under the alias key.
22
23
  #
23
- # Each alias is named and can only contain lowercase letters, numbers, dashes and underscores.
24
-
24
+ # Each alias is named and can only contain lowercase letters, numbers, dashes, and underscores:
25
25
  aliases:
26
26
  uname: app exec -p -q -r web "uname -a"
@@ -2,18 +2,18 @@
2
2
  #
3
3
  # When deploying to large numbers of hosts, you might prefer not to restart your services on every host at the same time.
4
4
  #
5
- # Kamal’s default is to boot new containers on all hosts in parallel. But you can control this with the boot configuration.
5
+ # Kamal’s default is to boot new containers on all hosts in parallel. However, you can control this with the boot configuration.
6
6
 
7
7
  # Fixed group sizes
8
8
  #
9
- # Here we boot 2 hosts at a time with a 10 second gap between each group.
9
+ # Here, we boot 2 hosts at a time with a 10-second gap between each group:
10
10
  boot:
11
11
  limit: 2
12
12
  wait: 10
13
13
 
14
14
  # Percentage of hosts
15
15
  #
16
- # Here we boot 25% of the hosts at a time with a 2 second gap between each group.
16
+ # Here, we boot 25% of the hosts at a time with a 2-second gap between each group:
17
17
  boot:
18
18
  limit: 25%
19
19
  wait: 2
@@ -1,8 +1,8 @@
1
1
  # Builder
2
2
  #
3
- # The builder configuration controls how the application is built with `docker build`
3
+ # The builder configuration controls how the application is built with `docker build`.
4
4
  #
5
- # See https://kamal-deploy.org/docs/configuration/builder-examples/ for more information
5
+ # See https://kamal-deploy.org/docs/configuration/builder-examples/ for more information.
6
6
 
7
7
  # Builder options
8
8
  #
@@ -11,15 +11,15 @@ builder:
11
11
 
12
12
  # Arch
13
13
  #
14
- # The architectures to build for - you can set an array or just a single value.
14
+ # The architectures to build for you can set an array or just a single value.
15
15
  #
16
- # Allowed values are `amd64` and `arm64`
16
+ # Allowed values are `amd64` and `arm64`:
17
17
  arch:
18
18
  - amd64
19
19
 
20
20
  # Remote
21
21
  #
22
- # The connection string for a remote builder. If supplied Kamal will use this
22
+ # The connection string for a remote builder. If supplied, Kamal will use this
23
23
  # for builds that do not match the local architecture of the deployment host.
24
24
  remote: ssh://docker@docker-builder
25
25
 
@@ -28,14 +28,14 @@ builder:
28
28
  # If set to false, Kamal will always use the remote builder even when building
29
29
  # the local architecture.
30
30
  #
31
- # Defaults to true
31
+ # Defaults to true:
32
32
  local: true
33
33
 
34
34
  # Builder cache
35
35
  #
36
- # The type must be either 'gha' or 'registry'
36
+ # The type must be either 'gha' or 'registry'.
37
37
  #
38
- # The image is only used for registry cache. Not compatible with the docker driver
38
+ # The image is only used for registry cache and is not compatible with the Docker driver:
39
39
  cache:
40
40
  type: registry
41
41
  options: mode=max
@@ -43,25 +43,25 @@ builder:
43
43
 
44
44
  # Build context
45
45
  #
46
- # If this is not set, then a local git clone of the repo is used.
46
+ # If this is not set, then a local Git clone of the repo is used.
47
47
  # This ensures a clean build with no uncommitted changes.
48
48
  #
49
- # To use the local checkout instead you can set the context to `.`, or a path to another directory.
49
+ # To use the local checkout instead, you can set the context to `.`, or a path to another directory.
50
50
  context: .
51
51
 
52
52
  # Dockerfile
53
53
  #
54
- # The Dockerfile to use for building, defaults to `Dockerfile`
54
+ # The Dockerfile to use for building, defaults to `Dockerfile`:
55
55
  dockerfile: Dockerfile.production
56
56
 
57
57
  # Build target
58
58
  #
59
- # If not set, then the default target is used
59
+ # If not set, then the default target is used:
60
60
  target: production
61
61
 
62
- # Build Arguments
62
+ # Build arguments
63
63
  #
64
- # Any additional build arguments, passed to `docker build` with `--build-arg <key>=<value>`
64
+ # Any additional build arguments, passed to `docker build` with `--build-arg <key>=<value>`:
65
65
  args:
66
66
  ENVIRONMENT: production
67
67
 
@@ -74,33 +74,31 @@ builder:
74
74
 
75
75
  # Build secrets
76
76
  #
77
- # Values are read from .kamal/secrets.
78
- #
77
+ # Values are read from `.kamal/secrets`:
79
78
  secrets:
80
79
  - SECRET1
81
80
  - SECRET2
82
81
 
83
- # Referencing Build Secrets
82
+ # Referencing build secrets
84
83
  #
85
84
  # ```shell
86
85
  # # Copy Gemfiles
87
86
  # COPY Gemfile Gemfile.lock ./
88
87
  #
89
88
  # # Install dependencies, including private repositories via access token
90
- # # Then remove bundle cache with exposed GITHUB_TOKEN)
89
+ # # Then remove bundle cache with exposed GITHUB_TOKEN
91
90
  # RUN --mount=type=secret,id=GITHUB_TOKEN \
92
91
  # BUNDLE_GITHUB__COM=x-access-token:$(cat /run/secrets/GITHUB_TOKEN) \
93
92
  # bundle install && \
94
93
  # rm -rf /usr/local/bundle/cache
95
94
  # ```
96
95
 
97
-
98
96
  # SSH
99
97
  #
100
- # SSH agent socket or keys to expose to the build
98
+ # SSH agent socket or keys to expose to the build:
101
99
  ssh: default=$SSH_AUTH_SOCK
102
100
 
103
101
  # Driver
104
102
  #
105
- # The build driver to use, defaults to `docker-container`
103
+ # The build driver to use, defaults to `docker-container`:
106
104
  driver: docker
@@ -1,14 +1,13 @@
1
1
  # Kamal Configuration
2
2
  #
3
- # Configuration is read from the `config/deploy.yml`
4
- #
3
+ # Configuration is read from the `config/deploy.yml`.
5
4
 
6
5
  # Destinations
7
6
  #
8
7
  # When running commands, you can specify a destination with the `-d` flag,
9
- # e.g. `kamal deploy -d staging`
8
+ # e.g., `kamal deploy -d staging`.
10
9
  #
11
- # In this case the configuration will also be read from `config/deploy.staging.yml`
10
+ # In this case, the configuration will also be read from `config/deploy.staging.yml`
12
11
  # and merged with the base configuration.
13
12
 
14
13
  # Extensions
@@ -18,10 +17,11 @@
18
17
  # However, you might want to declare a configuration block using YAML anchors
19
18
  # and aliases to avoid repetition.
20
19
  #
21
- # You can use prefix a configuration section with `x-` to indicate that it is an
20
+ # You can prefix a configuration section with `x-` to indicate that it is an
22
21
  # extension. Kamal will ignore the extension and not raise an error.
23
22
 
24
23
  # The service name
24
+ #
25
25
  # This is a required value. It is used as the container name prefix.
26
26
  service: myapp
27
27
 
@@ -32,147 +32,147 @@ image: my-image
32
32
 
33
33
  # Labels
34
34
  #
35
- # Additional labels to add to the container
35
+ # Additional labels to add to the container:
36
36
  labels:
37
37
  my-label: my-value
38
38
 
39
39
  # Volumes
40
40
  #
41
- # Additional volumes to mount into the container
41
+ # Additional volumes to mount into the container:
42
42
  volumes:
43
43
  - /path/on/host:/path/in/container:ro
44
44
 
45
45
  # Registry
46
46
  #
47
- # The Docker registry configuration, see kamal docs registry
47
+ # The Docker registry configuration, see kamal docs registry:
48
48
  registry:
49
49
  ...
50
50
 
51
51
  # Servers
52
52
  #
53
- # The servers to deploy to, optionally with custom roles, see kamal docs servers
53
+ # The servers to deploy to, optionally with custom roles, see kamal docs servers:
54
54
  servers:
55
55
  ...
56
56
 
57
57
  # Environment variables
58
58
  #
59
- # See kamal docs env
59
+ # See kamal docs env:
60
60
  env:
61
61
  ...
62
62
 
63
- # Asset Path
63
+ # Asset path
64
64
  #
65
- # Used for asset bridging across deployments, default to `nil`
65
+ # Used for asset bridging across deployments, default to `nil`.
66
66
  #
67
67
  # If there are changes to CSS or JS files, we may get requests
68
- # for the old versions on the new container and vice-versa.
68
+ # for the old versions on the new container, and vice versa.
69
69
  #
70
- # To avoid 404s we can specify an asset path.
70
+ # To avoid 404s, we can specify an asset path.
71
71
  # Kamal will replace that path in the container with a mapped
72
72
  # volume containing both sets of files.
73
73
  # This requires that file names change when the contents change
74
- # (e.g. by including a hash of the contents in the name).
74
+ # (e.g., by including a hash of the contents in the name).
75
75
  #
76
76
  # To configure this, set the path to the assets:
77
77
  asset_path: /path/to/assets
78
78
 
79
79
  # Hooks path
80
80
  #
81
- # Path to hooks, defaults to `.kamal/hooks`
82
- # See https://kamal-deploy.org/docs/hooks for more information
81
+ # Path to hooks, defaults to `.kamal/hooks`.
82
+ # See https://kamal-deploy.org/docs/hooks for more information:
83
83
  hooks_path: /user_home/kamal/hooks
84
84
 
85
85
  # Require destinations
86
86
  #
87
- # Whether deployments require a destination to be specified, defaults to `false`
87
+ # Whether deployments require a destination to be specified, defaults to `false`:
88
88
  require_destination: true
89
89
 
90
90
  # Primary role
91
91
  #
92
- # This defaults to `web`, but if you have no web role, you can change this
92
+ # This defaults to `web`, but if you have no web role, you can change this:
93
93
  primary_role: workers
94
94
 
95
95
  # Allowing empty roles
96
96
  #
97
- # Whether roles with no servers are allowed. Defaults to `false`.
97
+ # Whether roles with no servers are allowed. Defaults to `false`:
98
98
  allow_empty_roles: false
99
99
 
100
100
  # Retain containers
101
101
  #
102
- # How many old containers and images we retain, defaults to 5
102
+ # How many old containers and images we retain, defaults to 5:
103
103
  retain_containers: 3
104
104
 
105
105
  # Minimum version
106
106
  #
107
- # The minimum version of Kamal required to deploy this configuration, defaults to nil
107
+ # The minimum version of Kamal required to deploy this configuration, defaults to `nil`:
108
108
  minimum_version: 1.3.0
109
109
 
110
110
  # Readiness delay
111
111
  #
112
- # Seconds to wait for a container to boot after is running, default 7
112
+ # Seconds to wait for a container to boot after it is running, default 7.
113
113
  #
114
- # This only applies to containers that do not run a proxy or specify a healthcheck
114
+ # This only applies to containers that do not run a proxy or specify a healthcheck:
115
115
  readiness_delay: 4
116
116
 
117
117
  # Deploy timeout
118
118
  #
119
- # How long to wait for a container to become ready, default 30
119
+ # How long to wait for a container to become ready, default 30:
120
120
  deploy_timeout: 10
121
121
 
122
122
  # Drain timeout
123
123
  #
124
- # How long to wait for a containers to drain, default 30
124
+ # How long to wait for a container to drain, default 30:
125
125
  drain_timeout: 10
126
126
 
127
127
  # Run directory
128
128
  #
129
- # Directory to store kamal runtime files in on the host, default `.kamal`
129
+ # Directory to store kamal runtime files in on the host, default `.kamal`:
130
130
  run_directory: /etc/kamal
131
131
 
132
132
  # SSH options
133
133
  #
134
- # See kamal docs ssh
134
+ # See kamal docs ssh:
135
135
  ssh:
136
136
  ...
137
137
 
138
138
  # Builder options
139
139
  #
140
- # See kamal docs builder
140
+ # See kamal docs builder:
141
141
  builder:
142
142
  ...
143
143
 
144
144
  # Accessories
145
145
  #
146
- # Additionals services to run in Docker, see kamal docs accessory
146
+ # Additional services to run in Docker, see kamal docs accessory:
147
147
  accessories:
148
148
  ...
149
149
 
150
150
  # Proxy
151
151
  #
152
- # Configuration for kamal-proxy, see kamal docs proxy
152
+ # Configuration for kamal-proxy, see kamal docs proxy:
153
153
  proxy:
154
154
  ...
155
155
 
156
156
  # SSHKit
157
157
  #
158
- # See kamal docs sshkit
158
+ # See kamal docs sshkit:
159
159
  sshkit:
160
160
  ...
161
161
 
162
162
  # Boot options
163
163
  #
164
- # See kamal docs boot
164
+ # See kamal docs boot:
165
165
  boot:
166
166
  ...
167
167
 
168
168
  # Logging
169
169
  #
170
- # Docker logging configuration, see kamal docs logging
170
+ # Docker logging configuration, see kamal docs logging:
171
171
  logging:
172
172
  ...
173
173
 
174
174
  # Aliases
175
175
  #
176
- # Alias configuration, see kamal docs alias
176
+ # Alias configuration, see kamal docs alias:
177
177
  aliases:
178
178
  ...
@@ -1,13 +1,13 @@
1
1
  # Environment variables
2
2
  #
3
3
  # Environment variables can be set directly in the Kamal configuration or
4
- # read from .kamal/secrets.
4
+ # read from `.kamal/secrets`.
5
5
 
6
6
  # Reading environment variables from the configuration
7
7
  #
8
8
  # Environment variables can be set directly in the configuration file.
9
9
  #
10
- # These are passed to the docker run command when deploying.
10
+ # These are passed to the `docker run` command when deploying.
11
11
  env:
12
12
  DATABASE_HOST: mysql-db1
13
13
  DATABASE_PORT: 3306
@@ -16,7 +16,7 @@ env:
16
16
  #
17
17
  # Kamal uses dotenv to automatically load environment variables set in the `.kamal/secrets` file.
18
18
  #
19
- # If you are using destinations, secrets will instead be read from `.kamal/secrets-<DESTINATION>` if
19
+ # If you are using destinations, secrets will instead be read from `.kamal/secrets.<DESTINATION>` if
20
20
  # it exists.
21
21
  #
22
22
  # Common secrets across all destinations can be set in `.kamal/secrets-common`.
@@ -24,26 +24,27 @@ env:
24
24
  # This file can be used to set variables like `KAMAL_REGISTRY_PASSWORD` or database passwords.
25
25
  # You can use variable or command substitution in the secrets file.
26
26
  #
27
- # ```
27
+ # ```shell
28
28
  # KAMAL_REGISTRY_PASSWORD=$KAMAL_REGISTRY_PASSWORD
29
29
  # RAILS_MASTER_KEY=$(cat config/master.key)
30
30
  # ```
31
31
  #
32
- # You can also use [secret helpers](../commands/secrets) for some common password managers.
33
- # ```
32
+ # You can also use [secret helpers](../../commands/secrets) for some common password managers.
33
+ #
34
+ # ```shell
34
35
  # SECRETS=$(kamal secrets fetch ...)
35
36
  #
36
37
  # REGISTRY_PASSWORD=$(kamal secrets extract REGISTRY_PASSWORD $SECRETS)
37
38
  # DB_PASSWORD=$(kamal secrets extract DB_PASSWORD $SECRETS)
38
39
  # ```
39
40
  #
40
- # If you store secrets directly in .kamal/secrets, ensure that it is not checked into version control.
41
+ # If you store secrets directly in `.kamal/secrets`, ensure that it is not checked into version control.
41
42
  #
42
- # To pass the secrets you should list them under the `secret` key. When you do this the
43
+ # To pass the secrets, you should list them under the `secret` key. When you do this, the
43
44
  # other variables need to be moved under the `clear` key.
44
45
  #
45
- # Unlike clear values, secrets are not passed directly to the container,
46
- # but are stored in an env file on the host
46
+ # Unlike clear values, secrets are not passed directly to the container
47
+ # but are stored in an env file on the host:
47
48
  env:
48
49
  clear:
49
50
  DB_USER: app
@@ -55,7 +56,7 @@ env:
55
56
  # Tags are used to add extra env variables to specific hosts.
56
57
  # See kamal docs servers for how to tag hosts.
57
58
  #
58
- # Tags are only allowed in the top level env configuration (i.e not under a role specific env).
59
+ # Tags are only allowed in the top-level env configuration (i.e., not under a role-specific env).
59
60
  #
60
61
  # The env variables can be specified with secret and clear values as explained above.
61
62
  env:
@@ -6,16 +6,16 @@
6
6
  #
7
7
  # These go under the logging key in the configuration file.
8
8
  #
9
- # This can be specified in the root level or for a specific role.
9
+ # This can be specified at the root level or for a specific role.
10
10
  logging:
11
11
 
12
12
  # Driver
13
13
  #
14
- # The logging driver to use, passed to Docker via `--log-driver`
14
+ # The logging driver to use, passed to Docker via `--log-driver`:
15
15
  driver: json-file
16
16
 
17
17
  # Options
18
18
  #
19
- # Any logging options to pass to the driver, passed to Docker via `--log-opt`
19
+ # Any logging options to pass to the driver, passed to Docker via `--log-opt`:
20
20
  options:
21
21
  max-size: 100m
@@ -5,54 +5,59 @@
5
5
  # application container.
6
6
  #
7
7
  # The proxy is configured in the root configuration under `proxy`. These are
8
- # options that are set when deploying the application, not when booting the proxy
8
+ # options that are set when deploying the application, not when booting the proxy.
9
9
  #
10
- # They are application specific, so are not shared when multiple applications
10
+ # They are application-specific, so they are not shared when multiple applications
11
11
  # run on the same proxy.
12
12
  #
13
- # The proxy is enabled by default on the primary role, but can be disabled by
13
+ # The proxy is enabled by default on the primary role but can be disabled by
14
14
  # setting `proxy: false`.
15
15
  #
16
- # It is disabled by default on all other roles, but can be enabled by setting
17
- # `proxy: true`, or providing a proxy configuration.
16
+ # It is disabled by default on all other roles but can be enabled by setting
17
+ # `proxy: true` or providing a proxy configuration.
18
18
  proxy:
19
19
 
20
- # Host
20
+ # Hosts
21
21
  #
22
22
  # The hosts that will be used to serve the app. The proxy will only route requests
23
23
  # to this host to your app.
24
24
  #
25
25
  # If no hosts are set, then all requests will be forwarded, except for matching
26
26
  # requests for other apps deployed on that server that do have a host set.
27
+ #
28
+ # Specify one of `host` or `hosts`.
27
29
  host: foo.example.com
30
+ hosts:
31
+ - foo.example.com
32
+ - bar.example.com
28
33
 
29
34
  # App port
30
35
  #
31
- # The port the application container is exposed on
36
+ # The port the application container is exposed on.
32
37
  #
33
- # Defaults to 80
38
+ # Defaults to 80:
34
39
  app_port: 3000
35
40
 
36
41
  # SSL
37
42
  #
38
43
  # kamal-proxy can provide automatic HTTPS for your application via Let's Encrypt.
39
44
  #
40
- # This requires that we are deploying to a one server and the host option is set.
41
- # The host value must point to the server we are deploying to and port 443 must be
45
+ # This requires that we are deploying to one server and the host option is set.
46
+ # The host value must point to the server we are deploying to, and port 443 must be
42
47
  # open for the Let's Encrypt challenge to succeed.
43
48
  #
44
- # Defaults to false
49
+ # Defaults to `false`:
45
50
  ssl: true
46
51
 
47
52
  # Response timeout
48
53
  #
49
- # How long to wait for requests to complete before timing out, defaults to 30 seconds
54
+ # How long to wait for requests to complete before timing out, defaults to 30 seconds:
50
55
  response_timeout: 10
51
56
 
52
57
  # Healthcheck
53
58
  #
54
- # When deploying, the proxy will by default hit /up once every second until we hit
55
- # the deploy timeout, with a 5 second timeout for each request.
59
+ # When deploying, the proxy will by default hit `/up` once every second until we hit
60
+ # the deploy timeout, with a 5-second timeout for each request.
56
61
  #
57
62
  # Once the app is up, the proxy will stop hitting the healthcheck endpoint.
58
63
  healthcheck:
@@ -62,12 +67,12 @@ proxy:
62
67
 
63
68
  # Buffering
64
69
  #
65
- # Whether to buffer request and response bodies in the proxy
70
+ # Whether to buffer request and response bodies in the proxy.
66
71
  #
67
- # By default buffering is enabled with a max request body size of 1GB and no limit
72
+ # By default, buffering is enabled with a max request body size of 1GB and no limit
68
73
  # for response size.
69
74
  #
70
- # You can also set the memory limit for buffering, which defaults to 1MB, anything
75
+ # You can also set the memory limit for buffering, which defaults to 1MB; anything
71
76
  # larger than that is written to disk.
72
77
  buffering:
73
78
  requests: true
@@ -78,9 +83,9 @@ proxy:
78
83
 
79
84
  # Logging
80
85
  #
81
- # Configure request logging for the proxy
86
+ # Configure request logging for the proxy.
82
87
  # You can specify request and response headers to log.
83
- # By default, Cache-Control, Last-Modified and User-Agent request headers are logged
88
+ # By default, `Cache-Control`, `Last-Modified`, and `User-Agent` request headers are logged:
84
89
  logging:
85
90
  request_headers:
86
91
  - Cache-Control
@@ -91,10 +96,10 @@ proxy:
91
96
 
92
97
  # Forward headers
93
98
  #
94
- # Whether to forward the X-Forwarded-For and X-Forwarded-Proto headers.
99
+ # Whether to forward the `X-Forwarded-For` and `X-Forwarded-Proto` headers.
95
100
  #
96
- # If you are behind a trusted proxy, you can set this to true to forward the headers.
101
+ # If you are behind a trusted proxy, you can set this to `true` to forward the headers.
97
102
  #
98
- # By default kamal-proxy will not forward the headers the ssl option is set to true, and
99
- # will forward them if it is set to false.
103
+ # By default, kamal-proxy will not forward the headers if the `ssl` option is set to `true`, and
104
+ # will forward them if it is set to `false`.
100
105
  forward_headers: true
@@ -1,10 +1,9 @@
1
1
  # Registry
2
2
  #
3
- # The default registry is Docker Hub, but you can change it using registry/server:
3
+ # The default registry is Docker Hub, but you can change it using `registry/server`.
4
4
  #
5
- # A reference to secret (in this case DOCKER_REGISTRY_TOKEN) will look up the secret
6
- # in the local environment.
7
-
5
+ # A reference to a secret (in this case, `DOCKER_REGISTRY_TOKEN`) will look up the secret
6
+ # in the local environment:
8
7
  registry:
9
8
  server: registry.digitalocean.com
10
9
  username:
@@ -13,30 +12,31 @@ registry:
13
12
  - DOCKER_REGISTRY_TOKEN
14
13
 
15
14
  # Using AWS ECR as the container registry
16
- # You will need to have the aws CLI installed locally for this to work.
17
- # AWS ECR’s access token is only valid for 12hrs. In order to not have to manually regenerate the token every time, you can use ERB in the deploy.yml file to shell out to the aws cli command, and obtain the token:
18
-
15
+ #
16
+ # You will need to have the AWS CLI installed locally for this to work.
17
+ # AWS ECR’s access token is only valid for 12 hours. In order to avoid having to manually regenerate the token every time, you can use ERB in the `deploy.yml` file to shell out to the AWS CLI command and obtain the token:
19
18
  registry:
20
19
  server: <your aws account id>.dkr.ecr.<your aws region id>.amazonaws.com
21
20
  username: AWS
22
21
  password: <%= %x(aws ecr get-login-password) %>
23
22
 
24
23
  # Using GCP Artifact Registry as the container registry
25
- # To sign into Artifact Registry, you would need to
24
+ #
25
+ # To sign into Artifact Registry, you need to
26
26
  # [create a service account](https://cloud.google.com/iam/docs/service-accounts-create#creating)
27
27
  # and [set up roles and permissions](https://cloud.google.com/artifact-registry/docs/access-control#permissions).
28
- # Normally, assigning a roles/artifactregistry.writer role should be sufficient.
28
+ # Normally, assigning the `roles/artifactregistry.writer` role should be sufficient.
29
29
  #
30
30
  # Once the service account is ready, you need to generate and download a JSON key and base64 encode it:
31
31
  #
32
32
  # ```shell
33
- # base64 -i /path/to/key.json | tr -d "\\n")
33
+ # base64 -i /path/to/key.json | tr -d "\\n"
34
34
  # ```
35
- # You'll then need to set the KAMAL_REGISTRY_PASSWORD secret to that value.
36
35
  #
37
- # Use the env variable as password along with _json_key_base64 as username.
36
+ # You'll then need to set the `KAMAL_REGISTRY_PASSWORD` secret to that value.
37
+ #
38
+ # Use the environment variable as the password along with `_json_key_base64` as the username.
38
39
  # Here’s the final configuration:
39
-
40
40
  registry:
41
41
  server: <your registry region>-docker.pkg.dev
42
42
  username: _json_key_base64
@@ -46,6 +46,7 @@ registry:
46
46
  # Validating the configuration
47
47
  #
48
48
  # You can validate the configuration by running:
49
+ #
49
50
  # ```shell
50
51
  # kamal registry login
51
52
  # ```
@@ -1,22 +1,21 @@
1
1
  # Roles
2
2
  #
3
3
  # Roles are used to configure different types of servers in the deployment.
4
- # The most common use for this is to run a web servers and job servers.
4
+ # The most common use for this is to run web servers and job servers.
5
5
  #
6
6
  # Kamal expects there to be a `web` role, unless you set a different `primary_role`
7
7
  # in the root configuration.
8
8
 
9
9
  # Role configuration
10
10
  #
11
- # Roles are specified under the servers key
11
+ # Roles are specified under the servers key:
12
12
  servers:
13
13
 
14
14
  # Simple role configuration
15
15
  #
16
+ # This can be a list of hosts if you don't need custom configuration for the role.
16
17
  #
17
- # This can be a list of hosts, if you don't need custom configuration for the role.
18
- #
19
- # You can set tags on the hosts for custom env variables (see kamal docs env)
18
+ # You can set tags on the hosts for custom env variables (see kamal docs env):
20
19
  web:
21
20
  - 172.1.0.1
22
21
  - 172.1.0.2: experiment1
@@ -24,16 +23,16 @@ servers:
24
23
 
25
24
  # Custom role configuration
26
25
  #
27
- # When there are other options to set, the list of hosts goes under the `hosts` key
26
+ # When there are other options to set, the list of hosts goes under the `hosts` key.
28
27
  #
29
- # By default only the primary role uses a proxy.
28
+ # By default, only the primary role uses a proxy.
30
29
  #
31
- # For other roles, you can set it to `proxy: true` enable it and inherit the root proxy
30
+ # For other roles, you can set it to `proxy: true` to enable it and inherit the root proxy
32
31
  # configuration or provide a map of options to override the root configuration.
33
32
  #
34
33
  # For the primary role, you can set `proxy: false` to disable the proxy.
35
34
  #
36
- # You can also set a custom cmd to run in the container, and overwrite other settings
35
+ # You can also set a custom `cmd` to run in the container and overwrite other settings
37
36
  # from the root configuration.
38
37
  workers:
39
38
  hosts:
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # Servers are split into different roles, with each role having its own configuration.
4
4
  #
5
- # For simpler deployments though where all servers are identical, you can just specify a list of servers
5
+ # For simpler deployments, though, where all servers are identical, you can just specify a list of servers.
6
6
  # They will be implicitly assigned to the `web` role.
7
7
  servers:
8
8
  - 172.0.0.1
@@ -19,7 +19,7 @@ servers:
19
19
 
20
20
  # Roles
21
21
  #
22
- # For more complex deployments (e.g. if you are running job hosts), you can specify roles, and configure each separately (see kamal docs role)
22
+ # For more complex deployments (e.g., if you are running job hosts), you can specify roles and configure each separately (see kamal docs role):
23
23
  servers:
24
24
  web:
25
25
  ...
@@ -1,9 +1,9 @@
1
1
  # SSH configuration
2
2
  #
3
- # Kamal uses SSH to connect run commands on your hosts.
4
- # By default it will attempt to connect to the root user on port 22
3
+ # Kamal uses SSH to connect and run commands on your hosts.
4
+ # By default, it will attempt to connect to the root user on port 22.
5
5
  #
6
- # If you are using non-root user, you may need to bootstrap your servers manually, before using them with Kamal. On Ubuntu, you’d do:
6
+ # If you are using a non-root user, you may need to bootstrap your servers manually before using them with Kamal. On Ubuntu, you’d do:
7
7
  #
8
8
  # ```shell
9
9
  # sudo apt update
@@ -12,7 +12,6 @@
12
12
  # sudo usermod -a -G docker app
13
13
  # ```
14
14
 
15
-
16
15
  # SSH options
17
16
  #
18
17
  # The options are specified under the ssh key in the configuration file.
@@ -20,47 +19,52 @@ ssh:
20
19
 
21
20
  # The SSH user
22
21
  #
23
- # Defaults to `root`
24
- #
22
+ # Defaults to `root`:
25
23
  user: app
26
24
 
27
25
  # The SSH port
28
26
  #
29
- # Defaults to 22
27
+ # Defaults to 22:
30
28
  port: "2222"
31
29
 
32
30
  # Proxy host
33
31
  #
34
- # Specified in the form <host> or <user>@<host>
32
+ # Specified in the form <host> or <user>@<host>:
35
33
  proxy: root@proxy-host
36
34
 
37
35
  # Proxy command
38
36
  #
39
- # A custom proxy command, required for older versions of SSH
37
+ # A custom proxy command, required for older versions of SSH:
40
38
  proxy_command: "ssh -W %h:%p user@proxy"
41
39
 
42
40
  # Log level
43
41
  #
44
- # Defaults to `fatal`. Set this to debug if you are having
45
- # SSH connection issues.
42
+ # Defaults to `fatal`. Set this to `debug` if you are having SSH connection issues.
46
43
  log_level: debug
47
44
 
48
- # Keys Only
45
+ # Keys only
49
46
  #
50
- # Set to true to use only private keys from keys and key_data parameters,
51
- # even if ssh-agent offers more identities. This option is intended for
52
- # situations where ssh-agent offers many different identites or you have
53
- # a need to overwrite all identites and force a single one.
47
+ # Set to `true` to use only private keys from the `keys` and `key_data` parameters,
48
+ # even if ssh-agent offers more identities. This option is intended for
49
+ # situations where ssh-agent offers many different identities or you
50
+ # need to overwrite all identities and force a single one.
54
51
  keys_only: false
55
52
 
56
53
  # Keys
57
54
  #
58
- # An array of file names of private keys to use for publickey
59
- # and hostbased authentication
55
+ # An array of file names of private keys to use for public key
56
+ # and host-based authentication:
60
57
  keys: [ "~/.ssh/id.pem" ]
61
58
 
62
- # Key Data
59
+ # Key data
63
60
  #
64
61
  # An array of strings, with each element of the array being
65
62
  # a raw private key in PEM format.
66
63
  key_data: [ "-----BEGIN OPENSSH PRIVATE KEY-----" ]
64
+
65
+ # Config
66
+ #
67
+ # Set to true to load the default OpenSSH config files (~/.ssh/config,
68
+ # /etc/ssh_config), to false ignore config files, or to a file path
69
+ # (or array of paths) to load specific configuration. Defaults to true.
70
+ config: true
@@ -2,8 +2,8 @@
2
2
  #
3
3
  # [SSHKit](https://github.com/capistrano/sshkit) is the SSH toolkit used by Kamal.
4
4
  #
5
- # The default settings should be sufficient for most use cases, but
6
- # when connecting to a large number of hosts you may need to adjust
5
+ # The default, settings should be sufficient for most use cases, but
6
+ # when connecting to a large number of hosts, you may need to adjust.
7
7
 
8
8
  # SSHKit options
9
9
  #
@@ -13,11 +13,11 @@ sshkit:
13
13
  # Max concurrent starts
14
14
  #
15
15
  # Creating SSH connections concurrently can be an issue when deploying to many servers.
16
- # By default Kamal will limit concurrent connection starts to 30 at a time.
16
+ # By default, Kamal will limit concurrent connection starts to 30 at a time.
17
17
  max_concurrent_starts: 10
18
18
 
19
19
  # Pool idle timeout
20
20
  #
21
21
  # Kamal sets a long idle timeout of 900 seconds on connections to try to avoid
22
- # re-connection storms after an idle period, like building an image or waiting for CI.
22
+ # re-connection storms after an idle period, such as building an image or waiting for CI.
23
23
  pool_idle_timeout: 300
@@ -22,14 +22,14 @@ class Kamal::Configuration::Proxy
22
22
  proxy_config.fetch("ssl", false)
23
23
  end
24
24
 
25
- def host
26
- proxy_config["host"]
25
+ def hosts
26
+ proxy_config["hosts"] || proxy_config["host"]&.split(",") || []
27
27
  end
28
28
 
29
29
  def deploy_options
30
30
  {
31
- host: proxy_config["host"],
32
- tls: proxy_config["ssl"] ? true : nil,
31
+ host: hosts,
32
+ tls: proxy_config["ssl"],
33
33
  "deploy-timeout": seconds_duration(config.deploy_timeout),
34
34
  "drain-timeout": seconds_duration(config.drain_timeout),
35
35
  "health-check-interval": seconds_duration(proxy_config.dig("healthcheck", "interval")),
@@ -48,11 +48,7 @@ class Kamal::Configuration::Proxy
48
48
  end
49
49
 
50
50
  def deploy_command_args(target:)
51
- optionize ({ target: "#{target}:#{app_port}" }).merge(deploy_options)
52
- end
53
-
54
- def remove_command_args(target:)
55
- optionize({ target: "#{target}:#{app_port}" })
51
+ optionize ({ target: "#{target}:#{app_port}" }).merge(deploy_options), with: "="
56
52
  end
57
53
 
58
54
  def merge(other)
@@ -0,0 +1,67 @@
1
+ class Kamal::Configuration::Proxy
2
+ include Kamal::Configuration::Validation
3
+
4
+ DEFAULT_LOG_REQUEST_HEADERS = [ "Cache-Control", "Last-Modified", "User-Agent" ]
5
+ CONTAINER_NAME = "kamal-proxy"
6
+
7
+ delegate :argumentize, :optionize, to: Kamal::Utils
8
+
9
+ attr_reader :config, :proxy_config
10
+
11
+ def initialize(config:, proxy_config:, context: "proxy")
12
+ @config = config
13
+ @proxy_config = proxy_config
14
+ validate! @proxy_config, with: Kamal::Configuration::Validator::Proxy, context: context
15
+ end
16
+
17
+ def app_port
18
+ proxy_config.fetch("app_port", 80)
19
+ end
20
+
21
+ def ssl?
22
+ proxy_config.fetch("ssl", false)
23
+ end
24
+
25
+ def hosts
26
+ proxy_config["hosts"] || proxy_config["host"]&.split(",") || []
27
+ end
28
+
29
+ def deploy_options
30
+ {
31
+ <<<<<<< HEAD
32
+ host: hosts,
33
+ tls: proxy_config["ssl"] ? true : nil,
34
+ =======
35
+ host: proxy_config["host"],
36
+ tls: proxy_config["ssl"],
37
+ >>>>>>> 530d2cb (Use `=` in kamal-proxy deploy command args)
38
+ "deploy-timeout": seconds_duration(config.deploy_timeout),
39
+ "drain-timeout": seconds_duration(config.drain_timeout),
40
+ "health-check-interval": seconds_duration(proxy_config.dig("healthcheck", "interval")),
41
+ "health-check-timeout": seconds_duration(proxy_config.dig("healthcheck", "timeout")),
42
+ "health-check-path": proxy_config.dig("healthcheck", "path"),
43
+ "target-timeout": seconds_duration(proxy_config["response_timeout"]),
44
+ "buffer-requests": proxy_config.fetch("buffering", { "requests": true }).fetch("requests", true),
45
+ "buffer-responses": proxy_config.fetch("buffering", { "responses": true }).fetch("responses", true),
46
+ "buffer-memory": proxy_config.dig("buffering", "memory"),
47
+ "max-request-body": proxy_config.dig("buffering", "max_request_body"),
48
+ "max-response-body": proxy_config.dig("buffering", "max_response_body"),
49
+ "forward-headers": proxy_config.dig("forward_headers"),
50
+ "log-request-header": proxy_config.dig("logging", "request_headers") || DEFAULT_LOG_REQUEST_HEADERS,
51
+ "log-response-header": proxy_config.dig("logging", "response_headers")
52
+ }.compact
53
+ end
54
+
55
+ def deploy_command_args(target:)
56
+ optionize ({ target: "#{target}:#{app_port}" }).merge(deploy_options), with: "="
57
+ end
58
+
59
+ def merge(other)
60
+ self.class.new config: config, proxy_config: proxy_config.deep_merge(other.proxy_config)
61
+ end
62
+
63
+ private
64
+ def seconds_duration(value)
65
+ value ? "#{value}s" : nil
66
+ end
67
+ end
@@ -3,9 +3,13 @@ class Kamal::Configuration::Validator::Proxy < Kamal::Configuration::Validator
3
3
  unless config.nil?
4
4
  super
5
5
 
6
- if config["host"].blank? && config["ssl"]
6
+ if config["host"].blank? && config["hosts"].blank? && config["ssl"]
7
7
  error "Must set a host to enable automatic SSL"
8
8
  end
9
+
10
+ if (config.keys & [ "host", "hosts" ]).size > 1
11
+ error "Specify one of 'host' or 'hosts', not both"
12
+ end
9
13
  end
10
14
  end
11
15
  end
@@ -14,12 +14,14 @@ class Kamal::Configuration
14
14
 
15
15
  include Validation
16
16
 
17
- PROXY_MINIMUM_VERSION = "v0.6.0"
17
+ PROXY_MINIMUM_VERSION = "v0.7.0"
18
18
  PROXY_HTTP_PORT = 80
19
19
  PROXY_HTTPS_PORT = 443
20
20
 
21
21
  class << self
22
22
  def create_from(config_file:, destination: nil, version: nil)
23
+ ENV["KAMAL_DESTINATION"] = destination
24
+
23
25
  raw_config = load_config_files(config_file, *destination_config_file(config_file, destination))
24
26
 
25
27
  new raw_config, destination: destination, version: version
@@ -360,7 +362,7 @@ class Kamal::Configuration
360
362
  end
361
363
 
362
364
  def ensure_unique_hosts_for_ssl_roles
363
- hosts = roles.select(&:ssl?).map { |role| role.proxy.host }
365
+ hosts = roles.select(&:ssl?).flat_map { |role| role.proxy.hosts }
364
366
  duplicates = hosts.tally.filter_map { |host, count| host if count > 1 }
365
367
 
366
368
  raise Kamal::ConfigurationError, "Different roles can't share the same host for SSL: #{duplicates.join(", ")}" if duplicates.any?
@@ -35,8 +35,10 @@ class Kamal::Secrets::Adapters::Bitwarden < Kamal::Secrets::Adapters::Base
35
35
  value = item_field["value"]
36
36
  results["#{item}/#{field}"] = value
37
37
  end
38
+ elsif item_json.dig("login", "password")
39
+ results[item] = item_json.dig("login", "password")
38
40
  else
39
- results[item] = item_json["login"]["password"]
41
+ raise RuntimeError, "Item #{item} is not a login type item and no fields were specified"
40
42
  end
41
43
  end
42
44
  end
data/lib/kamal/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Kamal
2
- VERSION = "2.0.0.rc4"
2
+ VERSION = "2.1.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kamal
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.rc4
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-09-26 00:00:00.000000000 Z
11
+ date: 2024-10-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -285,6 +285,7 @@ files:
285
285
  - lib/kamal/configuration/env/tag.rb
286
286
  - lib/kamal/configuration/logging.rb
287
287
  - lib/kamal/configuration/proxy.rb
288
+ - lib/kamal/configuration/proxy.rb.orig
288
289
  - lib/kamal/configuration/registry.rb
289
290
  - lib/kamal/configuration/role.rb
290
291
  - lib/kamal/configuration/servers.rb
@@ -332,9 +333,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
332
333
  version: '0'
333
334
  required_rubygems_version: !ruby/object:Gem::Requirement
334
335
  requirements:
335
- - - ">"
336
+ - - ">="
336
337
  - !ruby/object:Gem::Version
337
- version: 1.3.1
338
+ version: '0'
338
339
  requirements: []
339
340
  rubygems_version: 3.3.22
340
341
  signing_key: