kamal 1.8.2 → 2.0.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/kamal/cli/accessory.rb +44 -20
  4. data/lib/kamal/cli/alias/command.rb +9 -0
  5. data/lib/kamal/cli/app/boot.rb +22 -16
  6. data/lib/kamal/cli/app.rb +40 -5
  7. data/lib/kamal/cli/base.rb +19 -51
  8. data/lib/kamal/cli/build.rb +12 -13
  9. data/lib/kamal/cli/healthcheck/barrier.rb +2 -0
  10. data/lib/kamal/cli/healthcheck/poller.rb +18 -39
  11. data/lib/kamal/cli/lock.rb +2 -3
  12. data/lib/kamal/cli/main.rb +54 -51
  13. data/lib/kamal/cli/proxy.rb +224 -0
  14. data/lib/kamal/cli/prune.rb +0 -1
  15. data/lib/kamal/cli/secrets.rb +36 -0
  16. data/lib/kamal/cli/server.rb +2 -3
  17. data/lib/kamal/cli/templates/deploy.yml +4 -21
  18. data/lib/kamal/cli/templates/sample_hooks/post-proxy-reboot.sample +3 -0
  19. data/lib/kamal/cli/templates/secrets +16 -0
  20. data/lib/kamal/cli.rb +1 -0
  21. data/lib/kamal/commander/specifics.rb +3 -3
  22. data/lib/kamal/commander.rb +24 -8
  23. data/lib/kamal/commands/accessory.rb +7 -7
  24. data/lib/kamal/commands/app/assets.rb +8 -8
  25. data/lib/kamal/commands/app/proxy.rb +16 -0
  26. data/lib/kamal/commands/app.rb +7 -15
  27. data/lib/kamal/commands/auditor.rb +6 -3
  28. data/lib/kamal/commands/base.rb +8 -0
  29. data/lib/kamal/commands/builder/base.rb +26 -13
  30. data/lib/kamal/commands/builder/hybrid.rb +21 -0
  31. data/lib/kamal/commands/builder/local.rb +14 -0
  32. data/lib/kamal/commands/builder/remote.rb +63 -0
  33. data/lib/kamal/commands/builder.rb +13 -29
  34. data/lib/kamal/commands/docker.rb +4 -0
  35. data/lib/kamal/commands/hook.rb +5 -2
  36. data/lib/kamal/commands/lock.rb +2 -6
  37. data/lib/kamal/commands/proxy.rb +77 -0
  38. data/lib/kamal/commands/prune.rb +1 -9
  39. data/lib/kamal/commands/server.rb +11 -1
  40. data/lib/kamal/configuration/accessory.rb +14 -2
  41. data/lib/kamal/configuration/alias.rb +15 -0
  42. data/lib/kamal/configuration/builder.rb +52 -18
  43. data/lib/kamal/configuration/docs/alias.yml +26 -0
  44. data/lib/kamal/configuration/docs/builder.yml +26 -23
  45. data/lib/kamal/configuration/docs/configuration.yml +22 -16
  46. data/lib/kamal/configuration/docs/env.yml +10 -11
  47. data/lib/kamal/configuration/docs/proxy.yml +100 -0
  48. data/lib/kamal/configuration/docs/registry.yml +4 -2
  49. data/lib/kamal/configuration/docs/role.yml +3 -5
  50. data/lib/kamal/configuration/env/tag.rb +4 -3
  51. data/lib/kamal/configuration/env.rb +10 -17
  52. data/lib/kamal/configuration/proxy.rb +66 -0
  53. data/lib/kamal/configuration/registry.rb +3 -2
  54. data/lib/kamal/configuration/role.rb +63 -94
  55. data/lib/kamal/configuration/validator/alias.rb +15 -0
  56. data/lib/kamal/configuration/validator/builder.rb +4 -0
  57. data/lib/kamal/configuration/validator/proxy.rb +11 -0
  58. data/lib/kamal/configuration/validator.rb +42 -24
  59. data/lib/kamal/configuration.rb +91 -33
  60. data/lib/kamal/env_file.rb +4 -0
  61. data/lib/kamal/secrets/adapters/base.rb +18 -0
  62. data/lib/kamal/secrets/adapters/bitwarden.rb +64 -0
  63. data/lib/kamal/secrets/adapters/last_pass.rb +30 -0
  64. data/lib/kamal/secrets/adapters/one_password.rb +61 -0
  65. data/lib/kamal/secrets/adapters/test.rb +10 -0
  66. data/lib/kamal/secrets/adapters.rb +14 -0
  67. data/lib/kamal/secrets/dotenv/inline_command_substitution.rb +32 -0
  68. data/lib/kamal/secrets.rb +37 -0
  69. data/lib/kamal/sshkit_with_ext.rb +1 -0
  70. data/lib/kamal/utils.rb +28 -0
  71. data/lib/kamal/version.rb +1 -1
  72. data/lib/kamal.rb +3 -1
  73. metadata +32 -23
  74. data/lib/kamal/cli/env.rb +0 -54
  75. data/lib/kamal/cli/templates/sample_hooks/post-traefik-reboot.sample +0 -3
  76. data/lib/kamal/cli/templates/template.env +0 -2
  77. data/lib/kamal/cli/traefik.rb +0 -122
  78. data/lib/kamal/commands/app/cord.rb +0 -22
  79. data/lib/kamal/commands/builder/multiarch/remote.rb +0 -61
  80. data/lib/kamal/commands/builder/multiarch.rb +0 -41
  81. data/lib/kamal/commands/builder/native/cached.rb +0 -25
  82. data/lib/kamal/commands/builder/native/remote.rb +0 -67
  83. data/lib/kamal/commands/builder/native.rb +0 -20
  84. data/lib/kamal/commands/traefik.rb +0 -85
  85. data/lib/kamal/configuration/docs/healthcheck.yml +0 -59
  86. data/lib/kamal/configuration/docs/traefik.yml +0 -62
  87. data/lib/kamal/configuration/healthcheck.rb +0 -63
  88. data/lib/kamal/configuration/traefik.rb +0 -60
  89. /data/lib/kamal/cli/templates/sample_hooks/{pre-traefik-reboot.sample → pre-proxy-reboot.sample} +0 -0
@@ -19,16 +19,38 @@ class Kamal::Configuration::Builder
19
19
  builder_config
20
20
  end
21
21
 
22
- def multiarch?
23
- builder_config["multiarch"] != false
22
+ def remote
23
+ builder_config["remote"]
24
24
  end
25
25
 
26
- def local?
27
- !!builder_config["local"]
26
+ def arches
27
+ Array(builder_config.fetch("arch", default_arch))
28
+ end
29
+
30
+ def local_arches
31
+ @local_arches ||= if local_disabled?
32
+ []
33
+ elsif remote
34
+ arches & [ Kamal::Utils.docker_arch ]
35
+ else
36
+ arches
37
+ end
38
+ end
39
+
40
+ def remote_arches
41
+ @remote_arches ||= if remote
42
+ arches - local_arches
43
+ else
44
+ []
45
+ end
28
46
  end
29
47
 
30
48
  def remote?
31
- !!builder_config["remote"]
49
+ remote_arches.any?
50
+ end
51
+
52
+ def local?
53
+ !local_disabled? && (arches.empty? || local_arches.any?)
32
54
  end
33
55
 
34
56
  def cached?
@@ -40,7 +62,7 @@ class Kamal::Configuration::Builder
40
62
  end
41
63
 
42
64
  def secrets
43
- builder_config["secrets"] || []
65
+ (builder_config["secrets"] || []).to_h { |key| [ key, config.secrets[key] ] }
44
66
  end
45
67
 
46
68
  def dockerfile
@@ -55,20 +77,12 @@ class Kamal::Configuration::Builder
55
77
  builder_config["context"] || "."
56
78
  end
57
79
 
58
- def local_arch
59
- builder_config["local"]["arch"] if local?
60
- end
61
-
62
- def local_host
63
- builder_config["local"]["host"] if local?
80
+ def driver
81
+ builder_config.fetch("driver", "docker-container")
64
82
  end
65
83
 
66
- def remote_arch
67
- builder_config["remote"]["arch"] if remote?
68
- end
69
-
70
- def remote_host
71
- builder_config["remote"]["host"] if remote?
84
+ def local_disabled?
85
+ builder_config["local"] == false
72
86
  end
73
87
 
74
88
  def cache_from
@@ -114,7 +128,23 @@ class Kamal::Configuration::Builder
114
128
  end
115
129
  end
116
130
 
131
+ def docker_driver?
132
+ driver == "docker"
133
+ end
134
+
117
135
  private
136
+ def valid?
137
+ if docker_driver?
138
+ raise ArgumentError, "Invalid builder configuration: the `docker` driver does not not support remote builders" if remote
139
+ raise ArgumentError, "Invalid builder configuration: the `docker` driver does not not support caching" if cached?
140
+ raise ArgumentError, "Invalid builder configuration: the `docker` driver does not not support multiple arches" if arches.many?
141
+ end
142
+
143
+ if @options["cache"] && @options["cache"]["type"]
144
+ raise ArgumentError, "Invalid cache type: #{@options["cache"]["type"]}" unless [ "gha", "registry" ].include?(@options["cache"]["type"])
145
+ end
146
+ end
147
+
118
148
  def cache_image
119
149
  builder_config["cache"]&.fetch("image", nil) || "#{image}-build-cache"
120
150
  end
@@ -150,4 +180,8 @@ class Kamal::Configuration::Builder
150
180
  def pwd_sha
151
181
  Digest::SHA256.hexdigest(Dir.pwd)[0..12]
152
182
  end
183
+
184
+ def default_arch
185
+ docker_driver? ? [] : [ "amd64", "arm64" ]
186
+ end
153
187
  end
@@ -0,0 +1,26 @@
1
+ # Aliases
2
+ #
3
+ # Aliases are shortcuts for Kamal commands.
4
+ #
5
+ # For example, for a Rails app, you might open a console with:
6
+ #
7
+ # ```shell
8
+ # kamal app exec -i -r console "rails console"
9
+ # ```
10
+ #
11
+ # By defining an alias, like this:
12
+ aliases:
13
+ console: app exec -r console -i "rails console"
14
+ # You can now open the console with:
15
+ # ```shell
16
+ # kamal console
17
+ # ```
18
+
19
+ # Configuring aliases
20
+ #
21
+ # Aliases are defined in the root config under the alias key
22
+ #
23
+ # Each alias is named and can only contain lowercase letters, numbers, dashes and underscores.
24
+
25
+ aliases:
26
+ uname: app exec -p -q -r web "uname -a"
@@ -1,10 +1,10 @@
1
1
  # Builder
2
2
  #
3
- # The builder configuration controls how the application is built with `docker build` or `docker buildx build`
3
+ # The builder configuration controls how the application is built with `docker build`
4
4
  #
5
5
  # If no configuration is specified, Kamal will:
6
- # 1. Create a buildx context called `kamal-<service>-multiarch`
7
- # 2. Use `docker buildx build` to build a multiarch image for linux/amd64,linux/arm64 with that context
6
+ # 1. Create a buildx context called `kamal-local-docker-container`, using the docker-container driver
7
+ # 2. Use `docker build` to build a multiarch image for linux/amd64,linux/arm64 with that context
8
8
  #
9
9
  # See https://kamal-deploy.org/docs/configuration/builder-examples/ for more information
10
10
 
@@ -13,35 +13,33 @@
13
13
  # Options go under the builder key in the root configuration.
14
14
  builder:
15
15
 
16
- # Multiarch
16
+ # Arch
17
17
  #
18
- # Enables multiarch builds, defaults to `true`
19
- multiarch: false
20
-
21
- # Local configuration
18
+ # The architectures to build for - you can set an array or just a single value.
22
19
  #
23
- # The build configuration for local builds, only used if multiarch is enabled (the default)
20
+ # Allowed values are `amd64` and `arm64`
21
+ arch:
22
+ - amd64
23
+
24
+ # Remote
24
25
  #
25
- # If there is no remote configuration, by default we build for amd64 and arm64.
26
- # If you only want to build for one architecture, you can specify it here.
27
- # The docker socket is optional and uses the default docker host socket when not specified
28
- local:
29
- arch: amd64
30
- host: /var/run/docker.sock
26
+ # The connection string for a remote builder. If supplied Kamal will use this
27
+ # for builds that do not match the local architecture of the deployment host.
28
+ remote: ssh://docker@docker-builder
31
29
 
32
- # Remote configuration
30
+ # Local
31
+ #
32
+ # If set to false, Kamal will always use the remote builder even when building
33
+ # the local architecture.
33
34
  #
34
- # The build configuration for remote builds, also only used if multiarch is enabled.
35
- # The arch is required and can be either amd64 or arm64.
36
- remote:
37
- arch: arm64
38
- host: ssh://docker@docker-builder
35
+ # Defaults to true
36
+ local: true
39
37
 
40
38
  # Builder cache
41
39
  #
42
40
  # The type must be either 'gha' or 'registry'
43
41
  #
44
- # The image is only used for registry cache
42
+ # The image is only used for registry cache. Not compatible with the docker driver
45
43
  cache:
46
44
  type: registry
47
45
  options: mode=max
@@ -80,7 +78,7 @@ builder:
80
78
 
81
79
  # Build secrets
82
80
  #
83
- # Values are read from the environment.
81
+ # Values are read from the .kamal/secrets.
84
82
  #
85
83
  secrets:
86
84
  - SECRET1
@@ -105,3 +103,8 @@ builder:
105
103
  #
106
104
  # SSH agent socket or keys to expose to the build
107
105
  ssh: default=$SSH_AUTH_SOCK
106
+
107
+ # Driver
108
+ #
109
+ # The build driver to use, defaults to `docker-container`
110
+ driver: docker
@@ -70,7 +70,7 @@ env:
70
70
  # volume containing both sets of files.
71
71
  # This requires that file names change when the contents change
72
72
  # (e.g. by including a hash of the contents in the name).
73
-
73
+ #
74
74
  # To configure this, set the path to the assets:
75
75
  asset_path: /path/to/assets
76
76
 
@@ -93,11 +93,6 @@ primary_role: workers
93
93
  # Whether roles with no servers are allowed. Defaults to `false`.
94
94
  allow_empty_roles: false
95
95
 
96
- # Stop wait time
97
- #
98
- # How long we wait for a container to stop before killing it, defaults to 30 seconds
99
- stop_wait_time: 60
100
-
101
96
  # Retain containers
102
97
  #
103
98
  # How many old containers and images we retain, defaults to 5
@@ -111,9 +106,20 @@ minimum_version: 1.3.0
111
106
  # Readiness delay
112
107
  #
113
108
  # Seconds to wait for a container to boot after is running, default 7
114
- # This only applies to containers that do not specify a healthcheck
109
+ #
110
+ # This only applies to containers that do not run a proxy or specify a healthcheck
115
111
  readiness_delay: 4
116
112
 
113
+ # Deploy timeout
114
+ #
115
+ # How long to wait for a container to become ready, default 30
116
+ deploy_timeout: 10
117
+
118
+ # Drain timeout
119
+ #
120
+ # How long to wait for a containers to drain, default 30
121
+ drain_timeout: 10
122
+
117
123
  # Run directory
118
124
  #
119
125
  # Directory to store kamal runtime files in on the host, default `.kamal`
@@ -137,10 +143,10 @@ builder:
137
143
  accessories:
138
144
  ...
139
145
 
140
- # Traefik
146
+ # Proxy
141
147
  #
142
- # The Traefik proxy is used for zero-downtime deployments, see kamal docs traefik
143
- traefik:
148
+ # Configuration for kamal-proxy, see kamal docs proxy
149
+ proxy:
144
150
  ...
145
151
 
146
152
  # SSHKit
@@ -155,14 +161,14 @@ sshkit:
155
161
  boot:
156
162
  ...
157
163
 
158
- # Healthcheck
159
- #
160
- # Configuring healthcheck commands, intervals and timeouts, see kamal docs healthcheck
161
- healthcheck:
162
- ...
163
-
164
164
  # Logging
165
165
  #
166
166
  # Docker logging configuration, see kamal docs logging
167
167
  logging:
168
168
  ...
169
+
170
+ # Aliases
171
+ #
172
+ # Alias configuration, see kamal docs alias
173
+ aliases:
174
+ ...
@@ -1,7 +1,7 @@
1
1
  # Environment variables
2
2
  #
3
- # Environment variables can be set directory in the Kamal configuration or
4
- # for loaded from a .env file, for secrets that should not be checked into Git.
3
+ # Environment variables can be set directly in the Kamal configuration or
4
+ # read from .kamal/secrets.
5
5
 
6
6
  # Reading environment variables from the configuration
7
7
  #
@@ -12,26 +12,25 @@ env:
12
12
  DATABASE_HOST: mysql-db1
13
13
  DATABASE_PORT: 3306
14
14
 
15
- # Using .env file to load required environment variables
15
+ # Using .kamal/secrets file to load required environment variables
16
16
  #
17
- # Kamal uses dotenv to automatically load environment variables set in the .env file present
18
- # in the application root.
17
+ # Kamal uses dotenv to automatically load environment variables set in the .kamal/secrets file.
19
18
  #
20
19
  # This file can be used to set variables like KAMAL_REGISTRY_PASSWORD or database passwords.
21
- # But for this reason you must ensure that .env files are not checked into Git or included
22
- # in your Dockerfile! The format is just key-value like:
20
+ # You can use variable or command substitution in the secrets file.
21
+ #
23
22
  # ```
24
- # KAMAL_REGISTRY_PASSWORD=pw
25
- # DB_PASSWORD=secret123
23
+ # KAMAL_REGISTRY_PASSWORD=$KAMAL_REGISTRY_PASSWORD
24
+ # RAILS_MASTER_KEY=$(cat config/master.key)
26
25
  # ```
27
- # See https://kamal-deploy.org/docs/commands/envify/ for how to use generated .env files.
26
+ #
27
+ # If you store secrets directly in .kamal/secrets, ensure that it is not checked into version control.
28
28
  #
29
29
  # To pass the secrets you should list them under the `secret` key. When you do this the
30
30
  # other variables need to be moved under the `clear` key.
31
31
  #
32
32
  # Unlike clear values, secrets are not passed directly to the container,
33
33
  # but are stored in an env file on the host
34
- # The file is not updated when deploying, only when running `kamal envify` or `kamal env push`.
35
34
  env:
36
35
  clear:
37
36
  DB_USER: app
@@ -0,0 +1,100 @@
1
+ # Proxy
2
+ #
3
+ # Kamal uses [kamal-proxy](https://github.com/basecamp/kamal-proxy) to provide
4
+ # gapless deployments. It runs on ports 80 and 443 and forwards requests to the
5
+ # application container.
6
+ #
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
9
+ #
10
+ # They are application specific, so are not shared when multiple applications
11
+ # run on the same proxy.
12
+ #
13
+ # The proxy is enabled by default on the primary role, but can be disabled by
14
+ # setting `proxy: false`.
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.
18
+ proxy:
19
+
20
+ # Host
21
+ #
22
+ # The hosts that will be used to serve the app. The proxy will only route requests
23
+ # to this host to your app.
24
+ #
25
+ # If no hosts are set, then all requests will be forwarded, except for matching
26
+ # requests for other apps deployed on that server that do have a host set.
27
+ host: foo.example.com
28
+
29
+ # App port
30
+ #
31
+ # The port the application container is exposed on
32
+ #
33
+ # Defaults to 80
34
+ app_port: 3000
35
+
36
+ # SSL
37
+ #
38
+ # kamal-proxy can provide automatic HTTPS for your application via Let's Encrypt.
39
+ #
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
42
+ # open for the Let's Encrypt challenge to succeed.
43
+ #
44
+ # Defaults to false
45
+ ssl: true
46
+
47
+ # Response timeout
48
+ #
49
+ # How long to wait for requests to complete before timing out, defaults to 30 seconds
50
+ response_timeout: 10s
51
+
52
+ # Healthcheck
53
+ #
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.
56
+ #
57
+ # Once the app is up, the proxy will stop hitting the healthcheck endpoint.
58
+ healthcheck:
59
+ interval: 3
60
+ path: /health
61
+ timeout: 3
62
+
63
+ # Buffering
64
+ #
65
+ # Whether to buffer request and response bodies in the proxy
66
+ #
67
+ # By default buffering is enabled with a max request body size of 1GB and no limit
68
+ # for response size.
69
+ #
70
+ # You can also set the memory limit for buffering, which defaults to 1MB, anything
71
+ # larger than that is written to disk.
72
+ buffering:
73
+ requests: true
74
+ responses: true
75
+ max_request_body: 40_000_000
76
+ max_response_body: 0
77
+ memory: 2_000_000
78
+
79
+ # Logging
80
+ #
81
+ # Configure request logging for the proxy
82
+ # You can specify request and response headers to log.
83
+ # By default, Cache-Control, Last-Modified and User-Agent request headers are logged
84
+ logging:
85
+ request_headers:
86
+ - Cache-Control
87
+ - X-Forwarded-Proto
88
+ response_headers:
89
+ - X-Request-ID
90
+ - X-Request-Start
91
+
92
+ # Forward headers
93
+ #
94
+ # Whether to forward the X-Forwarded-For and X-Forwarded-Proto headers (defaults to false)
95
+ #
96
+ # If you are behind a trusted proxy, you can set this to true to forward the headers.
97
+ #
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.
100
+ forward_headers: true
@@ -27,11 +27,13 @@ registry:
27
27
  # and [set up roles and permissions](https://cloud.google.com/artifact-registry/docs/access-control#permissions).
28
28
  # Normally, assigning a roles/artifactregistry.writer role should be sufficient.
29
29
  #
30
- # Once the service account is ready, you need to generate and download a JSON key, base64 encode it and add to .env:
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
- # echo "KAMAL_REGISTRY_PASSWORD=$(base64 -i /path/to/key.json)" | tr -d "\\n" >> .env
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
38
  # Here’s the final configuration:
37
39
 
@@ -26,7 +26,7 @@ servers:
26
26
  #
27
27
  # When there are other options to set, the list of hosts goes under the `hosts` key
28
28
  #
29
- # By default only the primary role uses Traefik, but you can set `traefik` to change
29
+ # By default only the primary role uses a proxy, but you can set `proxy` to change
30
30
  # it.
31
31
  #
32
32
  # You can also set a custom cmd to run in the container, and overwrite other settings
@@ -35,18 +35,16 @@ servers:
35
35
  hosts:
36
36
  - 172.1.0.3
37
37
  - 172.1.0.4: experiment1
38
- traefik: true
39
38
  cmd: "bin/jobs"
40
39
  options:
41
40
  memory: 2g
42
41
  cpus: 4
43
- healthcheck:
44
- ...
45
42
  logging:
46
43
  ...
44
+ proxy:
45
+ ...
47
46
  labels:
48
47
  my-label: workers
49
48
  env:
50
49
  ...
51
50
  asset_path: /public
52
-
@@ -1,12 +1,13 @@
1
1
  class Kamal::Configuration::Env::Tag
2
- attr_reader :name, :config
2
+ attr_reader :name, :config, :secrets
3
3
 
4
- def initialize(name, config:)
4
+ def initialize(name, config:, secrets:)
5
5
  @name = name
6
6
  @config = config
7
+ @secrets = secrets
7
8
  end
8
9
 
9
10
  def env
10
- Kamal::Configuration::Env.new(config: config)
11
+ Kamal::Configuration::Env.new(config: config, secrets: secrets)
11
12
  end
12
13
  end
@@ -1,36 +1,29 @@
1
1
  class Kamal::Configuration::Env
2
2
  include Kamal::Configuration::Validation
3
3
 
4
- attr_reader :secrets_keys, :clear, :secrets_file, :context
4
+ attr_reader :context, :secrets
5
+ attr_reader :clear, :secret_keys
5
6
  delegate :argumentize, to: Kamal::Utils
6
7
 
7
- def initialize(config:, secrets_file: nil, context: "env")
8
+ def initialize(config:, secrets:, context: "env")
8
9
  @clear = config.fetch("clear", config.key?("secret") || config.key?("tags") ? {} : config)
9
- @secrets_keys = config.fetch("secret", [])
10
- @secrets_file = secrets_file
10
+ @secrets = secrets
11
+ @secret_keys = config.fetch("secret", [])
11
12
  @context = context
12
13
  validate! config, context: context, with: Kamal::Configuration::Validator::Env
13
14
  end
14
15
 
15
- def args
16
- [ "--env-file", secrets_file, *argumentize("--env", clear) ]
16
+ def clear_args
17
+ argumentize("--env", clear)
17
18
  end
18
19
 
19
20
  def secrets_io
20
- StringIO.new(Kamal::EnvFile.new(secrets).to_s)
21
- end
22
-
23
- def secrets
24
- @secrets ||= secrets_keys.to_h { |key| [ key, ENV.fetch(key) ] }
25
- end
26
-
27
- def secrets_directory
28
- File.dirname(secrets_file)
21
+ Kamal::EnvFile.new(secret_keys.to_h { |key| [ key, secrets[key] ] }).to_io
29
22
  end
30
23
 
31
24
  def merge(other)
32
25
  self.class.new \
33
- config: { "clear" => clear.merge(other.clear), "secret" => secrets_keys | other.secrets_keys },
34
- secrets_file: secrets_file || other.secrets_file
26
+ config: { "clear" => clear.merge(other.clear), "secret" => secret_keys | other.secret_keys },
27
+ secrets: secrets
35
28
  end
36
29
  end
@@ -0,0 +1,66 @@
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 host
26
+ proxy_config["host"]
27
+ end
28
+
29
+ def deploy_options
30
+ {
31
+ host: proxy_config["host"],
32
+ tls: proxy_config["ssl"],
33
+ "deploy-timeout": seconds_duration(config.deploy_timeout),
34
+ "drain-timeout": seconds_duration(config.drain_timeout),
35
+ "health-check-interval": seconds_duration(proxy_config.dig("healthcheck", "interval")),
36
+ "health-check-timeout": seconds_duration(proxy_config.dig("healthcheck", "timeout")),
37
+ "health-check-path": proxy_config.dig("healthcheck", "path"),
38
+ "target-timeout": seconds_duration(proxy_config["response_timeout"]),
39
+ "buffer-requests": proxy_config.fetch("buffering", { "requests": true }).fetch("requests", true),
40
+ "buffer-responses": proxy_config.fetch("buffering", { "responses": true }).fetch("responses", true),
41
+ "buffer-memory": proxy_config.dig("buffering", "memory"),
42
+ "max-request-body": proxy_config.dig("buffering", "max_request_body"),
43
+ "max-response-body": proxy_config.dig("buffering", "max_response_body"),
44
+ "forward-headers": proxy_config.dig("forward_headers"),
45
+ "log-request-header": proxy_config.dig("logging", "request_headers") || DEFAULT_LOG_REQUEST_HEADERS,
46
+ "log-response-header": proxy_config.dig("logging", "response_headers")
47
+ }.compact
48
+ end
49
+
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}" })
56
+ end
57
+
58
+ def merge(other)
59
+ self.class.new config: config, proxy_config: proxy_config.deep_merge(other.proxy_config)
60
+ end
61
+
62
+ private
63
+ def seconds_duration(value)
64
+ value ? "#{value}s" : nil
65
+ end
66
+ end
@@ -1,10 +1,11 @@
1
1
  class Kamal::Configuration::Registry
2
2
  include Kamal::Configuration::Validation
3
3
 
4
- attr_reader :registry_config
4
+ attr_reader :registry_config, :secrets
5
5
 
6
6
  def initialize(config:)
7
7
  @registry_config = config.raw_config.registry || {}
8
+ @secrets = config.secrets
8
9
  validate! registry_config, with: Kamal::Configuration::Validator::Registry
9
10
  end
10
11
 
@@ -23,7 +24,7 @@ class Kamal::Configuration::Registry
23
24
  private
24
25
  def lookup(key)
25
26
  if registry_config[key].is_a?(Array)
26
- ENV.fetch(registry_config[key].first).dup
27
+ secrets[registry_config[key].first]
27
28
  else
28
29
  registry_config[key]
29
30
  end