Skip to content

Support for Caddy Server #558

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
MattWilcox opened this issue Sep 18, 2023 · 14 comments
Closed

Support for Caddy Server #558

MattWilcox opened this issue Sep 18, 2023 · 14 comments
Labels
enhancement New feature or request

Comments

@MattWilcox
Copy link

MattWilcox commented Sep 18, 2023

UPDATE: Ben has addressed these issues as of 4.9.1, so if you want to see how to get Caddy Server configured correctly to support server re-writes (skip Craft/PHP when a Blitz file cache exists) and SSI too, read the final comment.


Two things; one would need work on the plugin itself and the other I think is more documentation.

SSI for Caddy

Caddy doesn't support "standard" SSI because it has a more powerful and "simpler" concept called Templates (their words, not mine). It looks like things could be made to work but the output of the SSI stuff Blitz does would need to change from

<!--#include virtual="/_includes?action=blitz%2Finclude%2Fcached&index=12345" -->

to

{{httpInclude "/_includes?action=blitz%2Finclude%2Fcached&index=12345"}}

when the server is Caddy.

The delimiters are configurable but I don't think that helps anything here.

Blitz server re-writes

You've got examples for nGinx and Apache, and I think the equivalent for Caddy is the following. It's certainly working for us, but it may not be quite as targeted as you want because this is only loading the Blitz file cache is there's no query at all (as opposed to a one called token).

Most simplistic solution Caddyfile config

some-website.com {
        root * /websites/REPO/web
        encode gzip zstd

        file_server

        @blitzCache {
                method GET
                not expression {query} != ''
        }
        route @blitzCache {
                try_files /cache/blitz/{host}{uri}/index.html {path} {path}/index.php?{query}
        }

        php_fastcgi unix//run/php/php8.1-fpm.sock
}

More complete / realistic Caddyfile example

# Snippets (see: https://caddyserver.com/docs/caddyfile/concepts)
(staticFileCache) {
        @static {
                file
                path *.ico *.css *.js *.gif *.jpg *.jpeg *.webp *.png *.svg *.woff2
        }
        header @static Cache-Control max-age=5184000
}

(blitzNoQueryString) {
        @blitzCache {
                method GET
                not expression {query} != ''
        }
        route @blitzCache {
                try_files /cache/blitz/{host}{uri}/index.html {path} {path}/index.php?{query}
        }
}

# Websites

an-old-domain.com,
www.some-website.com {
        redir https://some-website.com{uri}
}
some-website.com {
        root * /websites/REPO/web
        encode gzip zstd

        file_server
        import staticFileCache
        import blitzNoQueryString

        log {
                output file /websites/_logs/REPO.log
        }

        php_fastcgi unix//run/php/php8.1-fpm.sock
}
@MattWilcox MattWilcox added the enhancement New feature or request label Sep 18, 2023
@bencroker
Copy link
Collaborator

Thanks for the suggestions and for providing so much helpful detail.

Caddy’s http.handlers.templates indeed appears to be equivalent to SSI (a technology that dates back to the 90’s, ironically). The delimiters would very likely need to be changed so that Twig doesn’t mistake it for a Twig tag. Also, the great thing about the SSI tag syntax is that if the include fails for any reason then browsers interpret the tag as a simple HTML comment. My main concern about adding support for it is that SSI handling in Blitz is already rather fickle and took a large effort in terms of testing before it could confidently be integrated. Caddy is a much less popular web server than Apache and nginx and I’m unsure whether the effort and the added complexity of implementing it would be justified.

Server rewrites can be achieved via PHP as explained here. It performs surprisingly well, but if your Caddyfile config works then that’s great. I’ve added a small section to the docs linking back to this issue for anyone else interested in using server rewrites in Caddy (thank you!).

@MattWilcox
Copy link
Author

I'd have thought the tags wouldn't matter as they'd be injected post the twig parsing stage, but I suppose your blitz stuff may be doing it's thing earlier than that?

@bencroker
Copy link
Collaborator

That’s probable, just needs some thorough testing.

@MattWilcox
Copy link
Author

Just as an update, I've got what I thought should work done - but it isn't actually being spat out on the Caddy side of things. I've currently asked for help on their forums; https://caddy.community/t/httpinclude-not-seeming-to-be-parsed/21191

I'll update the thread here if I get things working.

@bencroker
Copy link
Collaborator

Sounds good.

@MattWilcox
Copy link
Author

I now have this working, if you want to have a look and / or accept the changes, I've created a pull request.

@bencroker
Copy link
Collaborator

bencroker commented Nov 20, 2023

I’ve taken a slightly different approach, in which the SSI tag format can be customised, in 243311b.

Released in 4.9.1.

@MattWilcox
Copy link
Author

MattWilcox commented Nov 22, 2023

To add for clarity, this is the setup I have that now works with Blitz 4.9.1

I am using a .env variable to indicate whether the server is nginx or caddy. We use DDEV locally which uses nGinx as its server, and we use Caddy live.

.env (local)

SERVER_TYPE="nginx"

.env (live)

SERVER_TYPE="caddy"

config/blitz.php

'ssiTagFormat' => App::env('SERVER_TYPE') === 'caddy' ? 
    '<!--#caddy httpInclude "{uri}" -->' :
    '<!--#include virtual="{uri}" -->',

And for a minimal Caddyfile config with SSI support:

website.url {
        root * /websites/web-root
        encode gzip zstd

        file_server

        templates {
                between <!--#caddy -->
        }

        php_fastcgi unix//run/php/php8.1-fpm.sock
}

Templates?

The Caddy concept, and nothing to do with Craft's templates. Caddy has a "template" system of its own, which is how SSI is done here - it can also do more, like parse MarkDown.

I am explicitly setting the Caddy templates directive for this site to have custom delimiters, because the default Caddy configuration uses {{ and }} delimiters to trigger Caddy's template system - which may conflict with Craft projects where error pages may render source code to the page, which may contain {{ and }}.

A complete Caddyfile example

Caddy itself transparently and automatically handles enforcing HTTPS, obtaining applying and renewing the certificates from LetsEncrypt, and serving HTTP3/QUIK without any configuration required. It's all done by default.

A more complete Caddyfile example than above, with SSI support and Server Rewrites to avoid PHP altogether follows below. It also enforces the removal of a www. sub-domain, and forwards an-old-domain.com to the new url.

# Snippets

(blitzNoQueryString) {
        @blitzCache {
                method GET
                not expression {query} != ''
        }
        route @blitzCache {
                try_files /cache/blitz/{host}{uri}/index.html {path} {path}/index.php?{query}
        }
}

# Websites

an-old-domain.com,
www.website.url {
        redir https://website.url{uri}
}

website.url {
        root * /websites/web-root
        encode gzip zstd

        file_server
        import blitzNoQueryString

        templates {
                between <!--#caddy -->
        }

        php_fastcgi unix//run/php/php8.1-fpm.sock
}

@bencroker
Copy link
Collaborator

Thanks!

@r-anwar
Copy link

r-anwar commented Jan 22, 2025

Hi, I want caddy only to bypass the blitzcache when following req. params are send:

  • x-craft-live-preview
  • x-craft-preview

How to change the following config?

(blitzNoQueryString) {
      @blitzCache {
                method GET
                **not expression {query} != ''**
        }
        route @blitzCache {
                try_files /cache/blitz/{host}{uri}/index.html {path} {path}/index.php?{query}
        }
}

@MattWilcox
Copy link
Author

MattWilcox commented Jan 22, 2025

That's more a question for Caddy than Craft I think - you're likely better asking here: https://caddy.community/c/help/5 (but if you find out, please do copy the answer here - sadly, I don't know)

@bencroker
Copy link
Collaborator

@r-anwar Blitz will never cache previews, so those should be bypassed automatically. Are you seeing otherwise?

@r-anwar
Copy link

r-anwar commented Jan 22, 2025

@r-anwar Blitz will never cache previews, so those should be bypassed automatically. Are you seeing otherwise?

Blitz does not cache previews, thats corret but what I want is that blitz shouldnt get by passed when other arbitrary req. params are used.

e.g. example.com?abc=def -> I want to deliver the cached version of that site.

@bencroker
Copy link
Collaborator

I would have guessed that commenting out not expression {query} != '' would work. Otherwise, I really don’t know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants