dash 2.12.0
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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +13 -0
- data/bin/dash +18 -0
- data/bin/kamal +18 -0
- data/lib/kamal/cli/accessory.rb +342 -0
- data/lib/kamal/cli/alias/command.rb +10 -0
- data/lib/kamal/cli/app/assets.rb +24 -0
- data/lib/kamal/cli/app/boot.rb +126 -0
- data/lib/kamal/cli/app/error_pages.rb +33 -0
- data/lib/kamal/cli/app/ssl_certificates.rb +28 -0
- data/lib/kamal/cli/app.rb +368 -0
- data/lib/kamal/cli/base.rb +324 -0
- data/lib/kamal/cli/build/clone.rb +59 -0
- data/lib/kamal/cli/build/port_forwarding.rb +66 -0
- data/lib/kamal/cli/build.rb +242 -0
- data/lib/kamal/cli/healthcheck/barrier.rb +33 -0
- data/lib/kamal/cli/healthcheck/error.rb +2 -0
- data/lib/kamal/cli/healthcheck/poller.rb +42 -0
- data/lib/kamal/cli/lock.rb +34 -0
- data/lib/kamal/cli/main.rb +299 -0
- data/lib/kamal/cli/proxy.rb +419 -0
- data/lib/kamal/cli/prune.rb +34 -0
- data/lib/kamal/cli/registry.rb +49 -0
- data/lib/kamal/cli/secrets.rb +50 -0
- data/lib/kamal/cli/server.rb +70 -0
- data/lib/kamal/cli/templates/deploy.yml +102 -0
- data/lib/kamal/cli/templates/sample_hooks/docker-setup.sample +3 -0
- data/lib/kamal/cli/templates/sample_hooks/post-app-boot.sample +3 -0
- data/lib/kamal/cli/templates/sample_hooks/post-deploy.sample +14 -0
- data/lib/kamal/cli/templates/sample_hooks/post-proxy-reboot.sample +3 -0
- data/lib/kamal/cli/templates/sample_hooks/pre-app-boot.sample +3 -0
- data/lib/kamal/cli/templates/sample_hooks/pre-build.sample +51 -0
- data/lib/kamal/cli/templates/sample_hooks/pre-connect.sample +47 -0
- data/lib/kamal/cli/templates/sample_hooks/pre-deploy.sample +122 -0
- data/lib/kamal/cli/templates/sample_hooks/pre-proxy-reboot.sample +3 -0
- data/lib/kamal/cli/templates/secrets +22 -0
- data/lib/kamal/cli.rb +9 -0
- data/lib/kamal/commander/specifics.rb +62 -0
- data/lib/kamal/commander.rb +230 -0
- data/lib/kamal/commands/accessory/proxy.rb +16 -0
- data/lib/kamal/commands/accessory.rb +118 -0
- data/lib/kamal/commands/app/assets.rb +51 -0
- data/lib/kamal/commands/app/containers.rb +31 -0
- data/lib/kamal/commands/app/error_pages.rb +9 -0
- data/lib/kamal/commands/app/execution.rb +38 -0
- data/lib/kamal/commands/app/images.rb +13 -0
- data/lib/kamal/commands/app/logging.rb +28 -0
- data/lib/kamal/commands/app/proxy.rb +32 -0
- data/lib/kamal/commands/app.rb +125 -0
- data/lib/kamal/commands/auditor.rb +39 -0
- data/lib/kamal/commands/base.rb +147 -0
- data/lib/kamal/commands/builder/base.rb +143 -0
- data/lib/kamal/commands/builder/clone.rb +32 -0
- data/lib/kamal/commands/builder/cloud.rb +22 -0
- data/lib/kamal/commands/builder/hybrid.rb +21 -0
- data/lib/kamal/commands/builder/local.rb +20 -0
- data/lib/kamal/commands/builder/pack.rb +46 -0
- data/lib/kamal/commands/builder/remote.rb +75 -0
- data/lib/kamal/commands/builder.rb +54 -0
- data/lib/kamal/commands/docker.rb +50 -0
- data/lib/kamal/commands/hook.rb +20 -0
- data/lib/kamal/commands/loadbalancer.rb +130 -0
- data/lib/kamal/commands/lock.rb +70 -0
- data/lib/kamal/commands/proxy.rb +150 -0
- data/lib/kamal/commands/prune.rb +38 -0
- data/lib/kamal/commands/registry.rb +38 -0
- data/lib/kamal/commands/server.rb +15 -0
- data/lib/kamal/commands.rb +2 -0
- data/lib/kamal/configuration/accessory.rb +280 -0
- data/lib/kamal/configuration/alias.rb +15 -0
- data/lib/kamal/configuration/boot.rb +29 -0
- data/lib/kamal/configuration/builder.rb +218 -0
- data/lib/kamal/configuration/docs/accessory.yml +160 -0
- data/lib/kamal/configuration/docs/alias.yml +29 -0
- data/lib/kamal/configuration/docs/boot.yml +21 -0
- data/lib/kamal/configuration/docs/builder.yml +132 -0
- data/lib/kamal/configuration/docs/configuration.yml +228 -0
- data/lib/kamal/configuration/docs/env.yml +118 -0
- data/lib/kamal/configuration/docs/logging.yml +21 -0
- data/lib/kamal/configuration/docs/output.yml +25 -0
- data/lib/kamal/configuration/docs/proxy.yml +207 -0
- data/lib/kamal/configuration/docs/registry.yml +64 -0
- data/lib/kamal/configuration/docs/role.yml +54 -0
- data/lib/kamal/configuration/docs/servers.yml +27 -0
- data/lib/kamal/configuration/docs/ssh.yml +81 -0
- data/lib/kamal/configuration/docs/sshkit.yml +31 -0
- data/lib/kamal/configuration/env/tag.rb +13 -0
- data/lib/kamal/configuration/env.rb +42 -0
- data/lib/kamal/configuration/loadbalancer.rb +34 -0
- data/lib/kamal/configuration/logging.rb +33 -0
- data/lib/kamal/configuration/output.rb +34 -0
- data/lib/kamal/configuration/proxy/boot.rb +124 -0
- data/lib/kamal/configuration/proxy/run.rb +152 -0
- data/lib/kamal/configuration/proxy.rb +156 -0
- data/lib/kamal/configuration/registry.rb +40 -0
- data/lib/kamal/configuration/role.rb +247 -0
- data/lib/kamal/configuration/servers.rb +25 -0
- data/lib/kamal/configuration/ssh.rb +76 -0
- data/lib/kamal/configuration/sshkit.rb +26 -0
- data/lib/kamal/configuration/validation.rb +27 -0
- data/lib/kamal/configuration/validator/accessory.rb +13 -0
- data/lib/kamal/configuration/validator/alias.rb +15 -0
- data/lib/kamal/configuration/validator/builder.rb +15 -0
- data/lib/kamal/configuration/validator/configuration.rb +6 -0
- data/lib/kamal/configuration/validator/env.rb +54 -0
- data/lib/kamal/configuration/validator/proxy.rb +47 -0
- data/lib/kamal/configuration/validator/registry.rb +27 -0
- data/lib/kamal/configuration/validator/role.rb +13 -0
- data/lib/kamal/configuration/validator/servers.rb +7 -0
- data/lib/kamal/configuration/validator.rb +251 -0
- data/lib/kamal/configuration/volume.rb +29 -0
- data/lib/kamal/configuration.rb +465 -0
- data/lib/kamal/docker.rb +30 -0
- data/lib/kamal/env_file.rb +44 -0
- data/lib/kamal/git.rb +37 -0
- data/lib/kamal/otel_shipper.rb +176 -0
- data/lib/kamal/output/base_logger.rb +29 -0
- data/lib/kamal/output/file_logger.rb +51 -0
- data/lib/kamal/output/formatter.rb +36 -0
- data/lib/kamal/output/otel_logger.rb +70 -0
- data/lib/kamal/secrets/adapters/aws_secrets_manager.rb +59 -0
- data/lib/kamal/secrets/adapters/base.rb +33 -0
- data/lib/kamal/secrets/adapters/bitwarden.rb +81 -0
- data/lib/kamal/secrets/adapters/bitwarden_secrets_manager.rb +66 -0
- data/lib/kamal/secrets/adapters/doppler.rb +57 -0
- data/lib/kamal/secrets/adapters/enpass.rb +71 -0
- data/lib/kamal/secrets/adapters/gcp_secret_manager.rb +112 -0
- data/lib/kamal/secrets/adapters/last_pass.rb +40 -0
- data/lib/kamal/secrets/adapters/one_password.rb +104 -0
- data/lib/kamal/secrets/adapters/passbolt.rb +129 -0
- data/lib/kamal/secrets/adapters/test.rb +16 -0
- data/lib/kamal/secrets/adapters.rb +16 -0
- data/lib/kamal/secrets/dotenv/inline_command_substitution.rb +47 -0
- data/lib/kamal/secrets.rb +53 -0
- data/lib/kamal/sshkit_with_ext.rb +273 -0
- data/lib/kamal/tags.rb +40 -0
- data/lib/kamal/utils/sensitive.rb +20 -0
- data/lib/kamal/utils.rb +110 -0
- data/lib/kamal/version.rb +3 -0
- data/lib/kamal.rb +15 -0
- metadata +388 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Roles
|
|
2
|
+
#
|
|
3
|
+
# Roles are used to configure different types of servers in the deployment.
|
|
4
|
+
# The most common use for this is to run web servers and job servers.
|
|
5
|
+
#
|
|
6
|
+
# Kamal expects there to be a `web` role, unless you set a different `primary_role`
|
|
7
|
+
# in the root configuration.
|
|
8
|
+
|
|
9
|
+
# Role configuration
|
|
10
|
+
#
|
|
11
|
+
# Roles are specified under the servers key:
|
|
12
|
+
servers:
|
|
13
|
+
|
|
14
|
+
# Simple role configuration
|
|
15
|
+
#
|
|
16
|
+
# This can be a list of hosts if you don't need custom configuration for the role.
|
|
17
|
+
#
|
|
18
|
+
# You can set tags on the hosts for custom env variables (see kamal docs env):
|
|
19
|
+
web:
|
|
20
|
+
- 172.1.0.1
|
|
21
|
+
- 172.1.0.2: experiment1
|
|
22
|
+
- 172.1.0.2: [ experiment1, experiment2 ]
|
|
23
|
+
|
|
24
|
+
# Custom role configuration
|
|
25
|
+
#
|
|
26
|
+
# When there are other options to set, the list of hosts goes under the `hosts` key.
|
|
27
|
+
#
|
|
28
|
+
# By default, only the primary role uses a proxy.
|
|
29
|
+
#
|
|
30
|
+
# For other roles, you can set it to `proxy: true` to enable it and inherit the root proxy
|
|
31
|
+
# configuration or provide a map of options to override the root configuration.
|
|
32
|
+
#
|
|
33
|
+
# For the primary role, you can set `proxy: false` to disable the proxy.
|
|
34
|
+
#
|
|
35
|
+
# You can also set a custom `cmd` to run in the container and overwrite other settings
|
|
36
|
+
# from the root configuration.
|
|
37
|
+
workers:
|
|
38
|
+
hosts:
|
|
39
|
+
- 172.1.0.3
|
|
40
|
+
- 172.1.0.4: experiment1
|
|
41
|
+
cmd: "bin/jobs"
|
|
42
|
+
stop_timeout: 30
|
|
43
|
+
options:
|
|
44
|
+
memory: 2g
|
|
45
|
+
cpus: 4
|
|
46
|
+
logging:
|
|
47
|
+
...
|
|
48
|
+
proxy:
|
|
49
|
+
...
|
|
50
|
+
labels:
|
|
51
|
+
my-label: workers
|
|
52
|
+
env:
|
|
53
|
+
...
|
|
54
|
+
asset_path: /public
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Servers
|
|
2
|
+
#
|
|
3
|
+
# Servers are split into different roles, with each role having its own configuration.
|
|
4
|
+
#
|
|
5
|
+
# For simpler deployments, though, where all servers are identical, you can just specify a list of servers.
|
|
6
|
+
# They will be implicitly assigned to the `web` role.
|
|
7
|
+
servers:
|
|
8
|
+
- 172.0.0.1
|
|
9
|
+
- 172.0.0.2
|
|
10
|
+
- 172.0.0.3
|
|
11
|
+
|
|
12
|
+
# Tagging servers
|
|
13
|
+
#
|
|
14
|
+
# Servers can be tagged, with the tags used to add custom env variables (see kamal docs env).
|
|
15
|
+
servers:
|
|
16
|
+
- 172.0.0.1
|
|
17
|
+
- 172.0.0.2: experiments
|
|
18
|
+
- 172.0.0.3: [ experiments, three ]
|
|
19
|
+
|
|
20
|
+
# Roles
|
|
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):
|
|
23
|
+
servers:
|
|
24
|
+
web:
|
|
25
|
+
...
|
|
26
|
+
workers:
|
|
27
|
+
...
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# SSH configuration
|
|
2
|
+
#
|
|
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
|
+
#
|
|
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
|
+
#
|
|
8
|
+
# ```shell
|
|
9
|
+
# sudo apt update
|
|
10
|
+
# sudo apt upgrade -y
|
|
11
|
+
# sudo apt install -y docker.io curl git
|
|
12
|
+
# sudo usermod -a -G docker app
|
|
13
|
+
# ```
|
|
14
|
+
|
|
15
|
+
# SSH options
|
|
16
|
+
#
|
|
17
|
+
# The options are specified under the ssh key in the configuration file.
|
|
18
|
+
ssh:
|
|
19
|
+
|
|
20
|
+
# The SSH user
|
|
21
|
+
#
|
|
22
|
+
# Defaults to `root`:
|
|
23
|
+
user: app
|
|
24
|
+
|
|
25
|
+
# The SSH port
|
|
26
|
+
#
|
|
27
|
+
# Defaults to 22:
|
|
28
|
+
port: "2222"
|
|
29
|
+
|
|
30
|
+
# Proxy host
|
|
31
|
+
#
|
|
32
|
+
# Specified in the form <host> or <user>@<host>:
|
|
33
|
+
proxy: root@proxy-host
|
|
34
|
+
|
|
35
|
+
# Proxy command
|
|
36
|
+
#
|
|
37
|
+
# A custom proxy command, required for older versions of SSH:
|
|
38
|
+
proxy_command: "ssh -W %h:%p user@proxy"
|
|
39
|
+
|
|
40
|
+
# Log level
|
|
41
|
+
#
|
|
42
|
+
# Defaults to `fatal`. Set this to `debug` if you are having SSH connection issues.
|
|
43
|
+
log_level: debug
|
|
44
|
+
|
|
45
|
+
# Keys only
|
|
46
|
+
#
|
|
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.
|
|
51
|
+
keys_only: false
|
|
52
|
+
|
|
53
|
+
# Keys
|
|
54
|
+
#
|
|
55
|
+
# An array of file names of private keys to use for public key
|
|
56
|
+
# and host-based authentication:
|
|
57
|
+
keys: [ "~/.ssh/id.pem" ]
|
|
58
|
+
|
|
59
|
+
# Key data
|
|
60
|
+
#
|
|
61
|
+
# An array of strings, with each element of the array being a secret name.
|
|
62
|
+
key_data:
|
|
63
|
+
- SSH_PRIVATE_KEY
|
|
64
|
+
# You can also provide raw private key in PEM format, but this is deprecated.
|
|
65
|
+
key_data:
|
|
66
|
+
- "-----BEGIN OPENSSH PRIVATE KEY----- ..."
|
|
67
|
+
|
|
68
|
+
# Config
|
|
69
|
+
#
|
|
70
|
+
# Set to true to load the default OpenSSH config files (~/.ssh/config,
|
|
71
|
+
# /etc/ssh_config), to false ignore config files, or to a file path
|
|
72
|
+
# (or array of paths) to load specific configuration. Defaults to true.
|
|
73
|
+
config: [ "~/.ssh/myconfig" ]
|
|
74
|
+
|
|
75
|
+
# Forward agent
|
|
76
|
+
#
|
|
77
|
+
# Whether to forward the local SSH agent to the remote host. Defaults to
|
|
78
|
+
# true (sshkit's default). Set to false when connecting through a jump
|
|
79
|
+
# host or tunnel that does not support agent forwarding (for example,
|
|
80
|
+
# Cloudflare Access for Infrastructure with SSH).
|
|
81
|
+
forward_agent: false
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# SSHKit
|
|
2
|
+
#
|
|
3
|
+
# [SSHKit](https://github.com/capistrano/sshkit) is the SSH toolkit used by Kamal.
|
|
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.
|
|
7
|
+
|
|
8
|
+
# SSHKit options
|
|
9
|
+
#
|
|
10
|
+
# The options are specified under the sshkit key in the configuration file.
|
|
11
|
+
sshkit:
|
|
12
|
+
|
|
13
|
+
# Max concurrent starts
|
|
14
|
+
#
|
|
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.
|
|
17
|
+
max_concurrent_starts: 10
|
|
18
|
+
|
|
19
|
+
# Pool idle timeout
|
|
20
|
+
#
|
|
21
|
+
# Kamal sets a long idle timeout of 900 seconds on connections to try to avoid
|
|
22
|
+
# re-connection storms after an idle period, such as building an image or waiting for CI.
|
|
23
|
+
pool_idle_timeout: 300
|
|
24
|
+
|
|
25
|
+
# DNS retry settings
|
|
26
|
+
#
|
|
27
|
+
# Some resolvers (mDNSResponder, systemd-resolved, Tailscale) can drop lookups during
|
|
28
|
+
# bursts of concurrent SSH starts. Kamal will retry DNS failures automatically.
|
|
29
|
+
#
|
|
30
|
+
# Number of retries after the initial attempt. Set to 0 to disable.
|
|
31
|
+
dns_retries: 3
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class Kamal::Configuration::Env::Tag
|
|
2
|
+
attr_reader :name, :config, :secrets
|
|
3
|
+
|
|
4
|
+
def initialize(name, config:, secrets:)
|
|
5
|
+
@name = name
|
|
6
|
+
@config = config
|
|
7
|
+
@secrets = secrets
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def env
|
|
11
|
+
Kamal::Configuration::Env.new(config: config, secrets: secrets)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
class Kamal::Configuration::Env
|
|
2
|
+
include Kamal::Configuration::Validation
|
|
3
|
+
|
|
4
|
+
attr_reader :context, :clear, :secrets, :secret_keys
|
|
5
|
+
delegate :argumentize, to: Kamal::Utils
|
|
6
|
+
|
|
7
|
+
def initialize(config:, secrets:, context: "env")
|
|
8
|
+
@clear = config.fetch("clear", config.key?("secret") || config.key?("tags") ? {} : config)
|
|
9
|
+
@secrets = secrets
|
|
10
|
+
@secret_keys = config.fetch("secret", [])
|
|
11
|
+
@context = context
|
|
12
|
+
validate! config, context: context, with: Kamal::Configuration::Validator::Env
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def clear_args
|
|
16
|
+
argumentize("--env", clear)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def secrets_io
|
|
20
|
+
Kamal::EnvFile.new(aliased_secrets).to_io
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def merge(other)
|
|
24
|
+
self.class.new \
|
|
25
|
+
config: { "clear" => clear.merge(other.clear), "secret" => secret_keys | other.secret_keys },
|
|
26
|
+
secrets: secrets
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def to_h
|
|
30
|
+
clear.merge(aliased_secrets)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
def aliased_secrets
|
|
35
|
+
secret_keys.to_h { |key| extract_alias(key) }.transform_values { |secret_key| secrets[secret_key] }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def extract_alias(key)
|
|
39
|
+
key_name, key_aliased_to = key.split(":", 2)
|
|
40
|
+
[ key_name, key_aliased_to || key_name ]
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
class Kamal::Configuration::Loadbalancer < Kamal::Configuration::Proxy
|
|
2
|
+
CONTAINER_NAME = "load-balancer".freeze
|
|
3
|
+
SHARED_CONTAINER_NAME = "kamal-proxy".freeze
|
|
4
|
+
|
|
5
|
+
def self.validation_config_key
|
|
6
|
+
"proxy"
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def initialize(config:, proxy_config:, secrets:)
|
|
10
|
+
super
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def deploy_options
|
|
14
|
+
opts = super
|
|
15
|
+
|
|
16
|
+
opts[:host] = hosts if hosts.present?
|
|
17
|
+
opts[:tls] = proxy_config["ssl"].presence
|
|
18
|
+
|
|
19
|
+
opts
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def directory
|
|
23
|
+
File.join config.run_directory, "loadbalancer"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def container_name
|
|
27
|
+
on_proxy_host? ? SHARED_CONTAINER_NAME : CONTAINER_NAME
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# When loadbalancer is on a proxy host, it takes over the proxy role
|
|
31
|
+
def on_proxy_host?
|
|
32
|
+
config.proxy_hosts.include?(config.proxy.effective_loadbalancer)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
class Kamal::Configuration::Logging
|
|
2
|
+
delegate :optionize, :argumentize, to: Kamal::Utils
|
|
3
|
+
|
|
4
|
+
include Kamal::Configuration::Validation
|
|
5
|
+
|
|
6
|
+
attr_reader :logging_config
|
|
7
|
+
|
|
8
|
+
def initialize(logging_config:, context: "logging")
|
|
9
|
+
@logging_config = logging_config || {}
|
|
10
|
+
validate! @logging_config, context: context
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def driver
|
|
14
|
+
logging_config["driver"]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def options
|
|
18
|
+
logging_config.fetch("options", {})
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def merge(other)
|
|
22
|
+
self.class.new logging_config: logging_config.deep_merge(other.logging_config)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def args
|
|
26
|
+
if driver.present? || options.present?
|
|
27
|
+
optionize({ "log-driver" => driver }.compact) +
|
|
28
|
+
argumentize("--log-opt", options)
|
|
29
|
+
else
|
|
30
|
+
argumentize("--log-opt", { "max-size" => "10m" })
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
class Kamal::Configuration::Output
|
|
2
|
+
include Kamal::Configuration::Validation
|
|
3
|
+
|
|
4
|
+
LOGGER_TYPES = {
|
|
5
|
+
"otel" => "Kamal::Output::OtelLogger",
|
|
6
|
+
"file" => "Kamal::Output::FileLogger"
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
attr_reader :output_config, :loggers
|
|
10
|
+
|
|
11
|
+
def initialize(config:)
|
|
12
|
+
@config = config
|
|
13
|
+
@output_config = config.raw_config.output || {}
|
|
14
|
+
validate! @output_config unless @output_config.empty?
|
|
15
|
+
@loggers = build_loggers
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def enabled?
|
|
19
|
+
output_config.present?
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def to_h
|
|
23
|
+
output_config
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
def build_loggers
|
|
28
|
+
output_config.filter_map do |key, settings|
|
|
29
|
+
if (klass_name = LOGGER_TYPES[key])
|
|
30
|
+
klass_name.constantize.build(settings: settings || {}, config: @config)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
class Kamal::Configuration::Proxy::Boot
|
|
2
|
+
attr_reader :config
|
|
3
|
+
delegate :argumentize, :optionize, to: Kamal::Utils
|
|
4
|
+
|
|
5
|
+
def initialize(config:)
|
|
6
|
+
@config = config
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def publish_args(http_port, https_port, bind_ips = nil)
|
|
10
|
+
ensure_valid_bind_ips(bind_ips)
|
|
11
|
+
|
|
12
|
+
(bind_ips || [ nil ]).map do |bind_ip|
|
|
13
|
+
bind_ip = format_bind_ip(bind_ip)
|
|
14
|
+
publish_http = [ bind_ip, http_port, Kamal::Configuration::Proxy::Run::DEFAULT_HTTP_PORT ].compact.join(":")
|
|
15
|
+
publish_https = [ bind_ip, https_port, Kamal::Configuration::Proxy::Run::DEFAULT_HTTPS_PORT ].compact.join(":")
|
|
16
|
+
|
|
17
|
+
argumentize "--publish", [ publish_http, publish_https ]
|
|
18
|
+
end.join(" ")
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def logging_args(max_size)
|
|
22
|
+
argumentize "--log-opt", "max-size=#{max_size}" if max_size.present?
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def default_boot_options
|
|
26
|
+
[
|
|
27
|
+
*(publish_args(Kamal::Configuration::Proxy::Run::DEFAULT_HTTP_PORT, Kamal::Configuration::Proxy::Run::DEFAULT_HTTPS_PORT, nil)),
|
|
28
|
+
*(logging_args(Kamal::Configuration::Proxy::Run::DEFAULT_LOG_MAX_SIZE))
|
|
29
|
+
]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def repository_name
|
|
33
|
+
"ghcr.io/mhenrixon"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def image_name
|
|
37
|
+
"kamal-proxy"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def image_default
|
|
41
|
+
"#{repository_name}/#{image_name}"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def container_name
|
|
45
|
+
"kamal-proxy"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def host_directory
|
|
49
|
+
File.join config.run_directory, "proxy"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def options_file
|
|
53
|
+
File.join host_directory, "options"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def image_file
|
|
57
|
+
File.join host_directory, "image"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def image_version_file
|
|
61
|
+
File.join host_directory, "image_version"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def run_command_file
|
|
65
|
+
File.join host_directory, "run_command"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def apps_directory
|
|
69
|
+
File.join host_directory, "apps-config"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def apps_container_directory
|
|
73
|
+
"/home/kamal-proxy/.apps-config"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def apps_volume
|
|
77
|
+
Kamal::Configuration::Volume.new \
|
|
78
|
+
host_path: apps_directory,
|
|
79
|
+
container_path: apps_container_directory
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def app_directory
|
|
83
|
+
File.join apps_directory, config.service_and_destination
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def app_container_directory
|
|
87
|
+
File.join apps_container_directory, config.service_and_destination
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def error_pages_directory
|
|
91
|
+
File.join app_directory, "error_pages"
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def error_pages_container_directory
|
|
95
|
+
File.join app_container_directory, "error_pages"
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def tls_directory
|
|
99
|
+
File.join app_directory, "tls"
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def tls_container_directory
|
|
103
|
+
File.join app_container_directory, "tls"
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
private
|
|
107
|
+
def ensure_valid_bind_ips(bind_ips)
|
|
108
|
+
bind_ips.present? && bind_ips.each do |ip|
|
|
109
|
+
next if ip =~ Resolv::IPv4::Regex || ip =~ Resolv::IPv6::Regex
|
|
110
|
+
raise ArgumentError, "Invalid publish IP address: #{ip}"
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
true
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def format_bind_ip(ip)
|
|
117
|
+
# Ensure IPv6 address inside square brackets - e.g. [::1]
|
|
118
|
+
if ip =~ Resolv::IPv6::Regex && ip !~ /\A\[.*\]\z/
|
|
119
|
+
"[#{ip}]"
|
|
120
|
+
else
|
|
121
|
+
ip
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
class Kamal::Configuration::Proxy::Run
|
|
2
|
+
MINIMUM_VERSION = "v0.9.2.1"
|
|
3
|
+
DEFAULT_HTTP_PORT = 80
|
|
4
|
+
DEFAULT_HTTPS_PORT = 443
|
|
5
|
+
DEFAULT_LOG_MAX_SIZE = "10m"
|
|
6
|
+
|
|
7
|
+
attr_reader :config, :run_config
|
|
8
|
+
delegate :argumentize, :optionize, to: Kamal::Utils
|
|
9
|
+
|
|
10
|
+
def initialize(config, run_config:, context: "proxy/run")
|
|
11
|
+
@config = config
|
|
12
|
+
@run_config = run_config
|
|
13
|
+
@context = context
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def debug?
|
|
17
|
+
run_config.fetch("debug", nil)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def publish?
|
|
21
|
+
run_config.fetch("publish", true)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def http_port
|
|
25
|
+
run_config.fetch("http_port", DEFAULT_HTTP_PORT)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def https_port
|
|
29
|
+
run_config.fetch("https_port", DEFAULT_HTTPS_PORT)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def bind_ips
|
|
33
|
+
run_config.fetch("bind_ips", nil)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def publish_args
|
|
37
|
+
if publish?
|
|
38
|
+
(bind_ips || [ nil ]).map do |bind_ip|
|
|
39
|
+
bind_ip = format_bind_ip(bind_ip)
|
|
40
|
+
publish_http = [ bind_ip, http_port, DEFAULT_HTTP_PORT ].compact.join(":")
|
|
41
|
+
publish_https = [ bind_ip, https_port, DEFAULT_HTTPS_PORT ].compact.join(":")
|
|
42
|
+
|
|
43
|
+
argumentize "--publish", [ publish_http, publish_https ]
|
|
44
|
+
end.join(" ")
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def log_max_size
|
|
49
|
+
run_config.fetch("log_max_size", DEFAULT_LOG_MAX_SIZE)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def logging_args
|
|
53
|
+
argumentize "--log-opt", "max-size=#{log_max_size}" if log_max_size.present?
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def version
|
|
57
|
+
run_config.fetch("version", MINIMUM_VERSION)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def registry
|
|
61
|
+
run_config.fetch("registry", nil)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def repository
|
|
65
|
+
run_config.fetch("repository", "ghcr.io/mhenrixon/kamal-proxy")
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def image
|
|
69
|
+
"#{[ registry, repository ].compact.join("/")}:#{version}"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def container_name
|
|
73
|
+
"kamal-proxy"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def options_args
|
|
77
|
+
if args = run_config["options"]
|
|
78
|
+
optionize args
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def run_command
|
|
83
|
+
[ "kamal-proxy", "run", *optionize(run_command_options) ].join(" ")
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def metrics_port
|
|
87
|
+
run_config["metrics_port"]
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def run_command_options
|
|
91
|
+
{ debug: debug? || nil, "metrics-port": metrics_port }.compact
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def docker_options_args
|
|
95
|
+
[
|
|
96
|
+
*apps_volume_args,
|
|
97
|
+
*publish_args,
|
|
98
|
+
*logging_args,
|
|
99
|
+
*("--expose=#{metrics_port}" if metrics_port.present?),
|
|
100
|
+
*options_args
|
|
101
|
+
].compact
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def host_directory
|
|
105
|
+
File.join config.run_directory, "proxy"
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def apps_directory
|
|
109
|
+
File.join host_directory, "apps-config"
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def apps_container_directory
|
|
113
|
+
"/home/kamal-proxy/.apps-config"
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def apps_volume
|
|
117
|
+
Kamal::Configuration::Volume.new \
|
|
118
|
+
host_path: apps_directory,
|
|
119
|
+
container_path: apps_container_directory
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def apps_volume_args
|
|
123
|
+
[ apps_volume.docker_args ]
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def app_directory
|
|
127
|
+
File.join apps_directory, config.service_and_destination
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def app_container_directory
|
|
131
|
+
File.join apps_container_directory, config.service_and_destination
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def ==(other)
|
|
135
|
+
other.is_a?(self.class) && run_config == other.run_config
|
|
136
|
+
end
|
|
137
|
+
alias_method :eql?, :==
|
|
138
|
+
|
|
139
|
+
def hash
|
|
140
|
+
run_config.hash
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
private
|
|
144
|
+
def format_bind_ip(ip)
|
|
145
|
+
# Ensure IPv6 address inside square brackets - e.g. [::1]
|
|
146
|
+
if ip =~ Resolv::IPv6::Regex && ip !~ /\A\[.*\]\z/
|
|
147
|
+
"[#{ip}]"
|
|
148
|
+
else
|
|
149
|
+
ip
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|