Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to inject environment variables in Varnish configuration

I have 2 environments variables :

echo $FRONT1_PORT_8080_TCP_ADDR # 172.17.1.80
echo $FRONT2_PORT_8081_TCP_ADDR # 172.17.1.77

I want to inject them in a my default.vcl like :

backend front1 {
    .host = $FRONT1_PORT_8080_TCP_ADDR;
}

But I got an syntax error on the $ char.

I've also tried with user variables but I can't define them outside vcl_recv.

How can I retrieve my 2 values in the VCL ?

like image 813
manuquentin Avatar asked Jan 10 '14 23:01

manuquentin


5 Answers

I've managed to parse my vcl

backend front1 {
    .host = ${FRONT1_PORT_8080_TCP_ADDR};
}

With a script:

envs=`printenv`

for env in $envs
do
    IFS== read name value <<< "$env"

    sed -i "s|\${${name}}|${value}|g" /etc/varnish/default.vcl
done
like image 91
manuquentin Avatar answered Nov 20 '22 07:11

manuquentin


Now you can use the VMOD Varnish Standard Module (std) to get environment variables in the VCL, for example:

set req.backend_hint = app.backend(std.getenv("VARNISH_BACKEND_HOSTNAME"));

See documentation: https://varnish-cache.org/docs/trunk/reference/vmod_std.html#std-getenv

like image 21
Mauricio Sánchez Avatar answered Nov 20 '22 07:11

Mauricio Sánchez


Note: it doesn't work for backend configuration, but could work elsewhere. Apparently backends are expecting constant strings and if you try, you'll get Expected CSTR got 'std.fileread'.

You can use the fileread function of the std module, and create a file for each of your environment variables.

before running varnishd, you can run:

mkdir -p /env; \
env | while read envline; do \
    k=${envline%%=*}; \
    v=${envline#*=}; \
    echo -n "$v" >"/env/$k"; \
done

And then, within your varnish configuration:

import std;

...

backend front1 {
    .host = std.fileread("/env/FRONT1_PORT_8080_TCP_ADDR");
    .port = std.fileread("/env/FRONT1_PORT_8080_TCP_PORT");
}

I haven't tested it yet. Also, I don't know if giving a string to the port configuration of the backend would work. In that case, converting to an integer should work:

.port = std.integer(std.fileread("/env/FRONT1_PORT_8080_TCP_PORT"), 0);
like image 22
Mildred Avatar answered Nov 20 '22 08:11

Mildred


You can use use echo to eval strings.

Usually you can do something like:

VAR=test # Define variables

echo "my $VAR string" # Eval string

But, If you have the text in a file, you can use "eval" to have the same behaviour:

VAR=test # Define variables

eval echo $(cat file.vcl) # Eval string from the given file
like image 31
Joskfg Avatar answered Nov 20 '22 06:11

Joskfg


Sounds like a job for envsubst.

Just use standard env var syntax in your config $MY_VAR and ...

envsubst < myconfig.tmpl > myconfig.vcl

You can install with apt get install gettext in Ubuntu.

like image 41
MattK Avatar answered Nov 20 '22 08:11

MattK