Update proxy and docs for Kamal 2.0/kamal-proxy 0.3.0

Update to kamal-proxy 0.3.0 and improve docs making sure they are in
sync with that version.
This commit is contained in:
Donal McBreen
2024-09-18 14:00:43 +01:00
parent e07ac070aa
commit 34effef70a
11 changed files with 59 additions and 40 deletions

View File

@@ -123,7 +123,7 @@ class Kamal::Cli::Main < Kamal::Cli::Base
end end
end end
desc "docs", "Show Kamal documentation for configuration setting" desc "docs [SECTION]", "Show Kamal configuration documentation"
def docs(section = nil) def docs(section = nil)
case section case section
when NilClass when NilClass

View File

@@ -62,7 +62,7 @@ class Kamal::Cli::Proxy < Kamal::Cli::Base
end end
end end
desc "upgrade", "Upgrade to kamal-proxy on servers (stop container, remove container, start new container, reboot app)" desc "upgrade", "Upgrade to kamal-proxy on servers (stop container, remove container, start new container, reboot app)", hide: true
option :rolling, type: :boolean, default: false, desc: "Reboot proxy on hosts in sequence, rather than in parallel" option :rolling, type: :boolean, default: false, desc: "Reboot proxy on hosts in sequence, rather than in parallel"
option :confirmed, aliases: "-y", type: :boolean, default: false, desc: "Proceed without confirmation question" option :confirmed, aliases: "-y", type: :boolean, default: false, desc: "Proceed without confirmation question"
def upgrade def upgrade

View File

@@ -12,25 +12,25 @@
# #
# Options go under the builder key in the root configuration. # Options go under the builder key in the root configuration.
builder: builder:
# Driver
#
# The build driver to use, defaults to `docker-container`
driver: docker
# Arch # Arch
# #
# The architectures to build for, defaults to `[ amd64, arm64 ]` # The architectures to build for - you can set an array or just a single value.
# Unless you are using the docker driver, when it defaults to the local architecture #
# You can set an array or just a single value # Allowed values are `amd64` and `arm64`
arch: arch:
- amd64 - amd64
# Remote configuration # Remote
# #
# If you have a remote builder, you can configure it here # The connection string for a remote builder. If supplied Kamal will use this
# for builds that do not match the local architecture of the deployment host.
remote: ssh://docker@docker-builder remote: ssh://docker@docker-builder
# Whether to allow local builds # Local
#
# If set to false, Kamal will always use the remote builder even when building
# the local architecture.
# #
# Defaults to true # Defaults to true
local: true local: true
@@ -78,7 +78,7 @@ builder:
# Build secrets # Build secrets
# #
# Values are read from the environment. # Values are read from the .kamal/secrets.
# #
secrets: secrets:
- SECRET1 - SECRET1
@@ -103,3 +103,8 @@ builder:
# #
# SSH agent socket or keys to expose to the build # SSH agent socket or keys to expose to the build
ssh: default=$SSH_AUTH_SOCK ssh: default=$SSH_AUTH_SOCK
# Driver
#
# The build driver to use, defaults to `docker-container`
driver: docker

View File

@@ -1,7 +1,7 @@
# Environment variables # Environment variables
# #
# Environment variables can be set directly in the Kamal configuration or # Environment variables can be set directly in the Kamal configuration or
# loaded from a .env file, for secrets that should not be checked into Git. # read from .kamal/secrets.
# Reading environment variables from the configuration # Reading environment variables from the configuration
# #
@@ -12,19 +12,20 @@ env:
DATABASE_HOST: mysql-db1 DATABASE_HOST: mysql-db1
DATABASE_PORT: 3306 DATABASE_PORT: 3306
# Using .env file to load required environment variables # Using .kamal/secrets file to load required environment variables
# #
# Kamal uses dotenv to automatically load environment variables set in the .env file present # Kamal uses dotenv to automatically load environment variables set in the .kamal/secrets file.
# in the application root.
# #
# This file can be used to set variables like KAMAL_REGISTRY_PASSWORD or database passwords. # This file can be used to set variables like KAMAL_REGISTRY_PASSWORD or database passwords.
# But for this reason you must ensure that .env files are not checked into Git or included # You can use variable or command substitution in the secrets file.
# in your Dockerfile! The format is just key-value like: #
# ``` # ```
# KAMAL_REGISTRY_PASSWORD=pw # KAMAL_REGISTRY_PASSWORD=$KAMAL_REGISTRY_PASSWORD
# DB_PASSWORD=secret123 # RAILS_MASTER_KEY=$(cat config/master.key)
# ``` # ```
# #
# If you store secrets directly in .kamal/secrets, ensure that it is not checked into version control.
#
# To pass the secrets you should list them under the `secret` key. When you do this the # To pass the secrets you should list them under the `secret` key. When you do this the
# other variables need to be moved under the `clear` key. # other variables need to be moved under the `clear` key.
# #

View File

@@ -1,5 +1,9 @@
# Proxy # Proxy
# #
# Kamal uses [kamal-proxy](https://github.com/basecamp/kamal-proxy) to provide
# gapless deployments. It runs on ports 80 and 443 and forwards requests to the
# application container.
#
# The proxy is configured in the root configuration under `proxy`. These are # The proxy is configured in the root configuration under `proxy`. These are
# options that are set when deploying the application, not when booting the proxy # options that are set when deploying the application, not when booting the proxy
# #
@@ -13,20 +17,25 @@ proxy:
# to this host to your app. # to this host to your app.
# #
# If no hosts are set, then all requests will be forwarded, except for matching # If no hosts are set, then all requests will be forwarded, except for matching
# requests for other apps that do have a host set. # requests for other apps deployed on that server that do have a host set.
host: foo.example.com host: foo.example.com
# App port # App port
# #
# The port the application container is exposed on # The port the application container is exposed on
#
# Defaults to 80 # Defaults to 80
app_port: 3000 app_port: 3000
# SSL # SSL
# #
# Kamal Proxy can automatically obtain and renew TLS certificates for your applications. # kamal-proxy can provide automatic HTTPS for your application via Let's Encrypt.
# To ensure this set, the ssl flag. This only works if we are deploying to one server and #
# the host flag is set. # This requires that we are deploying to a one server and the host option is set.
# The host value must point to the server we are deploying to and port 443 must be
# open for the Let's Encrypt challenge to succeed.
#
# Defaults to false
ssl: true ssl: true
# Deploy timeout # Deploy timeout
@@ -36,8 +45,8 @@ proxy:
# Response timeout # Response timeout
# #
# How long to wait for requests to complete before timing out, defaults to 10 seconds # How long to wait for requests to complete before timing out, defaults to 30 seconds
response_timeout: 30s response_timeout: 10s
# Healthcheck # Healthcheck
# #
@@ -70,7 +79,7 @@ proxy:
# #
# Configure request logging for the proxy # Configure request logging for the proxy
# You can specify request and response headers to log. # You can specify request and response headers to log.
# By default, Cache-Control and Last-Modified request headers are logged # By default, Cache-Control, Last-Modified and User-Agent request headers are logged
logging: logging:
request_headers: request_headers:
- Cache-Control - Cache-Control
@@ -84,4 +93,7 @@ proxy:
# Whether to forward the X-Forwarded-For and X-Forwarded-Proto headers (defaults to false) # Whether to forward the X-Forwarded-For and X-Forwarded-Proto headers (defaults to false)
# #
# If you are behind a trusted proxy, you can set this to true to forward the headers. # If you are behind a trusted proxy, you can set this to true to forward the headers.
#
# By default kamal-proxy will not forward the headers the ssl option is set to true, and
# will forward them if it is set to false.
forward_headers: true forward_headers: true

View File

@@ -27,11 +27,13 @@ registry:
# and [set up roles and permissions](https://cloud.google.com/artifact-registry/docs/access-control#permissions). # and [set up roles and permissions](https://cloud.google.com/artifact-registry/docs/access-control#permissions).
# Normally, assigning a roles/artifactregistry.writer role should be sufficient. # Normally, assigning a roles/artifactregistry.writer role should be sufficient.
# #
# Once the service account is ready, you need to generate and download a JSON key, base64 encode it and add to .env: # Once the service account is ready, you need to generate and download a JSON key and base64 encode it:
# #
# ```shell # ```shell
# echo "KAMAL_REGISTRY_PASSWORD=$(base64 -i /path/to/key.json)" | tr -d "\\n" >> .env # base64 -i /path/to/key.json | tr -d "\\n")
# ``` # ```
# You'll then need to set the KAMAL_REGISTRY_PASSWORD secret to that value.
#
# Use the env variable as password along with _json_key_base64 as username. # Use the env variable as password along with _json_key_base64 as username.
# Heres the final configuration: # Heres the final configuration:

View File

@@ -47,4 +47,3 @@ servers:
env: env:
... ...
asset_path: /public asset_path: /public

View File

@@ -1,7 +1,7 @@
class Kamal::Configuration::Proxy class Kamal::Configuration::Proxy
include Kamal::Configuration::Validation include Kamal::Configuration::Validation
MINIMUM_VERSION = "v0.1.0" MINIMUM_VERSION = "v0.3.0"
DEFAULT_HTTP_PORT = 80 DEFAULT_HTTP_PORT = 80
DEFAULT_HTTPS_PORT = 443 DEFAULT_HTTPS_PORT = 443
DEFAULT_IMAGE = "basecamp/kamal-proxy:#{MINIMUM_VERSION}" DEFAULT_IMAGE = "basecamp/kamal-proxy:#{MINIMUM_VERSION}"

View File

@@ -22,7 +22,7 @@ class CliProxyTest < CliTestCase
end end
end end
assert_includes exception.message, "kamal-proxy version v0.0.1 is too old, please reboot to update to at least v0.1.0" assert_includes exception.message, "kamal-proxy version v0.0.1 is too old, please reboot to update to at least #{Kamal::Configuration::Proxy::MINIMUM_VERSION}"
ensure ensure
Thread.report_on_exception = false Thread.report_on_exception = false
end end
@@ -31,7 +31,7 @@ class CliProxyTest < CliTestCase
Thread.report_on_exception = false Thread.report_on_exception = false
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info) SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
.with(:docker, :inspect, "kamal-proxy", "--format '{{.Config.Image}}'", "|", :cut, "-d:", "-f2") .with(:docker, :inspect, "kamal-proxy", "--format '{{.Config.Image}}'", "|", :cut, "-d:", "-f2")
.returns("v0.1.0") .returns(Kamal::Configuration::Proxy::MINIMUM_VERSION)
.at_least_once .at_least_once
run_command("boot").tap do |output| run_command("boot").tap do |output|
@@ -189,7 +189,7 @@ class CliProxyTest < CliTestCase
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info) SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
.with(:docker, :inspect, "kamal-proxy", "--format '{{.Config.Image}}'", "|", :cut, "-d:", "-f2") .with(:docker, :inspect, "kamal-proxy", "--format '{{.Config.Image}}'", "|", :cut, "-d:", "-f2")
.returns("v0.1.0") .returns(Kamal::Configuration::Proxy::MINIMUM_VERSION)
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info) SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
.with(:docker, :container, :ls, "--all", "--filter", "name=^app-workers-latest$", "--quiet", "|", :xargs, :docker, :inspect, "--format", "'{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}'") .with(:docker, :container, :ls, "--all", "--filter", "name=^app-workers-latest$", "--quiet", "|", :xargs, :docker, :inspect, "--format", "'{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}'")
@@ -205,7 +205,7 @@ class CliProxyTest < CliTestCase
assert_match "/usr/bin/env mkdir -p .kamal", output assert_match "/usr/bin/env mkdir -p .kamal", output
assert_match "docker network create kamal", output assert_match "docker network create kamal", output
assert_match "docker login -u [REDACTED] -p [REDACTED]", output assert_match "docker login -u [REDACTED] -p [REDACTED]", output
assert_match "docker container start kamal-proxy || docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume $(pwd)/.kamal/proxy/config:/home/kamal-proxy/.config/kamal-proxy --log-opt max-size=\"10m\" basecamp/kamal-proxy:v0.1.0", output assert_match "docker container start kamal-proxy || docker run --name kamal-proxy --network kamal --detach --restart unless-stopped --publish 80:80 --publish 443:443 --volume /var/run/docker.sock:/var/run/docker.sock --volume $(pwd)/.kamal/proxy/config:/home/kamal-proxy/.config/kamal-proxy --log-opt max-size=\"10m\" basecamp/kamal-proxy:#{Kamal::Configuration::Proxy::MINIMUM_VERSION}", output
assert_match "/usr/bin/env mkdir -p .kamal", output assert_match "/usr/bin/env mkdir -p .kamal", output
assert_match %r{docker rename app-web-latest app-web-latest_replaced_.*}, output assert_match %r{docker rename app-web-latest app-web-latest_replaced_.*}, output
assert_match "/usr/bin/env mkdir -p .kamal/apps/app/env/roles", output assert_match "/usr/bin/env mkdir -p .kamal/apps/app/env/roles", output
@@ -228,7 +228,7 @@ class CliProxyTest < CliTestCase
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info) SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
.with(:docker, :inspect, "kamal-proxy", "--format '{{.Config.Image}}'", "|", :cut, "-d:", "-f2") .with(:docker, :inspect, "kamal-proxy", "--format '{{.Config.Image}}'", "|", :cut, "-d:", "-f2")
.returns("v0.1.0") .returns(Kamal::Configuration::Proxy::MINIMUM_VERSION)
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info) SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
.with(:docker, :container, :ls, "--all", "--filter", "name=^app-workers-latest$", "--quiet", "|", :xargs, :docker, :inspect, "--format", "'{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}'") .with(:docker, :container, :ls, "--all", "--filter", "name=^app-workers-latest$", "--quiet", "|", :xargs, :docker, :inspect, "--format", "'{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}'")

View File

@@ -28,7 +28,7 @@ class MainTest < IntegrationTest
assert_match /Proxy Host: vm2/, details assert_match /Proxy Host: vm2/, details
assert_match /App Host: vm1/, details assert_match /App Host: vm1/, details
assert_match /App Host: vm2/, details assert_match /App Host: vm2/, details
assert_match /basecamp\/kamal-proxy:v0.1.0/, details assert_match /basecamp\/kamal-proxy:#{Kamal::Configuration::Proxy::MINIMUM_VERSION}/, details
assert_match /registry:4443\/app:#{first_version}/, details assert_match /registry:4443\/app:#{first_version}/, details
audit = kamal :audit, capture: true audit = kamal :audit, capture: true

View File

@@ -53,11 +53,11 @@ class ProxyTest < IntegrationTest
private private
def assert_proxy_running def assert_proxy_running
assert_match /basecamp\/kamal-proxy:v0.1.0 \"kamal-proxy run\"/, proxy_details assert_match /basecamp\/kamal-proxy:#{Kamal::Configuration::Proxy::MINIMUM_VERSION} \"kamal-proxy run\"/, proxy_details
end end
def assert_proxy_not_running def assert_proxy_not_running
assert_no_match /basecamp\/kamal-proxy:v0.1.0 \"kamal-proxy run\"/, proxy_details assert_no_match /basecamp\/kamal-proxy:#{Kamal::Configuration::Proxy::MINIMUM_VERSION} \"kamal-proxy run\"/, proxy_details
end end
def proxy_details def proxy_details