Environment variables aren't visible

I’m trying to get some environment variables to show up inside a container, but I’m having problems.

I did lxc config set ubuntu environment.ZZZ Something. After that lxc exec ubuntu -- env shows the variable, so LXD probably did something right.

However, doing lxc console ubuntu and then env doesn’t show the variable. Even doing lxc restart ubuntu && lxc console ubuntu and then running env doesn’t show the variable.

I’m confused. I’d expect those variables set through LXD to be global for the machine running inside the container. What is the point of having this configuration option if only LXD can see them?

That’s not how this works unfortunately. Those environment variables are passed to anything you lxc exec and is passed to the container’s init system.

Unfortunately init systems usually don’t care much for those environment variables and never propagate them to their children, meaning that they’re effectively just present in lxc exec sessions or to scripts which directly look at PID 1’s environment.

Ah so they’re in /proc/1/environ only?

I see this file shows just those that I set - there’s nothing else. Would it be safe to propagate this unconditionally through an init script or something of the sort?

I mean, who else might touch this besides lxc config?

Parsing/sourcing that environment should be fine

You could put those variables in /etc/environment, then restart the container. The new variables should be visible system-wide.

lxc config is instant. I like that. Pity even /proc/1/environ isn’t instant. Guess what I see happen is just lxc console or lxc exec setting these variables before it shows a prompt.

So yeah I guess restarting is required for config changes to be picked up.

How does docker do it? /proc/1/environ has them, env has them, but /etc/environment doesn’t even exist. On lxd the last one just has PATH on ubuntu and nothing besides comments on alpine.

Yeah, we can’t change the environment of an existing process, so to see a change in PID1’s environment, a restart is needed.

@stgraber can you clarify how to get user variables, please?

lxc config set $ct user.fqdn test.hostname 
lxc exec $ct env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
container=lxc
LANG=C.UTF-8
TERM=xterm-256color
HOME=/root
USER=root

lxc exec $ct cat /proc/1/environ
container=lxc

That’s all. What I’m doing wrong?

lxc restart $ct does not change anything

user.* keys aren’t environment keys, they’re used to attach extra metadata to the container but are only visible from inside the container if you query them through /dev/lxd.

To do what you’re showing above, you’d want to use environment.fqdn instead.

1 Like

Hello!

I found this thread while looking to use environment variables in LXC.

I have a container setup and I’d like to run a Python script that requires a few environment variables set.

I’ve done the following:

lxc config set my_container environment.MYPATH "/path/to/config"
lxc restart my_container
lxc exec my_container env
(...)
MYPATH=/path/to/config
(...)
lxc exec my_container -- bash
root@my_container:~# echo $MYPATH
/path/to/config # All good...
lxc exec my_container -- bash -c "source /proc/1/environ && echo $MYPATH"
# Nothing is returned!

I need to trigger the Python script using lxc exec my_container -- bash -c "...", how can I retrieve the environment variable that I’ve just set?

EDIT: I’m not sure why, but this works:

lxc exec my_container -- bash -c "python3 -c 'import os; print(os.environ[\"MYPATH\"])'"
/path/to/config

Any explanation on why this works but the previous command doesn’t would be more than welcome :slight_smile:

That would be because init (systemd) clears its own environment, so even though we do expose those env variables to it on startup, it doesn’t really do anything.