Translating nginx caching configuration to caddy (using caddyserver/cache-handler)

1. The problem I’m having:

With the new 0.19.* releases of Lemmy, the server now returns proper Cache-Control headers, and it is recommended to enable caching in the reverse proxy. Here is the suggested way to do it with nginx.
I’m having a hard time finding the appropriate Caddy cache-handler directives that correspond to nginx’s.
Can someone help me translate this file, or at least point me to some good documentation (or perhaps another better-suited plugin)?

2. Error messages and/or full log output:

N/A

3. Caddy version:

v2.7.6 h1:w0NymbG2m9PcvKWsrXO6EEkY9Ru4FJK8uQbYcev1p3A=
(built with xcaddy)

4. How I installed and ran Caddy:

a. System environment:

Docker, with the official caddy:2-alpine image.

To include cache-handler, I turned to the xcaddy example in the Docker image’s README:

FROM caddy:2-builder-alpine AS builder

RUN xcaddy build \
    --with github.com/caddyserver/cache-handler

FROM caddy:2-alpine

COPY --from=builder /usr/bin/caddy /usr/bin/caddy

b. Command:

I do not change the command/entrypoint and just mount my caddyfile as a volume onto /etc/caddy/Caddyfile.

c. Service/unit/compose file:

version: "2"

services:
  caddy:
    hostname: ...
    restart: unless-stopped
    expose:
      - ...  # this caddy is behind another wider proxy
   volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - ./volumes/caddy/data:/data
      - ./volumes/caddy/config:/config
   networks:
      ...

d. My complete Caddy config:

{
    email admin@lemmy.pt
    log {
      format console
    }

    servers {
      metrics
    }

    http_port ...
}


(lemmycommon) {
    header {
        Strict-Transport-Security max-age=63072000

        # Various content security headers
        Referrer-Policy same-origin
        X-Content-Type-Options nosniff
        X-Frame-Options DENY
        X-XSS-Protection "1; mode=block"
        # disable FLoC tracking
        Permissions-Policy interest-cohort=()
    }

    # Enable compression for JS/CSS/HTML bundle, for improved client load times.
    # It might be nice to compress JSON, but leaving that out to protect against potential
    # compression+encryption information leak attacks like BREACH.
    @encode_mime {
        header Content-Type text/css
        header Content-Type application/javascript
        header Content-Type image/svg+xml
    }
    encode @encode_mime gzip

    request_body {
        max_size 10MB
    }

}

http://lemmy.pt {
    import lemmycommon

    @pictshare_regexp path_regexp pictshare_regexp \/pictshare\/(.*)
    redir @pictshare_regexp /pictrs/image/{re.pictshare_regexp.1} permanent

    @backend `
    path('/api/*', '/pictrs/*', '/feeds/*', '/nodeinfo/*', '/.well-known/*')
    || header({'Accept': 'application/*'})
    || method('POST')
    `
    @backend_metrics `path('/metrics')`

    reverse_proxy @backend lemmy:8536
    reverse_proxy @backend_metrics lemmy:10002

    reverse_proxy lemmy-ui:1234
}

http://m.lemmy.pt {
    import lemmycommon
    reverse_proxy voyager:5314
}

http://old.lemmy.pt {
    import lemmycommon
    reverse_proxy mlmym:8080
}

http://a.lemmy.pt {
    import lemmycommon
    reverse_proxy alexandrite:3000
}

http://p.lemmy.pt {
    import lemmycommon
    reverse_proxy photon:3000
}

http://metricas.lemmy.pt {
    reverse_proxy netdata:19999
}

5. Links to relevant resources:

Suggested nginx config (on which I based my caddyfile)
Suggested nginx cache config

Hello @tmpod I’m on it to setup a working Caddyfile with HTTP cache.

@tmpod here is the minimal config I made to proxy and have cache on lemmy.pt

{
    order cache before rewrite
    cache {
        nuts {
            path ./test
        }
    }
}

localhost:80

route {
    cache {
        # Only if you want to prevent the Pragma: no-cache or the Cache-Control: no-cache being interpreted from the request headers
        mode bypass_request
    }
    reverse_proxy https://lemmy.pt {
        header_up Origin lemmy.pt
        header_up Host lemmy.pt
    }
}

I think you config may look like the following:

{
    order cache before rewrite
    cache {
        ttl 4h
        stale 24h
        nuts {
            path ./test
        }
    }
    email admin@lemmy.pt
    log {
      format console
    }

    servers {
      metrics
    }

    http_port ...
}


(lemmycommon) {
    cache {
        # Only if you want to prevent the Pragma: no-cache or the Cache-Control: no-cache being interpreted from the request headers
        mode bypass_request
    }
    header {
        Strict-Transport-Security max-age=63072000

        # Various content security headers
        Referrer-Policy same-origin
        X-Content-Type-Options nosniff
        X-Frame-Options DENY
        X-XSS-Protection "1; mode=block"
        # disable FLoC tracking
        Permissions-Policy interest-cohort=()
    }

    # Enable compression for JS/CSS/HTML bundle, for improved client load times.
    # It might be nice to compress JSON, but leaving that out to protect against potential
    # compression+encryption information leak attacks like BREACH.
    @encode_mime {
        header Content-Type text/css
        header Content-Type application/javascript
        header Content-Type image/svg+xml
    }
    encode @encode_mime gzip

    request_body {
        max_size 10MB
    }

}

http://lemmy.pt {
    import lemmycommon

    @pictshare_regexp path_regexp pictshare_regexp \/pictshare\/(.*)
    redir @pictshare_regexp /pictrs/image/{re.pictshare_regexp.1} permanent

    @backend `
    path('/api/*', '/pictrs/*', '/feeds/*', '/nodeinfo/*', '/.well-known/*')
    || header({'Accept': 'application/*'})
    || method('POST')
    `
    @backend_metrics `path('/metrics')`

    reverse_proxy @backend lemmy:8536
    reverse_proxy @backend_metrics lemmy:10002

    reverse_proxy lemmy-ui:1234
}

http://m.lemmy.pt {
    import lemmycommon
    reverse_proxy voyager:5314
}

http://old.lemmy.pt {
    import lemmycommon
    reverse_proxy mlmym:8080
}

http://a.lemmy.pt {
    import lemmycommon
    reverse_proxy alexandrite:3000
}

http://p.lemmy.pt {
    import lemmycommon
    reverse_proxy photon:3000
}

http://metricas.lemmy.pt {
    reverse_proxy netdata:19999
}

With that all your domains that import lemmycommon will use the cache directive for all routes.
With the given config the key will be considered as fresh for 4 hours, stale for 1d and won’t obey to the no-cache directive from the client.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.