Passing environment variables around in systemd

EnvironmentFile is not an option as per this answer.

I am trying to understand the recommended way of using and passing environment variables.

I have a urxvtd.socket:

[Unit]
Description=urxvt deamon (socket activation)
Documentation=man:urxvtd(1) man:urxvt(1)

[Socket]
ListenStream=%t/urxvt/urxvtd-%H

[Install]
WantedBy=sockets.target

Now a urxvtd.service with a Requires dependency on that urxvtd.socket:

[Unit]
Description=Urxvt Terminal Daemon
Requires=urxvtd.socket

[Service]
# Needs to know socket file location RXVT_SOCKET environment variable.
# Where will it come from?
ExecStart=/usr/bin/urxvtd -o -q

[Install]
WantedBy=default.target

Now I need RXVT_SOCKET to be set before starting i3 as i3 will have a key binding to start urxvtc (urxvt client).

If I start i3/Xorg without systemd (i.e with xinitrc), and put in .zshenv (user specific environment file loaded always.):

export RXVT_SOCKET=${XDG_RUNTIME_DIR}/urxvt/urxvtd-machinename

Then urxvtc launched by i3 will correctly infer the RXVT_SOCKET variable and look for the socket at that path.

However, the urxvtd.service launches urxvtd (the daemon), so it also needs RXVT_SOCKET.

The Archwiki recommends setting the environment in urxvtd.service:

...
Environment=RXVT_SOCKET=%t/urxvtd-%H
...

But therein the problem lies. Why should the environment variable be set again in urxvtd.service, when the initial user urxvtd.socket should set it?

Note, it is set again in .zshenv for i3 to get it. This is a case of multiple sources of truth for one simple environment variable..

Did we notice that urxvtd.service example above has the incorrect path for RXVT_SOCKET set in .zshenv? Reiterates my multiple source of truth argument.

What is the best way to deal with this?

I was thinking maybe I can set the RXVT_SOCKET in urxvtd.socket as so:

[Socket]
Environment=RXVT_SOCKET
ListenStream=%t/urxvt/urxvtd-%H

And since urxvtd.service is a dependency then there should be a way to import environment variable. But there isn’t. So urxvtd daemon will behave as if RXVT_SOCKET is not set, but the socket will be created correctly due to urxvtd.socket.

Then I dug a bit deeper, and systemctl --user import-environment RXVT_SOCKET should import the variable across systemd units. Would that really be the way? Then I also need to ensure that the import happens before urxvtd.service runs. How would that work?

If I do use Xorg/i3 with systemd, I believe there should be a way to transfer the environment variable across systemd units.

At this point I am likely to believe there is no pure systemd solution to such requirement for propagation of environment variables

I ended up using a shell to wrap the ExecStart command since the shell will inherit the environment correctly.