Iterating over a comma deliminated environment variable

1. Caddy version (caddy version):

caddy:2.4.6

2. How I run Caddy:

My Caddyfile:

{
    admin off
    auto_https off

    log {
        format json
    }
}

(cors) {
    @origin{args.0} header Origin {args.0}
    header @origin{args.0} Access-Control-Allow-Origin "{args.0}"
    header @origin{args.0} Vary Origin
}

:80 {
    root * /static
    file_server

    @options {
        method OPTIONS
    }

    respond @options 204
    respond / 200

    header Access-Control-Allow-Methods "POST, GET, OPTIONS"
    header Access-Control-Allow-Headers "*"
    import cors {$CORS_ALLOWED_ORIGIN}

    log {
        output stdout
        format json
    }
}

a. System environment:

My Dockerfile:

FROM caddy:2.4.6

COPY META-INF/resources/*.css /static/
COPY Caddyfile /etc/caddy/Caddyfile

RUN \
	caddy fmt --overwrite /etc/caddy/Caddyfile && \
	caddy validate --config /etc/caddy/Caddyfile && \
	cat /etc/caddy/Caddyfile

EXPOSE 8080/tcp

b. Command:

See the docker file. I just run that with default commands.

3. The problem I’m having:

I’d like to change CORS_ALLOWED_ORIGIN environment var to be a comma delimited list and then invoke the cors macro for each entry.

I think that’s more “smarts” than the Caddyfile was designed for. I don’t think we’ll implement something like that.

You’re probably better off writing a bash script which performs those expansions yourself. Emit it to a file like caddy-cors.txt, mount that at runtime, then do import /etc/caddy/caddy-cors.txt. The file would have this in it:

@origin-example1.com header Origin example1.com
header @origin-example1.com Access-Control-Allow-Origin "example1.com"
header @origin-example1.com Vary Origin

@origin-example2.com header Origin example2.com
header @origin-example2.com Access-Control-Allow-Origin "example2.com"
header @origin-example2.com Vary Origin
1 Like

Ok good to know.

One last question though. When Caddy imports a file (like your example import /etc/caddy/caddy-cors.txt) is that file subject to templating? i.e. can templating generate Caddy instructions?

There’s not really any “templating” going on, just environment variable expansion, and import.

Yes, imports are recursive, and yes env vars are expanded within imported files.

It essentially gets flattened to a single file, then parsed.

Thank you for your insights! Much appreciated :slightly_smiling_face:

1 Like

For posterity here’s what I did (following @francislavoie 's suggestion).

I changed the Caddyfile like so:

{
    admin off
    auto_https off

    log {
        format json
    }
}

:80 {
    root * /static
    file_server
    encode gzip

    @options {
        method OPTIONS
    }

    respond @options 204
    respond / 200

    header Access-Control-Allow-Methods "POST, GET, OPTIONS"
    header Access-Control-Allow-Headers "*"
    import /etc/caddy.d/*

    log {
        output stdout
        format json
    }
}

Notice import /etc/caddy.d/*.

I then wrote a small ash script (to stay in the limits of Caddy base image):

for i in $(echo $CORS_ALLOWED_ORIGIN | tr "," "\n"); do
    ADDRESS="https://${i}" # strictly https
    cat >> /etc/caddy.d/cors.txt << EOF
    @origin${ADDRESS} header Origin ${ADDRESS}
    header @origin${ADDRESS} Access-Control-Allow-Origin "${ADDRESS}"
    header @origin${ADDRESS} Vary Origin
EOF
done
caddy run --config /etc/caddy/Caddyfile --adapter caddyfile

And finally the Dockerfile:

FROM caddy:2.4.6

RUN mkdir -p /etc/caddy.d;

COPY META-INF/resources /static/
COPY caddycmd.sh /usr/share/caddycmd.sh
COPY Caddyfile /etc/caddy/Caddyfile

RUN chmod +x /usr/share/caddycmd.sh

CMD ["sh", "-c", "/usr/share/caddycmd.sh"]

The result is not too onerous :slight_smile:

However, Caddyfile would be super powered by allowing go templates on import. Since, as you stated, all imports are resolved before the Caddyfile is parsed, it’d be no different than having an external template engine generate the Caddyfile (except no need for external dependencies. You have the go template engine right there.)

Anyway, just food for thought.

But thanks a bunch for the already awesome product.

1 Like