Skip to content

Commit

Permalink
Merge pull request #1265 from phoozle/proxy-bind-ip
Browse files Browse the repository at this point in the history
Add proxy boot_config --publish-ip argument
  • Loading branch information
djmb authored Jan 17, 2025
2 parents 620b132 + 1c8a56b commit f1a9a09
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 3 deletions.
3 changes: 2 additions & 1 deletion lib/kamal/cli/proxy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def boot

desc "boot_config <set|get|reset>", "Manage kamal-proxy boot configuration"
option :publish, type: :boolean, default: true, desc: "Publish the proxy ports on the host"
option :publish_host_ip, type: :string, repeatable: true, default: nil, desc: "Host IP address to bind HTTP/HTTPS traffic to. Defaults to all interfaces"
option :http_port, type: :numeric, default: Kamal::Configuration::PROXY_HTTP_PORT, desc: "HTTP port to publish on the host"
option :https_port, type: :numeric, default: Kamal::Configuration::PROXY_HTTPS_PORT, desc: "HTTPS port to publish on the host"
option :log_max_size, type: :string, default: Kamal::Configuration::PROXY_LOG_MAX_SIZE, desc: "Max size of proxy logs"
Expand All @@ -31,7 +32,7 @@ def boot_config(subcommand)
case subcommand
when "set"
boot_options = [
*(KAMAL.config.proxy_publish_args(options[:http_port], options[:https_port]) if options[:publish]),
*(KAMAL.config.proxy_publish_args(options[:http_port], options[:https_port], options[:publish_host_ip]) if options[:publish]),
*(KAMAL.config.proxy_logging_args(options[:log_max_size])),
*options[:docker_options].map { |option| "--#{option}" }
]
Expand Down
30 changes: 28 additions & 2 deletions lib/kamal/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,16 @@ def env_tag(name)
env_tags.detect { |t| t.name == name.to_s }
end

def proxy_publish_args(http_port, https_port)
argumentize "--publish", [ "#{http_port}:#{PROXY_HTTP_PORT}", "#{https_port}:#{PROXY_HTTPS_PORT}" ]
def proxy_publish_args(http_port, https_port, bind_ips = nil)
ensure_valid_bind_ips(bind_ips)

(bind_ips || [ nil ]).map do |bind_ip|
bind_ip = format_bind_ip(bind_ip)
publish_http = [ bind_ip, http_port, PROXY_HTTP_PORT ].compact.join(":")
publish_https = [ bind_ip, https_port, PROXY_HTTPS_PORT ].compact.join(":")

argumentize "--publish", [ publish_http, publish_https ]
end.join(" ")
end

def proxy_logging_args(max_size)
Expand Down Expand Up @@ -344,6 +352,15 @@ def ensure_valid_kamal_version
true
end

def ensure_valid_bind_ips(bind_ips)
bind_ips.present? && bind_ips.each do |ip|
next if ip =~ Resolv::IPv4::Regex || ip =~ Resolv::IPv6::Regex
raise ArgumentError, "Invalid publish IP address: #{ip}"
end

true
end

def ensure_retain_containers_valid
raise Kamal::ConfigurationError, "Must retain at least 1 container" if retain_containers < 1

Expand Down Expand Up @@ -375,6 +392,15 @@ def ensure_unique_hosts_for_ssl_roles
true
end

def format_bind_ip(ip)
# Ensure IPv6 address inside square brackets - e.g. [::1]
if ip =~ Resolv::IPv6::Regex && ip !~ /\[.*\]/
"[#{ip}]"
else
ip
end
end

def role_names
raw_config.servers.is_a?(Array) ? [ "web" ] : raw_config.servers.keys.sort
end
Expand Down
26 changes: 26 additions & 0 deletions test/cli/proxy_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,32 @@ class CliProxyTest < CliTestCase
end
end

test "boot_config set bind IP" do
run_command("boot_config", "set", "--publish-host-ip", "127.0.0.1").tap do |output|
%w[ 1.1.1.1 1.1.1.2 ].each do |host|
assert_match "Running /usr/bin/env mkdir -p .kamal/proxy on #{host}", output
assert_match "Uploading \"--publish 127.0.0.1:80:80 --publish 127.0.0.1:443:443 --log-opt max-size=10m\" to .kamal/proxy/options on #{host}", output
end
end
end

test "boot_config set multiple bind IPs" do
run_command("boot_config", "set", "--publish-host-ip", "127.0.0.1", "--publish-host-ip", "::1").tap do |output|
%w[ 1.1.1.1 1.1.1.2 ].each do |host|
assert_match "Running /usr/bin/env mkdir -p .kamal/proxy on #{host}", output
assert_match "Uploading \"--publish 127.0.0.1:80:80 --publish 127.0.0.1:443:443 --publish [::1]:80:80 --publish [::1]:443:443 --log-opt max-size=10m\" to .kamal/proxy/options on #{host}", output
end
end
end

test "boot_config set invalid bind IPs" do
exception = assert_raises do
run_command("boot_config", "set", "--publish-host-ip", "1.2.3.invalidIP", "--publish-host-ip", "::1")
end

assert_includes exception.message, "Invalid publish IP address: 1.2.3.invalidIP"
end

test "boot_config set docker options" do
run_command("boot_config", "set", "--docker_options", "label=foo=bar", "add_host=thishost:thathost").tap do |output|
%w[ 1.1.1.1 1.1.1.2 ].each do |host|
Expand Down

0 comments on commit f1a9a09

Please sign in to comment.