nginx / unit

NGINX Unit - universal web app server - a lightweight and versatile open source server that simplifies the application stack by natively executing application code across eight different programming language runtimes.
https://unit.nginx.org
Apache License 2.0
5.29k stars 325 forks source link

Access to environment variables in Unit config #968

Open cohix opened 9 months ago

cohix commented 9 months ago

When writing a Unit config, certain parts may need to be dynamically inserted, and so it would be great to be able to reference env vars that get evaluated at runtime. For example, I'd like to be able to do this:

"applications": {
            "foo": {
                    "type": "external",
                    "working_directory": "$(HOME)/path/to/thing",
                    "executable": "app",
                    "environment": {
                        "SOME_APP_CONFIG": "$(SOME_ENV_VAR)"
                    }
            }
    }

Which currently does not work.

travisbell commented 9 months ago

Oooooh, this is a good one. I use envtpl right now to get this functionality in my configs but would love to drop it as a dependency!

hongzhidao commented 9 months ago

Hi, There are a few separate functions here.

  1. Unit supports variables and njs/JS for options like pass, share, etc. https://unit.nginx.org/scripting/
  2. It's able to access environment variables with njs. https://nginx.org/en/docs/njs/reference.html#process
  3. The variables and JS only work on the runtime phase.

But the option environment in the application is applied when the proto process starts, it's a different phase than the runtime phase which runs for the http request.

To make it short, the feature is about whether Unit provides variable engine in the application starting phase. We'll discuss it with the team, and any thoughts are welcome.

hongzhidao commented 9 months ago

Hi, our thoughts on it:

  1. Users can now use a config template to maintain the "environment" options.
  2. We agree it's more convenient to provide native variables for the application options like working_directory and environment. Now we are on the 1.32 version and we'll try it when we start the 1.33 version.

Thanks.

lcrilly commented 9 months ago

If we consider that envsubst(1) and similar tools provides a reasonable workaround today, how useful would it be to "pass through" specific environment variables to the application's environment?

{
  "applications": {
    "foo": {
      "type": "external",
      "working_directory": "/path/to/thing",
      "executable": "app",
      "environment_passthrough": ["SOME_ENV_VAR", "OTHER_ENV_VAR"],
      "environment": {
        "HOME": "/path/to/thing"
      }
    }
  }
}

Would this be a worthwhile feature in its own right? Or is full access to env vars, across the entire configuration scope the main thing? If so, we might also consider environment variable substitution a function that the unitc CLI tool can provide.

razvanphp commented 9 months ago

Our use-case would be to configure number of processes, options for applications (like memory_limit), etc. Thank you!

travisbell commented 9 months ago

Yup, same here. Here's what one of our configs looks like and how we use ENV vars in our config:

"applications": {
    "sinatra": {
      "type": "ruby",
      "processes": {{ NUM_WORKERS }},
      "threads": {{ WORKER_THREADS_MAX }},
      "script": "{{ HOME }}/workspace/app/config.ru",
      "hooks": "{{ HOME }}/workspace/app/config/unit/hooks.rb",
      "working_directory": "{{ HOME}}/workspace/app/",
      "limits": {
        "timeout": 30
      }
    }
  }
gourav-kandoria commented 3 months ago

@lcrilly Does this issue needs work. Would be happy to work on it

lcrilly commented 3 months ago

Yes, still open. Would welcome a contribution but makes sense to discuss the approach and design here, first.

For example, are we reading the env vars of the user applying the configuration or the user that owns the unit: controller process?