kamal 1.8.2 → 2.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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