Environment Variables in Sway

Setting environment variables in Hyprland is easy: just put them in its config file. Setting environment variables in Sway is a bit harder, and there seems to be some confusion. The documentation is unclear about that, at least in my humble opinion.

This blog post documents my way of setting environment variables in Sway.

NOTE: This tutorial and its contents are based on Arch Linux; in other distros, configurations might have to be adapted.

Let’s install qt6ct for some experiments.

If we run it, we get the following problem:

Where can environment variables be specified when using Sway?

In my experiments, “~/.profile” is not loaded (either when logging in or using SDDM). Instead, “~/.bash_profile” and “~/.zshenv” should be used for BASH and ZSH, respectively.

So, in those files, source “~/.profile” explicitly

Let’s put the environment variable declaration and export into “~/.profile”

Exit Sway and get back in, and now qt6ct is happy:

If we want also to have our environment variables available to systemd, we can follow another strategy to specify environment variables in one place.

First of all, let’s create a file (or any, if you want to have several environment variables categorized in different files) that ends with “.conf” in the directory “~/.config/environment.d/”.

For example, I have “~/.config/environment.d/10-env.conf” (these files are read by systemd alphabetically); I move the environment variable definition in this file (so, I remove it from “~/.profile”):

Note that in this file, you only have to use the syntax “key=value” (to see the full syntax: https://www.freedesktop.org/software/systemd/man/latest/environment.d.html)

Each time you modify that directory, you have to run this command:

To verify that systemd read this file, run

And you should see the line:

If you restart Sway and run qt6ct, you will see that qt6ct complains again. The environment variable is only visible to the systemd. We have to export the variables read by systemd.

To avoid duplication, we can use the program “/usr/lib/systemd/user-environment-generators/30-systemd-environment-d-generator”, which does precisely that (of course, it handles all the environment variables in the “.conf” files in the environment.d directory). In “~/.profile” we now put this line:

Restart Sway and run qt6ct, and now everything went back to work!

You can also open a terminal from Sway and verify the environment variable is there!

I hope you find this blog post helpful 🙂

7 thoughts on “Environment Variables in Sway

  1. Borg Laugh

    This is dependent on your login manager (which may also be your display manager, and I’m not even sure what the difference is).
    If you check the envar presence using a terminal which launches your shell, of course shell-specific config file like .profile .zprofile .zshenv etc are loaded. But that’s specific to the shell in the terminal.
    However, If you launch a program by other means (say a launcher like dmenu or rofi) launcher, those variables will not inherit the environment of the shell.
    So what you need is for these env vars to be part of the environment for sway. How?
    You can’t do it via the sway config file (not by set which is irrelevent, and not by exec which is a subshell and has no effect).
    Sway needs to inherit these variables from the process that launches it. If you alunch sway from a scrip, that’s easy. if it’s launched by a login manager, you need to find out which files (if any) the login manager reads in order to import environment variables. Some, like GDM, read standard files like .profile. Others don’t, or define their own files for that.

    It’s a huge f* mess, and I’ve now spent hours chasing down idiocy.

    Reply
    1. Lorenzo Bettini Post author

      The solution I presented works when starting sway from the sddm display manager and everything works as expected as detailed in the blog post.

      Reply
      1. Borg Laugh

        On fedora, there are two alternative packages for the sway config files:
        sway-config-upstream.noarch
        and
        sway-config-fedora.noarch

        the latter has a sway session script that reads in /etc/sway/environment
        and
        ${XDG_CONFIG_HOME:-$HOME/.config}/sway/environment

        I’ve read all I could find about this on the webs and many of the solutions actually rely on the behavior of specific setups.

        For example .config/sway/environment above is not read by sway, or by your login-manager, but by a particular handwritten config provided by the distro, which you may or may not have installed.

        Similarly, .profile is read by GDM/SDDM, but not lightdm. But it still may work, if you launch sway from the shell, but not otherwise….

        and the same goes for xinitrc files,

        and variables in the systemd environment are propagated to sway only if you run sway as a systemd service, etc’, etc’…

        You end up trying 5 different solutions, and nothing works because they are all based on implicit assumptions that don’t apply to you.

        Every couple of years something breaks in my system so I’m forced to manually reach into the configuration cespool that is Desktop Linux, and invariably I end up feeling violated and gross for days in the aftermath.

        Reply
        1. Lorenzo Bettini Post author

          As I said, for my scenario, my solution still works like a charm.
          It all depends on how you run Sway, as you said.
          You have to decide how you want to start Sway, and act accordingly.

          Reply
          1. Borg Laugh

            Of course. Could you just add a note at the top that your solution is for Arch in particular? this may not be obvious to folks who land here via google.

            Thanks.

            Reply

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.