Caddy 2.4.0 beta 1 is now available

Thanks @francislavoie and @matt. That gives me some ideas to work with.

After a successful caddy upgrade, until Caddy is restarted, wouldn’t caddy version still give me the old version i.e. the Caddy instance that is presently running rather than the version of the binary just replaced?

No. The old binary won’t exist anymore so it will have to run the new one.

1 Like

If you use any commands that use the API, like caddy reload, then it would reload the currently running instance (old binary) by using the new binary to send the reload message, but commands like caddy version that just query the currently available binary, it’ll use the latest.


Here’s a version of a bash script that can be run periodically as a cron job to automatically upgrade Caddy 2.4.0 and above to the most current release of Caddy. It should run on FreeBSD systems and its derivatives like FreeNAS/TrueNAS. It implements the logic discussed in the last few posts of this thread and can probably be adapted for other Unix-like systems that also run Caddy.

ver=$(caddy version)
caddy upgrade
if [ $status -eq 0 ]; then
  if [ "$(caddy version)" != "$ver" ]; then
    service caddy restart
  echo "Something bad happened! Upgrade status=$status"

I installed the 2.4.0-beta.1 static binary and then manually ran caddy upgrade. I had in my mind that the latest tweaks to beta.1 would be applied. The upgrade went through successfully. The only issue was that Caddy was downgraded to 2.3.0 :sob:

[root@wp-basil /usr/local/bin]# caddy version
v2.4.0-beta.1 h1:Ed/tIaN3p6z8M3pEiXWJL/T8JmCqV62FrSJCHKquW/I=
[root@wp-basil /usr/local/bin]# caddy upgrade
2021/03/09 17:19:29.637 INFO    this executable will be replaced        {"path": "/usr/local/bin/caddy"}
2021/03/09 17:19:29.637 INFO    requesting build        {"os": "freebsd", "arch": "amd64", "packages": []}
2021/03/09 17:19:30.381 INFO    build acquired; backing up current executable   {"current_path": "/usr/local/bin/caddy", "backup_path": "/usr/local/bin/caddy.tmp"}
2021/03/09 17:19:30.381 INFO    downloading binary      {"source": "", "destination": "/usr/local/bin/caddy"}
2021/03/09 17:19:42.494 INFO    download successful; displaying new binary details      {"location": "/usr/local/bin/caddy"}

Module versions:

admin.api.load v2.3.0
admin.api.metrics v2.3.0
caddy.adapters.caddyfile v2.3.0
caddy.listeners.tls v2.3.0
caddy.logging.encoders.console v2.3.0
caddy.logging.encoders.filter v2.3.0
caddy.logging.encoders.filter.delete v2.3.0
caddy.logging.encoders.filter.ip_mask v2.3.0
caddy.logging.encoders.json v2.3.0
caddy.logging.encoders.logfmt v2.3.0
caddy.logging.encoders.single_field v2.3.0
caddy.logging.writers.discard v2.3.0
caddy.logging.writers.file v2.3.0 v2.3.0
caddy.logging.writers.stderr v2.3.0
caddy.logging.writers.stdout v2.3.0 v2.3.0
http v2.3.0
http.authentication.hashes.bcrypt v2.3.0
http.authentication.hashes.scrypt v2.3.0
http.authentication.providers.http_basic v2.3.0
http.encoders.gzip v2.3.0
http.encoders.zstd v2.3.0
http.handlers.acme_server v2.3.0
http.handlers.authentication v2.3.0
http.handlers.encode v2.3.0
http.handlers.error v2.3.0
http.handlers.file_server v2.3.0
http.handlers.headers v2.3.0 v2.3.0
http.handlers.metrics v2.3.0
http.handlers.push v2.3.0
http.handlers.request_body v2.3.0
http.handlers.reverse_proxy v2.3.0
http.handlers.rewrite v2.3.0
http.handlers.static_response v2.3.0
http.handlers.subroute v2.3.0
http.handlers.templates v2.3.0
http.handlers.vars v2.3.0
http.matchers.expression v2.3.0
http.matchers.file v2.3.0
http.matchers.header v2.3.0
http.matchers.header_regexp v2.3.0 v2.3.0
http.matchers.method v2.3.0
http.matchers.not v2.3.0
http.matchers.path v2.3.0
http.matchers.path_regexp v2.3.0
http.matchers.protocol v2.3.0
http.matchers.query v2.3.0
http.matchers.remote_ip v2.3.0
http.matchers.vars v2.3.0
http.matchers.vars_regexp v2.3.0
http.reverse_proxy.selection_policies.cookie v2.3.0
http.reverse_proxy.selection_policies.first v2.3.0
http.reverse_proxy.selection_policies.header v2.3.0
http.reverse_proxy.selection_policies.ip_hash v2.3.0
http.reverse_proxy.selection_policies.least_conn v2.3.0
http.reverse_proxy.selection_policies.random v2.3.0
http.reverse_proxy.selection_policies.random_choose v2.3.0
http.reverse_proxy.selection_policies.round_robin v2.3.0
http.reverse_proxy.selection_policies.uri_hash v2.3.0
http.reverse_proxy.transport.fastcgi v2.3.0
http.reverse_proxy.transport.http v2.3.0
pki v2.3.0
tls v2.3.0
pki v2.3.0
tls v2.3.0
tls.certificates.automate v2.3.0
tls.certificates.load_files v2.3.0
tls.certificates.load_folders v2.3.0
tls.certificates.load_pem v2.3.0
tls.handshake_match.sni v2.3.0
tls.issuance.acme v2.3.0
tls.issuance.internal v2.3.0
tls.issuance.zerossl v2.3.0
tls.stek.distributed v2.3.0
tls.stek.standard v2.3.0

v2.3.0 h1:fnrqJLa3G5vfxcxmOH/+kJOcunPLhSBnjgIvjXV/QTA=

2021/03/09 17:19:42.604 INFO    upgrade successful; please restart any running Caddy instances  {"executable": "/usr/local/bin/caddy"}
[root@wp-basil /usr/local/bin]# service caddy restart
Stopping caddy.
Waiting for PIDS: 76788.
[root@wp-basil /usr/local/bin]# caddy version
v2.3.0 h1:fnrqJLa3G5vfxcxmOH/+kJOcunPLhSBnjgIvjXV/QTA=

In addition, although the output from caddy upgrade suggests that the previous version of Caddy would be backed up as /usr/local/bin/caddy.tmp, the backup didn’t occur.

Ha - that probably shouldn’t happen, it shouldn’t fetch an older version than you’re currently running even if you’re running a beta. Mind filing an issue on github?

1 Like

It’s intentional that it upgrades you to the latest stable. Depending on how you define upgrade, changing from a pre-release to a stable release is an upgrade. I dunno. I’m not actually sure that is wrong?

But I can also see arguments for this.

The backup occurs, but is cleaned up after the change finishes successfully.

Sure, but only if that brings you from like v2.3.0-beta.1 to v2.3.0 for example. Going from a v2.4.0-beta.1 to v2.3.0 doesn’t make sense IMO. That’s clearly a downgrade.

I’d even go so far as to say that going from 2.3.0-beta-1 to 2.3.0 isn’t an upgrade, it’s a channel swap. It might be practically an upgrade because it’s strictly newer, more updated code. But as we can see if we channel swap from beta to stable and go backwards in semantic version, that’s definitely not newer code. Conceptually the difference is important, I think.

Strictly speaking an upgrade would be 2.3.0-beta.1 to hypothetically 2.3.0-beta.2 or 2.4.0-beta.1.

1 Like

I see the dilemma here, though I’m not sure that latest stable is the right terminology to use; maybe
latest release or latest official is a better choice of words. My reasoning is, the Caddy reverse proxy that drives my production environment is predicated on an xcaddy build master. This was necessary to solve the map directive issue identified in the thread Migrate to using a wildcard certificate. In that thread, I even expressed concern about moving away from Caddy 2.3.0 to the beta, but I had to make a choice. I chose the beta and it solved the issue and had no other visible impact on the production environment. IMO, that’s the latest stable version of Caddy even if it’s not deemed the latest official version.

I wonder if a way around this may be to allow both behaviours? For example, caddy upgrade for the existing behaviour and caddy upgrade -master to allow the latest tweaks from the master to filter through.

I wonder if there’s any harm in leaving the backup there (instead of naming it caddy.tmp, it could be named caddy.backup), but overwriting it when Caddy is next upgraded? This provides an easy path to revert back to the last release prior to the upgrade if required. It would have been useful in this instance i.e. to revert back to the 2.4.0-beta.1 from 2.3.0.

I don’t think I agree. You wouldn’t want to skip v2.3.0 if you were on v2.3.0-beta.1, that doesn’t make sense. We don’t tend have a beta for the next version before we have stable for the previous. If we wanted to introduce channels as a concept then we’d need to allow the user to separately indicate what channel they want to be in. We do have that for the apt repos Install — Caddy Documentation where we have two separate repos, one stable and one testing.

1 Like

A fair disagreement, to be sure.

Either way I don’t think there’s any scenario where it makes sense to call a 2.4.0 beta reverting to 2.3.0 stable to be a functional upgrade. An argument could be made that you could colloquially refer to it as a stability upgrade, but not in terms of software functionality would it ever be called an upgrade.


Maybe it’s a bit like negative growth, a popular term among economists :wink:

Just want to open up a discussion around caddy fmt. According to the 2.4.0 release notes:

  • Caddyfile fmt lint check. When running with a Caddyfile, Caddy will emit a warning if the Caddyfile is not formatted with caddy fmt.


When I reload my Caddyfile, this is the output I see:

# service caddy reload
2021/03/22 05:10:55.234 INFO    using provided configuration    {"config_file": "/usr/local/www/Caddyfile", "config_adapter": "caddyfile"}
[WARNING][caddyfile] /usr/local/www/Caddyfile:2: input is not formatted with 'caddy fmt'

Is caddy fmt a mandatory or non-mandatory step? If it’s optional, does it need to be a WARNING? If not, can I suggest that the bracketed word [WARNING] be changed to [INFO]? Personally, at present, I find the message comes across like a red flag.

caddy fmt options

This is the current list of fmt options:

# caddy fmt --help
Usage of format:
        Overwrite the input file with the results

caddy fmt does a good job of formatting the Caddyfile. The indentation is eight spaces. I already indent (using two spaces). I’d be more inclined to use caddy fmt if I had a choice over the depth of indentation. I’m not sure how other forum members feel about this?

caddy fmt sometimes does too good a job at formatting… for a machine. At times, it misses the human element. There are some areas of the Caddyfile that I prefer not to be formatted, for example, around the map directive.

Before formatting…

  map {path} {backend} {online} {

#   PATH                BACKEND          ONLINE
    ~^/tautulli.*   yes
    ~^/transmission.*   yes
    ~^/.*          yes

After formatting…

        map {path} {backend} {online} {
                #   PATH                BACKEND          ONLINE
                ~^/tautulli.* yes
                ~^/transmission.* yes
                ~^/.* yes

Unless you’re Cypher and can read The Matrix, I know which version I prefer.

In this case, all Caddyfile adapter warnings are basically “non-errors”, as in things that don’t need to prevent Caddy from running. There’s no concept of log levels for those, although it may seem like it. I understand what you mean though.

Somewhat related, you reminded me that the fmt log is using fmt.Printf instead of the zap logger, so it sticks out like a sore thumb. PR to fix:


This topic was automatically closed after 120 days. New replies are no longer allowed.