Commit Graph
100 Commits
Author SHA1 Message Date
Donal McBreen bf64d9a0f5 Run pre-connect hooks before ssh commands
We hook into the SSHKit `on` method to run the pre-connect hook before
the first SSH command. This doesn't work for interactive exec commands
where ssh is called directly.

Fixes: https://github.com/basecamp/kamal/issues/1157
2025-04-18 14:30:52 +01:00
Donal McBreen 8d5ed62d30 Don't allow booleans for root proxy config
Setting it to a false or true doesn't affect the config so shouldn't be
allowed. true/false are for role level configurations.

Fixes: https://github.com/basecamp/kamal/issues/1120
2025-04-18 14:25:29 +01:00
Donal McBreen e4e39c31e3 Add KAMAL.app_hosts
KAMAL.hosts includes accessory and apps hosts. Add KAMAL.app_hosts which
does not include accessory only hosts and use it for app specific
commands.

Fixes:
- https://github.com/basecamp/kamal/issues/1059
- https://github.com/basecamp/kamal/issues/1148
2025-04-18 13:15:50 +01:00
Donal McBreen 03cac7ae3d Skip existing containers on accessory boot
When booting an accessory, check for the container first and skip boot
if it exists. This allows us to rerun `kamal setup` on hosts with
accessories without raising an error.

Fixes: https://github.com/basecamp/kamal/issues/488
2025-04-18 10:53:26 +01:00
Donal McBreen 399f1526af Handle role filter when booting accessories
Filter the accessory hosts via KAMAL.accessory_hosts, which correctly
handles role and host filters.

Fixes: https://github.com/basecamp/kamal/issues/935
2025-04-18 10:20:54 +01:00
Donal McBreen 098c937bab Move docker login into build command
We only need to run the docker login commands for pushing and pulling
images.

So let's move the logins into those commands. This ensures we are logged
in when calling `kamal build` commands directly.

Fixes: https://github.com/basecamp/kamal/issues/919
2025-04-18 09:57:02 +01:00
Donal McBreen 91f01ece1b Ensure that the restart policy is unless-stopped
No other restart policy makes sense to don't let it be changed.

Fixes: https://github.com/basecamp/kamal/issues/749
2025-04-17 13:36:26 +01:00
Donal McBreen 521425c386 Rely on semver for version checks 2025-04-17 13:18:46 +01:00
Donal McBreen 55ec6ca0a6 Allow accessory only configurations
If there are accessories defined in the configuration, we'll not require
servers to be defined as well.

This allows for accessory-only configurations which allows you to run
external images with kamal-proxy for zero-downtime deployments.

We don't manage image cleanup for accessories though so the user will
need to deal with that themselves.
2025-04-17 11:40:03 +01:00
Donal McBreen 354530f3b8 Maintenance mode
Adds support for maintenance mode to Kamal.

There are two new commands:
- `kamal app maintenance` - puts the app in maintenance mode
- `kamal app live` - puts the app back in live mode

In maintenance mode, the kamal proxy will respond to requests with a
503 status code. It will use an error page built into kamal proxy.

You can use your own error page by setting `error_pages_path` in the
configuration. This will copy any 4xx.html or 5xx.html files from that
page to a volume mounted into the proxy container.
2025-04-17 09:11:21 +01:00
Donal McBreen 26b6c072f3 Add a writable proxy volume
Maps in and external /home/kamal-proxy/.app-config volume that we can
use to map files to the proxy.

Can be used to store custom maintenance pages or SSL certificates.
2025-04-17 09:08:36 +01:00
Donal McBreen 8ceeda6ac9 Extract proxy_default_boot_options 2025-04-17 08:47:01 +01:00
Donal McBreen dd9048e09c Allow version 'next' 2025-04-17 08:20:25 +01:00
Donal McBreen bd81632439 Set DEBUG for integration test output 2025-04-16 16:54:46 +01:00
Donal McBreen 85320dbc51 Custom proxy image registry, repo and version
Use the --registry, --repository and --image_version options of
`kamal proxy boot_config set` to change the kamal-proxy image used.

We'll still insist that the image version is at least as high as the
minimum.
2025-04-16 16:54:46 +01:00
Donal McBreen c9a755bde6 Extract echo_boot_config/docker_run methods 2025-04-16 14:33:15 +01:00
Donal McBreen 215fd2faed Use registry:3 image for the integration tests
v3 was recently released which broke the integration tests. Update them
to use the correct config file.

Set the major version to prevent this from happening when v4 is
released.
2025-04-15 10:55:36 +01:00
Donal McBreen fb95b38e73 Tidy up the env secrets handling
The secrets accessor was only used in the tests so remove it.
Skip the memoization, it makes things slightly harder to follow and
it's not needed.
2025-03-24 09:21:27 +00:00
Donal McBreen 7fa27faaca Use xargs to handle spaces in proxy options
We cat the options file, append the proxy image and then pass it
to xargs to ensure it handles spaces correctly.

Works better than using eval which can handle spaces but tries
to evaluate things like backticks.

Fixes: https://github.com/basecamp/kamal/issues/1448
2025-03-18 08:46:31 +00:00
Donal McBreen 36f4e90a76 Update to kamal-proxy 0.8.6
Includes a fix for locking the proxy while draining
2025-03-07 11:33:17 +00:00
Donal McBreen 62dfa45ee6 Bump version for 2.5.3 2025-02-27 10:27:27 +00:00
Donal McBreen 6f29d4e78b Bump version for 2.5.2 2025-02-07 15:27:30 +00:00
Donal McBreen b130bc0321 Fix the docker build
Somewhere along the way the docker build broke, it now needs yaml-dev
to be installed. Maybe the underlying image changed?

Update to 3.4-alpine while we are here.
2025-02-06 14:45:37 +00:00
Donal McBreen 28be0300b9 Bump version for 2.5.1 2025-02-06 13:54:46 +00:00
Donal McBreen fdf7e6927a Only check for docker when logging in locally
If we are skipping a local registry login, we don't need docker
installed locally.

Fixes: https://github.com/basecamp/kamal/issues/1400
2025-02-06 11:12:56 +00:00
Donal McBreen 45197e46f6 Bump version for 2.5.0 2025-02-04 11:19:44 +00:00
Donal McBreen 9af2425fbd Doc changes for 2.5
Sync up the accessory.yml file with the latest changes in the
kamal-site repo.
2025-02-04 11:05:25 +00:00
Donal McBreen 8775d202bd Prep for 2.5
- Reset KAMAL on alias command, rather than relying on checking
  "invoked_via_subcommand"
- Validate the accessories roles when loading the configuration
  not later on when trying to access them
2025-02-04 09:08:57 +00:00
Donal McBreen 04a96aa5be Allow accessory roles with no hosts
Only raise an exception if the role is not found, not it it has no
hosts.
2025-02-03 16:44:01 +00:00
Donal McBreen cd73cea850 Add pre and post app boot hooks
Add two new hooks pre-app-boot and post-app-boot. They are analagous
to the pre/post proxy reboot hooks.

If the boot strategy deploys in groups, then the hooks are called once
per group of hosts and `KAMAL_HOSTS` contains a comma delimited list of
the hosts in that group.

If all hosts are deployed to at once, then they are called once with
`KAMAL_HOSTS` containing all the hosts.

It is possible to have pauses between groups of hosts in the boot config,
where this is the case the pause happens after the post-app-boot hook is
called.
2025-02-03 15:54:45 +00:00
Donal McBreen f187080db5 Don't cleanup traefik on reboot
This was designed to help with upgrading from Kamal 1 to Kamal 2
but it causes issues if you have a traefik container you don't want
to be shut down.
2025-01-20 15:06:06 +00:00
Donal McBreen 34050f1036 Don't read a file in sample deploy.yml
The ERB runs first so it does matter if it in a comment. If the file
doesn't exist (e.g. if not using Ruby, you'll get an error).

We'll change the example to match the Rails deploy.yml template won't
have than problem.
2025-01-20 14:26:43 +00:00
Donal McBreen a5b9c69838 Update to Ruby 3.4 from the preview version 2025-01-17 15:17:37 +00:00
Donal McBreen dc9a95db2c Check for docker locally before registry login
We were checking before `kamal build push`, but not `kamal registry login`.
Since `kamal registry login` is called first by a deploy we don't
get the nice error message.
2025-01-17 15:17:22 +00:00
Donal McBreen 1db44c402c Boot accessories after pre-deploy hook
That allows you to set proxy config in the hook before booting
the proxy.
2025-01-17 15:04:16 +00:00
Donal McBreen 4ffa772201 Don't boot proxy twice when setting up 2025-01-17 13:04:37 +00:00
Donal McBreen 9f1688da7a Fix test 2025-01-17 12:52:23 +00:00
Donal McBreen 2bd716ece4 Drop the TestOptionalAccount adapter
It's included in the gem lib which is best to avoid and we can infer
that it works account optional adapters.
2025-01-17 12:37:12 +00:00
Donal McBreen f9a78f4fcb gcloud login tidy
Use unless instead of if !, don't suggest running gcloud auth login,
we've just tried that.
2025-01-17 12:34:38 +00:00
Donal McBreen 10dafc058a Extract secrets_get_flags 2025-01-17 12:31:24 +00:00
Donal McBreen 5e2678dece Ensure external input is shell escaped 2025-01-17 12:28:59 +00:00
Donal McBreen a1708f687f Prefix secrets in fetch_secrets
This allows us to remove the custom fetch method for enpass.
2025-01-17 12:24:46 +00:00
Donal McBreen db7556ed99 Fix enpass adapter
There were changes in main that meant the tests failed after merging.

Adding the new `requires_account?` method to the enpass adapter fixed it.
2025-01-17 12:07:56 +00:00
Donal McBreen dd8cadf743 Add tests for env/secret file precedence 2025-01-17 11:06:29 +00:00
Donal McBreen 2cdca4596c Create but don't run the assets container
We don't need to run the assets container to copy the assets out,
instead we can just create, copy and remove.
2025-01-16 16:28:02 +00:00
Donal McBreen 78fcc3d88f Allow destination and config-file in aliases
We only loaded the configuration once, which meant that aliases always
used the initial configuration file and destination.

We don't want to load the configuration in subcommands as it is not
passed all the options we need. But just checking if we are in a
subcommand is enough - the alias reloads and the subcommand does not.

One thing to note is that anything passed on the command line overrides
what is in the alias, so if an alias says
`other_config: config -c config/deploy2.yml` and you run
`kamal other_config -c config/deploy.yml`, it won't switch.
2025-01-16 15:51:18 +00:00
Donal McBreen 1547089da0 Bump version for 2.4.0 2024-12-13 12:38:26 +00:00
Donal McBreen ae7a4f3411 Update yml files to match doc site changes 2024-12-13 12:27:22 +00:00
Donal McBreen 77c202ebaf Highlight ssl/forward_headers behaviour
Pulled in from: https://github.com/basecamp/kamal-site/pull/141
2024-12-13 12:20:05 +00:00
Donal McBreen 3e4a190173 Fix for Dotenv 3.1.5
In Dotenv 3.1.5, `Dotenv.parse` no longer returns values that are
already in the environment.

See https://github.com/bkeepers/dotenv/issues/518

We can get the values though by setting overwrite: true, which works
with both 3.1.4 and 3.1.5.
2024-12-13 10:42:02 +00:00
Donal McBreen 2386c903ca Update to proxy version 0.8.4
Release: https://github.com/basecamp/kamal-proxy/releases/tag/v0.8.4

- Silence late healthcheck requests
2024-12-02 10:37:07 +00:00
Donal McBreen e9ba92386c Filter correctly for empty destinations
An empty destination should only filter container with empty
destination, not pick up all containers.

Fixes: https://github.com/basecamp/kamal/issues/1184
2024-11-04 11:05:24 +00:00
Donal McBreen 685312c9f8 Bump version for 2.3.0 2024-10-31 09:14:29 +00:00
Donal McBreen 2c14f48300 Bump proxy minimum version to 0.8.2
Detect event-stream content type properly

See: https://github.com/basecamp/kamal-proxy/releases/tag/v0.8.2
2024-10-30 08:06:52 +00:00
Donal McBreen 9a8a45015b Allow log max size to not be set
The max-size log opt is not valid for all logging drivers, such as
syslog. Allow the option to be removed from the boot config with:

```
kamal proxy boot_config set --log-max-size=
or
kamal proxy boot_config set --log-max-size=""
```
2024-10-23 15:21:06 +01:00
Donal McBreen 8d0f4903ae Ensure using at least net-ssh 7.3.0
This has support for aes(128|256)gcm ciphers and some fixes for
Ruby 3.3.
2024-10-23 14:58:36 +01:00
Donal McBreen 3ee45d7b30 Require zeitwerk 2.6.12
We were requiring Zeitwerk 2.5+, but calling eager_load_namespace
which was added in 2.6.2.

Fixes: https://github.com/basecamp/kamal/issues/1109
2024-10-22 13:01:36 +01:00
Donal McBreen 5cb9fb787b Bump version for 2.2.2 2024-10-10 13:29:38 -04:00
Donal McBreen 3654a7e1be Bump version for 2.2.1 2024-10-09 14:46:44 -04:00
Donal McBreen 74960499c0 Bump proxy to version 0.8.1
Fixes issue where incorrect status code may be returned when buffering
responses.

https://github.com/basecamp/kamal-proxy/releases/tag/v0.8.1
2024-10-09 14:00:38 -04:00
Donal McBreen 7b48648bf2 Bump version for 2.2.0 2024-10-08 08:59:23 -04:00
Donal McBreen 06419f8749 Add Active Support require for to_sentence
Fixes: https://github.com/basecamp/kamal/issues/1061
2024-10-08 07:33:03 -04:00
Donal McBreen 67ce1912f7 Default to keeping 10m of proxy logs
Match the defaults for the application containers of 10m of logs.

Allow them to be altered with the proxy boot_config set command.
2024-10-07 16:20:40 -04:00
Donal McBreen a434b10bfd Update to kamal-proxy 0.8.0
Proxy changes:
- Add option to use custom TLS certificates (#17)
- Don't buffer SSE responses (#36)
- Allow routing to wildcard subdomains (#45)

Custom TLS certificates not supported in Kamal itself yet. Buffering
SSE responses and wildcard subdomains will work without any Kamal
changes.
2024-10-06 13:48:00 -04:00
Donal McBreen e34031f70c Bump version for 2.1.2 2024-10-06 13:40:53 -04:00
Donal McBreen 1e9c9e9103 Skip setting the proxy flag when ssl is false
Fixes: https://github.com/basecamp/kamal/issues/1037
2024-10-06 13:22:43 -04:00
Donal McBreen 279bda2770 Bump version for 2.1.0 2024-10-02 11:35:45 +01:00
Donal McBreen 641e9056b3 Use = in kamal-proxy deploy command args
`=` is required for boolean values and works for all values.
2024-10-01 15:42:12 +01:00
Donal McBreen df1232d90f Added support for ACME http-01 challenges
Update to kamal-proxy 0.7.0 for ACME `http-01` challenge support.
2024-09-30 14:44:28 +01:00
Donal McBreen e441399255 Add kamal secrets print for secret debugging
Dotenv's variable substitution doesn't work the same way as commands run
in the shell. It needs values to be escaped.

```sh
$ cat /tmp/env
SECRETS=$(cat /tmp/json)
SECRETS2=$(echo $SECRETS | jq)
$ cat /tmp/json
\{\ \"foo\"\ :\ \"bar\" \}
$ SECRETS=$(cat /tmp/json)
$ SECRETS2=$(echo $SECRETS | jq)
jq: parse error: Invalid numeric literal at line 1, column 2
$ ruby -e 'require "dotenv"; puts Dotenv.parse("/tmp/env")["SECRETS2"]'
{
  "foo": "bar"
}
```

Since you then can't use the shell to debug, `kamal secrets print` will
allow you to see what the secrets will be set to.
2024-09-30 12:28:29 +01:00
Donal McBreen 14d0396581 Rails 8 doesn't support Ruby 3.1
Remove it from the build matrix as its no longer a supported combination.
2024-09-27 08:13:24 -04:00
Donal McBreen 8c32e6af07 Bump version for 2.0.0 2024-09-26 15:34:24 -04:00
Donal McBreen a765c501a3 Bump version for 2.0.0.rc4 2024-09-26 07:06:51 -04:00
Donal McBreen b3a6921118 Handle ssl: false in proxy config
Fixes: https://github.com/basecamp/kamal/issues/956
2024-09-26 06:17:45 -04:00
Donal McBreen 7bdf6cd2e8 Bump to latest version of kamal-proxy 2024-09-25 17:54:38 -04:00
Donal McBreen f6851048a6 Proxy boot config
Add commands for managing proxy boot config. Since the proxy can be
shared by multiple applications, the configuration doesn't belong in
`config/deploy.yml`.

Instead you can set the config with:

```
Usage:
  kamal proxy boot_config <set|get|clear>

Options:
      [--publish], [--no-publish], [--skip-publish]   # Publish the proxy ports on the host
                                                      # Default: true
      [--http-port=N]                                 # HTTP port to publish on the host
                                                      # Default: 80
      [--https-port=N]                                # HTTPS port to publish on the host
                                                      # Default: 443
      [--docker-options=option=value option2=value2]  # Docker options to pass to the proxy container
```

By default we boot the proxy with `--publish 80:80 --publish 443:443`.

You can stop it from publishing ports, specify different ports and pass
other docker options.

The config is stored in `.kamal/proxy/options` as arguments to be passed
verbatim to docker run.

Where someone wants to set the options in their application they can do
that by calling `kamal proxy boot_config set` in a pre-deploy hook.

There's an example in the integration tests showing how to use this to
front kamal-proxy with Traefik, using an accessory.
2024-09-25 15:15:26 -04:00
Donal McBreen f0d7f786fa Traefik should be kamal-proxy in reboot hooks 2024-09-25 14:51:22 -04:00
Donal McBreen 6df169a4fb Doc updates 2024-09-20 15:27:10 +01:00
Donal McBreen a6a48c456c Response timeout should be a number
Kamal will append the `s` for the duration when talking to kamal-proxy
so no need to have it in the config.
2024-09-20 09:26:06 +01:00
Donal McBreen 6e65968bdc Integration test two apps
Use localhost for app_with_roles and 127.0.0.1 for app. Confirm we can
deploy both and the respond to requests. Ensure the proxy is removed
once both have been removed.
2024-09-19 16:25:09 +01:00
Donal McBreen 2c829a4824 Avoid setting env via SSHKit
SSHKit puts the env in the command, so leaks them in process listings.
2024-09-19 15:09:17 +01:00
Donal McBreen 834b343ded Run app exec in the kamal network
All other containers run in the kamal network, so let's add app exec-ed
containers as well.
2024-09-19 14:29:33 +01:00
Donal McBreen 1d7c9fec1d Fix /home/kamal-proxy/.config/kamal-proxy ownership
1. Update to kamal-proxy 0.4.0 which creates and chowns
/home/kamal-proxy/.config/kamal-proxy to kamal-proxy
2. Use a docker volume rather than mapping in a directory, so docker
keeps it owned by the correct user
2024-09-19 12:25:57 +01:00
Donal McBreen 63f854ea18 Add validations for host/ssl roles
Roles with SSL can only have one server.
Two roles with SSL can't use the same host.
2024-09-18 17:42:45 +01:00
Donal McBreen fd0cdc1ca1 All role specific proxy configuration
By default only the primary role runs the proxy. To disable the proxy
for that role, you can set `proxy: false` under it.

For other roles they default to not running the proxy, but you can
enable it by setting `proxy: true` for the role, or alternatively
setting a proxy configuration.

The proxy configuration will be merged into the root proxy configuration.
2024-09-18 17:25:35 +01:00
Donal McBreen d218264b69 Doc output fixes 2024-09-18 15:28:26 +01:00
Donal McBreen 8bcd896242 Simplified deploy/drain timeouts
Remove `stop_wait_time` and `readiness_timeout` from the root config
and remove `deploy_timeout` and `drain_timeout` from the proxy config.

Instead we'll just have `deploy_timeout` and `drain_timeout` in the
root config.

For roles that run the proxy, they are passed to the kamal-proxy deploy
command. Once that returns we can assume the container is ready to
shut down.

For other roles, we'll use the `deploy_timeout` when polling the
container to see if it is ready and the `drain_timeout` when stopping
the container.
2024-09-18 15:08:08 +01:00
Donal McBreen 34effef70a 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.
2024-09-18 14:00:43 +01:00
Donal McBreen 46c0836cd4 Upgrade on accessory hosts only with correct messages 2024-09-18 10:07:07 +01:00
Donal McBreen f183419f7a Ensure we don't load the secrets more than once
Secrets were being created twice, which might require logging in twice.
2024-09-17 14:21:43 +01:00
Donal McBreen 0fe6a17a91 Need a duration string for the response timeout
Add `s` as the timeout is a duration.
2024-09-17 13:23:15 +01:00
Donal McBreen 7f15fd143f Upgrade commands for Kamal 1.x -> 2.0
Adds:
- `kamal upgrade` to upgrade all app hosts and accessory hosts
- `kamal proxy upgrade` to upgrade the proxy on all hosts
- `kamal accessory upgrade [name]` to upgrade accessories on all hosts

Upgrade takes rolling and confirmed options and calls `proxy upgrade`
and `accessory upgrade` in turn.

To just upgrade a single host add -h [host] to the command. But the
upgrade should run on all hosts, not just those running the proxy.

Calling upgrade on a host that has already been upgraded should work ok.

Upgrading hosts causes downtime but you can avoid if you run multiple
hosts by:
1. Implementing the pre-proxy-reboot and post-proxy-reboot hooks to
   remove the host from external load balancers
2. Running the upgrade with the --rolling option

**kamal proxy upgrade**
1. Creates a `kamal` network if required
2. Stops and removes the old proxy (whether Traefik or kamal-proxy)
3. Starts a kamal-proxy container in the `kamal` network
4. Reboots the app containers in the `kamal` network

**kamal accessory upgrade [name]**
1. Creates a `kamal` network if required
2. Reboots the accessory containers in the `kamal` network

A matching `downgrade` command will be added to Kamal 1.9.
2024-09-17 13:02:02 +01:00
Donal McBreen 267b526438 Switch proxy/hosts to proxy/host
The proxy only supports a single host per app for nowm so make the
config match that.
2024-09-16 20:45:09 +01:00
Donal McBreen 1f721739d6 Use version 0.1.0 of kamal-proxy and add minimum version check 2024-09-16 16:44:58 +01:00
Donal McBreen 6c51e596ae Put locks directories in .kamal so they leave no trace when deleted 2024-09-16 16:44:58 +01:00
Donal McBreen 7f31510aec Set hosts via config rather than options 2024-09-16 16:44:58 +01:00
Donal McBreen e8ff233e81 Fix default log header tests 2024-09-16 16:44:58 +01:00
Donal McBreen a316e51eda Add user agent to default headers 2024-09-16 16:44:58 +01:00
Donal McBreen bf91d6c1ca Fix command description 2024-09-16 16:44:58 +01:00
Donal McBreen a84ee6315f Rename service -> app directory 2024-09-16 16:44:58 +01:00