Caddy sorts directives inside a site block according to a predefined ordering rather than reading them top to bottom. handle and redir and file_server and the rest each have a fixed position, so moving lines around in the file changes nothing about behavior.
This is deliberate, because HTTP middleware order is easy to get wrong, but it makes some configurations impossible to express directly. A rewrite placed after a reverse_proxy in the file still runs first, and two matchers intended to be tried in a specific sequence may not be.
When explicit ordering is needed, wrap the directives in a route block, which preserves the written order of its contents. handle blocks are mutually exclusive: the first whose matcher matches runs and the others are skipped, which is the right construct for path-based branching, whereas bare directives with matchers all run. The global order option can insert a custom directive from a plugin at a chosen position. Run caddy fmt --overwrite and caddy validate before deploying; caddy adapt prints the JSON the Caddyfile becomes, which is the reliable way to see the resulting order.