#29766·podman

Support environment variable interpolation during unit generation

Author: b-thinkingCreated Sep 13, 2026Updated Sep 16, 2026
Labelskind/featurequadlettriaged

Feature request description

Quadlet: support environment variable interpolation during unit generation

Feature request

I would like to propose support for environment-variable interpolation during Quadlet unit generation.

Quadlet currently supports systemd specifiers such as %h, and variables can also be expanded by systemd when the generated unit is executed. However, there does not appear to be a general mechanism for supplying host-side configuration variables to the Quadlet generator itself and using them in Quadlet-specific directives.

This becomes particularly relevant for host-specific configuration such as bind-mount paths.

Example use case

Suppose I have the following user environment configuration:

ini
# ~/.config/environment.d/ai.conf

PODMAN_VOLUMES_AI=/srv/ai

I would like to be able to write a Quadlet such as:

ini
[Container]
Image=docker.io/ollama/ollama:0.34.0

Volume=${PODMAN_VOLUMES_AI}/ollama/.ollama:/root/.ollama:Z
Volume=${PODMAN_VOLUMES_AI}/ollama/.tmp:/tmp:Z

and have Quadlet resolve ${PODMAN_VOLUMES_AI} while generating the systemd unit, resulting in the equivalent of:

--volume /srv/ai/ollama/.ollama:/root/.ollama:Z
--volume /srv/ai/ollama/.tmp:/tmp:Z

The variable is a host-side configuration variable. It is not intended to be passed into the container.

Why systemd EnvironmentFile= does not solve this use case

There are currently two different stages involved:

Quadlet source
     |
     v
quadlet-generator
     |
     v
generated systemd unit
     |
     v
systemd variable expansion
     |
     v
podman

Using:

ini
[Service]
EnvironmentFile=%h/.config/environment.d/ai.conf

allows systemd to expand variables at the second stage.

For example, this works for values that remain part of the generated systemd unit and are subsequently interpreted by systemd.

However, Quadlet-specific directives such as:

ini
Volume=
PublishPort=
Network=
Image=

are interpreted by Quadlet while generating the systemd unit. By the time systemd performs its own environment-variable expansion, these directives have already been converted into the corresponding Podman command-line arguments.

Therefore, a value such as:

ini
Volume=${PODMAN_VOLUMES_AI}/ollama:/root/.ollama:Z

cannot currently be used to parameterize the host-side path at Quadlet generation time.

This is an important distinction between:

  • runtime/systemd environment variables, and
  • variables used to parameterize the Quadlet source itself.

Proposed behavior

I suggest providing an explicit mechanism for making host-side variables available to the Quadlet generator.

The exact implementation is open for discussion. For example, this could be an explicit Quadlet configuration mechanism such as:

ini
[Quadlet]
EnvironmentFile=%h/.config/environment.d/ai.conf

or another mechanism considered more appropriate by the maintainers.

The important part of the proposed behavior is that variables would be available during Quadlet parsing/generation, so that:

ini
Volume=${PODMAN_VOLUMES_AI}/ollama:/root/.ollama:Z

could be resolved before the generated systemd unit is produced.

I would prefer this to be a general interpolation mechanism rather than special handling for Volume=.

Potential examples include:

ini
Image=${IMAGE}
Volume=${CONTAINER_DATA}/app:/data:Z
PublishPort=${APP_PORT}:8080
Network=${NETWORK}

This is not intended to replace container environment variables

It is worth emphasizing that this feature would serve a different purpose from:

ini
[Container]
Environment=...
EnvironmentFile=...

Those directives configure the environment inside the container.

The proposed functionality would configure the environment available to the Quadlet generator, allowing host-side Quadlet configuration to be parameterized.

For example:

Host configuration
       |
       v
Quadlet generator
       |
       | interpolate ${VARIABLE}
       v
Generated systemd unit
       |
       v
Podman container

The variable does not necessarily need to exist inside the resulting container.

Related discussions and issues

There have already been several discussions about this general limitation.

Discussion #26536 — Variable substitution in quadlet files

https://github.com/containers/podman/discussions/26536

This discussion asks explicitly about variable substitution in .container, .network, and .volume files. The use case is to keep image versions consistent across multiple Quadlet files without passing the variables into the container.

The suggested solution was to use EnvironmentFile= under [Service].

This is closely related to the feature requested here, but it does not solve the generation-time problem described above: systemd expands the variables after Quadlet has already generated the unit.

Discussion #26933 — What I can't do with Quadlets...

https://github.com/containers/podman/discussions/26933

This discussion describes several use cases where variables are used with scripted podman run/podman build workflows but cannot be used in the corresponding Quadlet parameters, including image tags, IP addresses, health commands, and volume mounts.

The discussion explicitly asks whether environment variables could be supported in [Container], [Build], [Image], etc.

Again, this is very close to the proposed feature, but it is a Q&A discussion rather than an implementation request for a defined generation-time interpolation mechanism.

Issue #25047 / Discussion #25053 — Environment variables unavailable in Exec=

https://github.com/containers/podman/issues/25047

https://github.com/containers/podman/discussions/25053

These discussions are useful because they explicitly demonstrate the distinction between the two levels of variable expansion.

The resolution is to put EnvironmentFile= under [Service], allowing systemd to substitute the variable before invoking Podman.

That is useful for values that survive into the generated systemd unit, but it does not provide interpolation of Quadlet directives during Quadlet generation.

Why I think this would be useful

Quadlet is already a declarative layer that generates systemd units. Allowing controlled parameterization of Quadlet source files would make it possible to reuse the same Quadlet definition across hosts with different:

  • host storage locations;
  • image versions;
  • network names;
  • published ports;
  • other host-specific configuration.

It would also avoid having to introduce external template-generation scripts merely to substitute a small number of host-specific values.

Systemd specifiers such as %h solve some common cases, but they cannot represent arbitrary host configuration such as:

PODMAN_VOLUMES_AI=/srv/ai

without resorting to symlinks, generated Quadlet files, wrappers, or other workarounds.

Desired error handling

If generation-time interpolation is implemented, I would suggest that references to undefined variables produce a clear error or warning during Quadlet generation rather than silently generating an invalid unit.

The exact syntax and implementation details are, of course, open to discussion.

Summary

The requested feature is therefore not simply "expand environment variables in Volume=".

The broader request is:

Provide an explicit and controlled mechanism for environment-variable interpolation while Quadlet is generating the systemd unit, distinct from the environment used by the generated service or by the container itself.

The Volume= example above is simply a concrete use case where the distinction is particularly easy to demonstrate.

Disclaimer

This feature request was drafted with the assistance of AI.

However, the underlying request is based on a real problem encountered while using Podman Quadlet. The issue was also independently reflected in several existing Podman discussions and issues, including #26536, #26933, and #25047/#25053. The purpose of this request is to consolidate the underlying use case and clearly distinguish generation-time Quadlet interpolation from the existing systemd runtime environment-variable expansion.

Suggest potential solution

Proposed solution

One possible implementation would be to introduce a dedicated [Quadlet] section for variables that are evaluated by the Quadlet generator itself.

For example:

ini
[Quadlet]
EnvironmentFile=%h/.config/containers/quadlet.env

with:

ini
# ~/.config/containers/quadlet.env

PODMAN_VOLUMES_AI=/srv/ai
OLLAMA_VERSION=0.34.0
AI_NETWORK=ai.network

Variables defined in this file would be available only during Quadlet generation and would not automatically become part of the generated systemd service environment or the container environment.

The Quadlet file could then use them as follows:

ini
[Quadlet]
EnvironmentFile=%h/.config/containers/quadlet.env

[Container]
Image=docker.io/ollama/ollama:${OLLAMA_VERSION}

Volume=${PODMAN_VOLUMES_AI}/ollama/.ollama:/root/.ollama:Z
Volume=${PODMAN_VOLUMES_AI}/ollama/.tmp:/tmp:Z

Network=${AI_NETWORK}

During generation, Quadlet would resolve the variables and generate a systemd unit equivalent to:

Image=docker.io/ollama/ollama:0.34.0

--volume /srv/ai/ollama/.ollama:/root/.ollama:Z
--volume /srv/ai/ollama/.tmp:/tmp:Z

--network ai.network

Why a dedicated [Quadlet] section?

Using a dedicated section would make the evaluation stage explicit and avoid ambiguity with the existing systemd and container environments.

There would then be three clearly separated scopes:

[Quadlet]
    |
    | generation-time variables
    v
quadlet-generator
    |
    v
[Service]
    |
    | systemd runtime environment
    v
systemd
    |
    v
[Container]
    |
    | container environment
    v
container

This would also avoid making Quadlet implicitly dependent on the ambient environment of the quadlet-generator process.

Alternative: inline variable definitions

An alternative, or complementary mechanism, could be to allow variables to be defined directly in the Quadlet file:

ini
[Quadlet]
PODMAN_VOLUMES_AI=/srv/ai
OLLAMA_VERSION=0.34.0
AI_NETWORK=ai.network

and subsequently referenced using:

ini
[Container]
Image=docker.io/ollama/ollama:${OLLAMA_VERSION}
Volume=${PODMAN_VOLUMES_AI}/ollama:/root/.ollama:Z
Network=${AI_NETWORK}

An EnvironmentFile=-style mechanism would nevertheless be preferable for host-specific configuration because it would allow the same Quadlet definition to be deployed unchanged on different hosts.

Variable precedence

If both an environment file and inline definitions are supported, a well-defined precedence order would be useful.

For example:

  1. Variables explicitly defined in [Quadlet];
  2. Variables supplied by [Quadlet] EnvironmentFile=;
  3. Optionally, variables from a documented generator environment.

The exact precedence is open for discussion.

Undefined variables

An undefined ${VARIABLE} should preferably result in a clear error from quadlet-generator, identifying both the Quadlet file and the variable that could not be resolved.

For example:

Error: undefined Quadlet variable 'PODMAN_VOLUMES_AI'
       in ollama.container: Volume=...

This would be preferable to silently generating a malformed systemd unit.

Variable expansion syntax

The proposed ${VARIABLE} syntax is intentional because it clearly distinguishes generation-time interpolation from systemd specifiers such as %h.

It also follows a syntax already familiar to users from shell environments, systemd, container configuration and other declarative tools.

The implementation should define escaping rules and, in particular, ensure that users can still provide a literal $ or ${...} when required.

Have you considered any alternatives?

A clear and concise description of any alternative solutions or features you've considered.

Additional context

Add any other context or screenshots about the feature request here.

Source: podman-container-tools/podman