Using Environment Variables #

It is good practice to make a FLAT app configurable so that it can run in multiple environments. For example, the upstream APIs have different locations in a local development setup and the production system.

FLAT runs as a Docker Container and can make use of the environment variables defined, for example, in the Dockerfile, docker-compose.yaml or with docker run -e.

Defining Environment Variables #

Docker #

As usual, environment variables can be defined in the docker-compose.yaml like this:

services:
  flat:
    image: code-registry.avenga.cloud/product/flat/flat/flatrunner
    volumes:
      - .:/app
    ports:
      - 8080:8080
    environment:
      - MY_VAR=my value
      - FLAT_DEBUG_ALLOW_HEADER=true

Here, we have defined MY_VAR in the environment section and enabled debugging via HTTP header. (We assume, that you have a swagger.yaml and some API path that you can call. If you’re not so far, yet, checkout the tutorial).

Start the container with

$ docker compose up

and run the following curl command. The environment variables can be inspected with the env debug topic: The inline sink interweaves the debug output with your API response. It will disturb your response, but it is sometimes handy for debugging:

$ curl -s -H debug:env::inline localhost:8080
debug   [env]           Env vars: {
    …
    "FLAT_DEBUG_ALLOW_HEADER": "true",
    …
    "MY_VAR": "my value",
    …
}

There’s our MY_VAR!

Another way of defining environment vars would be the -e flag of a simple docker run:

$ docker run --rm -it -e MY_VAR="my value" -v "$(pwd):/app" code-registry.avenga.cloud/product/flat/flat-src/flatrunner

Great! We now know how to define environment variables. Let’s use them!

Accessing Environment Variables in Flows #

All environment variables are accessible from flows by the system variable $env. It is an object with the defined environment variables as properties:

{
  "MY_VAR": "my value",
  …
}

We could create a simple template to send our environment variable back to the client:

<flow>
  <template>
  {
    "my var": {{ $env/MY_VAR }}
  }
  </template>
</flow>

Use Cases #

Upstream URLs #

A typical use-case for an environment variable is the base URL of an upstream API.

Let’s define the origin of our auth service:

AUTH_SERVICE=http://localhost:3000

To request the auth service, we have to build a URL:

<flow>
  <request>
  {
    "url": {{ concat($env/AUTH_SERVICE, "/v1/logout" )}},
    "headers": {
      {{: $request/headers/authorization }}
    }
  }
  </request>
</flow>

If the app is deployed into production, the AUTH_SERVICE variable will be set to another value, probably one with https and running on a different port.

JWT #

When working with JWT a signing key (or two, in case of RS* algorithms) need to be configured in FLAT. It is good idea to pass these as environment variables.

See Working with JWT for a larger example.

Credentials #

Often, access between services is restricted by an HTTP Authentication.

You could read Basic Authentication credentials from an environment variable in your request:

<flow>
  <request>
  {
    "url": "…",
    "options": {
      "basic-auth-credentials": {{ $env/AUTH_SERVICE_CREDS }}
    }
  }
  </request>
</flow>

Or if you need to include a token in your requests:

<flow>
  <request>
  {
    "url": "…",
    "headers": {
      "authentication": {{ concat("Bearer ", $env/AUTH_SERVICE_TOKEN) }}
    }
  }
  </request>
</flow>

See also #