Environment variables in Sway

:rofl:
Sure you can, as long as you know what’s inside, better use explicit names or conventional ones.

Yes. The Linux Common Communication Language. :rofl: Welcome to my world!!
No Desktop Environment, or Window Manager developers realize, or want to accept that they are not alone (users may want to use more than one DE/WM in one user account). That’s a psychiatric condition, IMHO, or something deeper exists and I cannot figure it out for more than a decade using Linux.

If you want to absolutely control how a user session handles environment variables, and more other settings, close it in a box you create yourself. Actually, create a session init executable (example for an Xorg session) with your preferred logic, and one session.desktop file for the relevant system session init folder (Xorg/Wayland).
Or better, create your own set of rules and create your own Display Environment.

TL;DR
For simple solutions to your problem, study Arch PKGBUILD for sway. I am sure you will have the answers you are looking for.
Like how you export envvars in sway config

exec systemctl --user set-environment XDG_CURRENT_DESKTOP=sway
exec systemctl --user import-environment DISPLAY \
                                         SWAYSOCK \
                                         WAYLAND_DISPLAY \
                                         XDG_CURRENT_DESKTOP

From /etc/sway/config.d/50-systemd-user.conf

@lorebett I will appreciate what you find along the way of Linux investigations :male_detective: :wink:

I think I’m getting close :wink:

systemctl --user show-environment

indeed shows the variables I defined in ~/.config/environment.d/*.conf files; but they are available only to systemd: if I open a terminal in sway and try to echo one of such variables, I get nothing!

The variables I defined in ~/.config/environment.d/*.conf (available to systemd) must be EXPLICITLY exported as environment variables. There’s a tool for that: /usr/lib/systemd/user-environment-generators/30-systemd-environment-d-generator.

One has to run

export $(/usr/lib/systemd/user-environment-generators/30-systemd-environment-d-generator)

But, of course, that only works for the currently open shell. And guess what? Running that command in the sway config as an exec_always is also useless.

You need to run that export command in a file that you know it will be sourced, e.g., .bash_profile (by the way, you cannot always automatically rely on .profile, https://nanxiao.me/en/why-doesnt-profile-take-effect-in-arch-linux/).

Alternatively, you do that in a custom start script before running Sway.

1 Like

I think you owe an explanation about the actual reason for this issue.
Is it for your one and only user account on your one system?
Is it an addition for your /etc/skel system files on your one system?
Is it for a redistributed method for general use?

I think that for one sway user account, the solution is given.
If you want to apply envvars conditionally, there are a few options. The goal is to have one file with conditional checks (per session type and session desktop), and source it from wayland and bash login initial files. You may also use systemd user services with conditionals, and/or the EnvironmentFile key. And more…
New user accounts always get bash files from skel

pacman -Qo /etc/skel/.*                                                                                                                                                            
/etc/skel/.bash_logout is owned by bash 5.2.026-2
/etc/skel/.bash_profile is owned by bash 5.2.026-2
/etc/skel/.bashrc is owned by bash 5.2.026-2

.profile does the same job as .bash_profile but is also sourced by some DMs. Not KISS behavior, but you can still decide one of them as main and source it from the other, so you don’t repeat exports.

There are more things to consider for the login process, depending on how you login and where from (TTY, DM), if the login executable is a shell script itself,etc.
That’s why a clarification for your use case may help give better info.
Or, why to bother? :crystal_ball: :thinking: :man_shrugging:

The reason for this issue is basically what I said in my original post: in the Sway edition, what’s in ~/.config/environment.d will NOT become environment variables available inside Sway (e.g., in terminals or in programs launched from Sway). What’s defined here: https://github.com/EndeavourOS-Community-Editions/sway/tree/main/.config/environment.d would only be available to systemd started services.

To properly have them as environment variables what’s inside .config/environment.d should be explicitly exported (e.g., as I showed above).

1 Like

This is a systemd functionality, and is used from DEs that use systemd/dbus and/or Wayland.

For sway only, you may use what I posted from sway PKGBUILD.

For bash, fill .profile with exports (with conditionals), source it from .bash_profile .
For Xorg, fill .xprofile with exports (with conditionals).

The problem is when you want to use different sessions, that don’t use the same init method, and have to stage traps. In such complicated, multipurpose cases, for absolute control, create a custom init script for each session.

1 Like

I now know how to implement it right, thanks for the hints.

But, again, it looks like what’s implemented in the Sway edition doesn’t work out of the box.
I’m talking about the configuration you get with the Sway edition. (I know, it’s not an official one)
I understand that the sway package deals with crucial variables.

2 Likes

Just in case, I documented my findings and my approach:

it literally says how you launch sway determines how you set environment variables, PAM was just an example with a login manager, there are other login managers, like SDDM.

But if you just launch it by typing sway in a tty, you could literally just set up a bash alias in bashrc so that it’ll haev a bunch of env variables, hell, you can even redirect it to a launch script of your choice that sets them instead of an alias if you need to set a lot of them.

The above-described approach works in all the scenarios you mentioned (it doesn’t even require a custom launcher), independent of how you launch Sway: it works when launched from tty and SDDM.

not bad! you should mark it as a solution.

This setup seems unnecessarily convoluted and messy. There are configs scattered all over the place, some of them sourcing other configs, and systemd is roped into it somehow… It’s just my opinion, but using a simple wrapper script seems much better than this approach.

Splitting environment variable declarations between ~/.profile and ~/.config/environment.d/ adds complexity. Users need to manage two separate files, which can lead to confusion and potential errors if variables are duplicated or not synchronized. Explicitly sourcing ~/.profile in ~/.bash_profile and ~/.zshenv adds another layer of complexity. It’s just a lot of separate files to maintain for this one thing.

I also think the systemd stuff should be left out of it. Not just because it makes the solution less portable (not all distros use systemd), but also it just seems a little clunky. Using 30-systemd-environment-d-generator to export systemd-managed environment variables back to the shell environment is basically just a workaround for the fact that the environment variables set by systemd are not automatically visible to Sway.

Also, the command export $(/usr/lib/systemd/user-environment-generators/30-systemd-environment-d-generator) assumes that all environment variables in any .conf file in the ~/.config/environment.d/ and /etc/environment.d/ directories are safe and intended to be exported as global environment variables. User beware: exporting unintended variables could lead to conflicts or security issues.

Another consideration is there are edge cases where environment variables need to be set before Sway is launched in order to work correctly. I remember this came up when I was trying to get Flameshot (the screenshotting tool) working on Sway. Setting XDG_CURRENT_DESKTOP=sway in ~/.profile was not good enough, it had to be set before starting Sway.

The methods described in your blog post set environment variables after the session is started. ~/.profile, ~/.bash_profile, or ~/.zshenv are sourced by the shell after a user logs in. This means the environment variables set in these files are available to the shell and applications started by the shell, but not to the Sway session itself if Sway has already started.

In a case where you need a variable to be set before the session starts (so the variables are available to Sway and all child processes), a wrapper script or appropriate display manager configuration should be used.

You could still use your setup with ~/.profile by making sure the display manager is setting the environment variables (like in the community GitHub repo you linked–this part: https://github.com/EndeavourOS-Community-Editions/sway/blob/main/sway-install.sh#L11-L12) instead of relying on the login shell to do it. This solution is obviously dependent on the display manager (i.e., it will not work if you start the session from a TTY).

If you use a wrapper script for launching Sway (as mentioned in post #9 of this topic), it is equally easy because it’s just one file–the same experience you are familiar with from Hyprland. Adding, removing, or changing variables is all done in the one single file.

In addition to being simple and easy to set up or maintain, a wrapper script preserves the option of having multiple login environments since everything is isolated in the one tidy file. There are not various configs strewn throughout the system setting Sway-specific environment variables. Only the wrapper script sets them, if Sway is being launched.

It is also a very portable solution. If you want to change login managers for example, just do it–the only thing you need to do is configure the display manager to launch sway-run (or whatever you name your wrapper script) instead of sway.

I guess all I am trying to say is setting environment variables on Sway does not need to be complicated. Using a wrapper script is simple, consistent, and has certain advantages compared to trying to shoehorn the system-level configuration methods into working.

1 Like

I agree, but that isn’t what the OP wanted, clearly.

1 Like

The use of 30-systemd-environment-d-generator is only if you care about systemd. Otherwise, the first part of the post would be enough.

Even the use of wrapper script requires some work, anyway. Moreover, it requires changing files outside the home directory, which I wanted to avoid. My solution looks simple to me: after tweaking profile files, as part of “dotfile” management, you set environment variables in place only. Everything is handled as “dotfiles” (I use “chezmoi” in that respect, but it works also with “stow”).

The mentioned link would do the trick, of course, about the sourcing profile in the desktop file (which has to be modified); will the desktop file resist possible updates to Sway?

If I had to use a wrapper script, then I’d rather launch it from the tty.

In any case, in my experiments, the https://github.com/EndeavourOS-Community-Editions/sway/tree/main/.config/environment.d is completely useless and ignored, as I said in other parts of this thread. This seems to be due to the “setting environment variables on Sway sounds complicated”.

In any case, I find it hard to doubt that in Hyprland it’s easier (just put everything in its config file) :slight_smile:

1 Like

This is the misunderstanding and confusing thing, which is a wrong assumption, to my experience.

When starting a session,

from TTY

  • You have already started the user session
  • This means you have already sourced the SHELL variables (you are in a shell already)
  • Hyprland command (or any other DE/WM) acknowledges the shell login vars (in .profile or other)

from DM

  • Init .desktop file runs Hyprland command
  • This means you are using a shell (implementing .desktop file execution) and sourcing the SHELL variables, before you execute the Exec key command line
  • Hyprland command (or any other DE/WM) acknowledges the shell login vars (in .profile or other)

This is correct. When starting from a TTY, you are indeed already in a shell environment where ~/.profile or other shell initialization files have been sourced. Thus, any environment variables set in those files are available to the session.

Most display managers (DMs) like GDM, SDDM, or LightDM do not necessarily source ~/.profile, ~/.bash_profile, or similar shell initialization files. Instead, they directly execute the session command specified in the .desktop file, which might not include these shell variables unless explicitly configured to do so.

This is not typically how display managers operate by default. Display managers generally start the session by running the command specified in the .desktop file (e.g., Exec=sway), without going through a login shell that sources files like ~/.profile or ~/.bash_profile.

Again, yes when just using a TTY but using a display manager complicates this. Display managers generally do not source shell initialization files. Often you can configure them to source this file or that, but there is not a typical behavior that is universal to display managers in this sense.

In practice, this is correct, that’s why I referenced .desktop file implementation, which depends on the implementor.
This is what messes up Linux. For this, it is the (ethical?) responsibility of the packagers, or the program developers to make this session init/start confident and providing always the same result, independent of factors like DM, SHELL, system init, etc.
They have to provide a script (or executable) for this specific task (session init).
That’s why we (the users) have to replace their incompetence to provide a trustworthy outcome.
This topic is an example of the very respectable efforts of end-users to fix the upstream deafness.

TLDR, an init script for the DM is a good solution, either from upstream, or custom users’ one. :man_shrugging:

I can see both sides of it. Another way of looking at it is they have left this configuration decision up to the user. Depending on the user’s preference and the other software decisions they make, there are any number of solutions that will get the job done.

This point we agree on, it seems. :wink:

1 Like

Yes. I create a bicycle but not assembled, because the user may want to use another layout (with only one wheel). What am I? :rofl:

1 Like

I will take one! This was a great hobby of mine in my younger days. Some college buddies and I set up a makeshift bicycle workshop in the basement where we would repair bicycles, but also build them from scratch for the fun of it. :biking_man:

I have even built quite a few wheels in my day! :grin:

1 Like