Environment variable not getting interpolated into another environment variable

I am trying to set up Miniflux with postgres and consul for service discovery, but for whatever reason I can’t get the environment variable for the database address (NOMAD_UPSTREAM_ADDR_postgres) to interpolate, because when I look at the error logs for miniflux I see it complaining it can’t parse ${NOMAD_UPSTREAM_ADDR_postgres}. Here is my job declaration:

job "miniflux" {
  datacenters = ["dc1"]

  update {
    stagger = "10s"
    max_parallel = 1
  }

  group "postgres" {
    network {
      port "db" {
        to = 5432
      }
    }

    task "postgres" {
      driver = "docker"
      config {
        image = "postgres"
        ports = ["db"]

        volumes = [
          "miniflux-db:/var/lib/postgresql/data"
        ]
      }

      resources {
        cpu = 256
        memory = 256
      }

      env {
        POSTGRES_USERNAME = "postgres"
        POSTGRES_PASSWORD = "postgres"
      }

      service {
        name = "postgres"
        port = "db"

        check {
          name = "alive"
          type = "tcp"
          interval = "10s"
          timeout = "2s"
        }
      }
    }

    restart {
      attempts = 10
      interval = "5m"
      delay = "25s"
      mode = "delay"
    }
  }

  group "miniflux" {
    network {
      port "app" {
        to = 80
      }
    }
    
    restart {
      attempts = 10
      interval = "5m"
      delay = "25s"
      mode = "delay"
    }

    task "miniflux" {
      env {
        DATABASE_URL = "postgres://postgres:postgres@${NOMAD_UPSTREAM_ADDR_postgres}/miniflux?sslmode=disable"
        RUN_MIGRATIONS = "1"
        CREATE_ADMIN = "1"
        ADMIN_USERNAME = "pta2002"
        ADMIN_PASSWORD = "password"
      }

      service {
        name = "miniflux"
        port = "app"

        check {
          name = "alive"
          type = "tcp"
          port = "app"
          interval = "10s"
          timeout = "2s"
        }

        tags = [
          "traefik.enable=true",
          "traefik.http.routers.miniflux.rule=PathPrefix(`/miniflux`)"
        ]
      }

      driver = "docker"

      config {
        image = "miniflux/miniflux"
        ports = ["app"]
      }
    }
  }
}

The “upstream” environment variable is only available if you have an upstream registered.

You need a connect-service in your miniflux-task, containing an upstream.

service {
  #...blah, blah..
  connect {
    sidecar_service {
      proxy {
        upstreams {
         destination_name = "postgres"
          local_bind_port = 5432 # Or anything you like
        }
      }
    }
  }
}

See the consul-connect example for countdash.

Thank you, I’ll try this later tonight. Is there any other way to connect to the postgres instance, or does it have to be this way? I only defined them in separate groups because they don’t necessarily have to be on the same node.

You CAN expose the database-port on the host, and connect without using consul-connect.
Then you can either use consul to find the host/port (consul dns, consul-template, etc), or just hardcode it (pin the postgres group/task to a known host, and use a static port).

One of the nice things about Nomad is that there is usually nothing you CAN’T do. If you have any preferred way to set it up, you will usually be able to do so.

I’d recommend you to stick with the connect-solution (ref. the countdash example), as it is a very nice and (by default) secure way to connect your services.

EDIT: If you put them in the same group (host), then it’s a lot easier. Just use variable interpolation (NOMAD_ADDR_<task>_<label>). Also, if you use e.g. bridge network mode, then all tasks in same group share the network stack, and you can access the other tasks on 127.0.0.1/localhost.

1 Like