Some loose ends for sway on nixos which we should fix

Hey everyone,

I have been using sway window manager on nixos for nearly a year and a half now, and the experience has been pretty good. There are a few rough edges though, and I wanted to start a discussion about them, because 1. I want to fix them, but don’t have the skills and 2. we are very close to having pretty much everything sway related just working out of the box. First, let me just write down what I think is a sane default configuration for all things sway related:


{ config, pkgs, lib, ... }:

let


  # bash script to let dbus know about important env variables and propogate them to relevent services
  # run at the end of sway config
  # see https://github.com/emersion/xdg-desktop-portal-wlr/wiki/"It-doesn't-work"-Troubleshooting-Checklist
  dbus-sway-environment = pkgs.writeTextFile {
    name = "dbus-sway-environment";
    destination = "/bin/dbus-sway-environment";
    executable = true;

    text = ''
  dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP=sway
  systemctl --user stop pipewire pipewire-media-session xdg-desktop-portal xdg-desktop-portal-wlr
  systemctl --user start pipewire pipewire-media-session xdg-desktop-portal xdg-desktop-portal-wlr
      '';
};

in
{

environment.systemPackages = with pkgs; [
    alacritty
    dbus-sway-environment
    chromium
];

  services.dbus.enable = true;
  xdg.portal = {
    enable = true;
    wlr.enable = true;
    # gtk portal needed to make firefox happy
    extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
    gtkUsePortal = true;
  };

  programs.sway = {
    enable = true;
    wrapperFeatures.gtk = true;
    extraPackages = with pkgs; [
        swaylock
        swayidle
        grim         # screenshot functionality
        slurp        # screenshot functionality
        wl-clipboard
        # make sure the default gnome icons are avaliable
        # to gtk applications
        gnome3.adwaita-icon-theme
      ];
  };

  services.pipewire = {
    enable = true;
    alsa.enable = true;
    pulse.enable = true;
  };
}

I think the main thing which is working now that didn’t in the past is pipewire with xdg-desktop-portal-wlr which allows for screen sharing in webRTC apps like google meet (and to a lesser extent, zoom, but lets not get into that). Now the main issues as I seem them are as follows.

  • It is very difficult to get sway working well as a user space systemd service. I think the main issue here is to do with environment variables not being shared between user environments and service environments. For example, if you follow the instructions for the nix wiki to create a sway service, it gets run with a different DBUS_SESSION_BUS_ADDRESS, which breaks things like xdg-desktop-portal-wlr since they are running with the default user DBUS_SESSION_BUS_ADDRESS.
  • It is difficult to get GTK and sway working well together. This is a know issue on the sway side, and there are official sway docs on how to deal with it, but they don’t seem to work well on nixos, so it seems like something we need to fix in nixpkgs directly.
  • related to the above issues, the sway wiki is somewhat out of date. It does discuss these issues, but the proposed solutions don’t seem to work. I feel like they need to be solved directly in nixpkgs rather than at the configuration level.

I am probably going to start digging into the relevant parts of nixpkgs soon to try and figure out how the stuff works, but presumably there are a lot of people floating around who understand the infrastructure better than I do, and I would appreciate any thoughts or comments.

EDIT: I just found sway: Optimal NixOS integration · Issue #57602 · NixOS/nixpkgs · GitHub, which seems to be the issue tracking this kind of stuff.

EDIT 2: It seems that running sway as a systemd user service is not recommended: Systemd integration · swaywm/sway Wiki · GitHub and Include a systemd.service file · Issue #5160 · swaywm/sway · GitHub

5 Likes

OK, i have done a fair amount of digging and feel like I have arrived at a solid spot. I think the main thing we need to do is rewrite the nixos sway wiki page so that it is inline with what is currently being recommended on the official sway wiki. My goal here is to have the nixos wiki describe a sway configuration where everything just works. The central changes are as follows:

  • The sway developers do not recommend running sway as a systemd user service as explained in Systemd integration · swaywm/sway Wiki · GitHub and Include a systemd.service file · Issue #5160 · swaywm/sway · GitHub. We could probably set up such a service correctly in nixos, but I think that for the sake of simplicity, we should not suggest doing so on the nixos wiki with an explanation that it isn’t recommended by the sway developers.

  • For picking a gtk theme, the suggested way of doing this in the official sway wiki is using gsettings. Some strace digging suggests that the main place that gtk apps are searching for themes is in /run/current-system/sw/share/themes and you can install a theme there by just appending it to environment.systemPackages.

Here is a minimal configuration where everything works:

{ config, pkgs, lib, ... }:

let
  # bash script to let dbus know about important env variables and
  # propogate them to relevent services run at the end of sway config
  # see
  # https://github.com/emersion/xdg-desktop-portal-wlr/wiki/"It-doesn't-work"-Troubleshooting-Checklist
  dbus-sway-environment = pkgs.writeTextFile {
    name = "dbus-sway-environment";
    destination = "/bin/dbus-sway-environment";
    executable = true;

    text = ''
  dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP=sway
  systemctl --user stop pipewire pipewire-media-session xdg-desktop-portal xdg-desktop-portal-wlr
  systemctl --user start pipewire pipewire-media-session xdg-desktop-portal xdg-desktop-portal-wlr
      '';
  };

  # currently, there is some friction between sway and gtk:
  # https://github.com/swaywm/sway/wiki/GTK-3-settings-on-Wayland
  # the suggested way to set gtk settings is with gsettings
  # for gsettings to work, we need to tell it where the schemas are
  # using the XDG_DATA_DIR environment variable
  # run at the end of sway config
  configure-gtk = pkgs.writeTextFile {
      name = "configure-gtk";
      destination = "/bin/configure-gtk";
      executable = true;
      text = let
        schema = pkgs.gsettings-desktop-schemas;
        datadir = "${schema}/share/gsettings-schemas/${schema.name}";
      in ''
        export XDG_DATA_DIRS=${datadir}:$XDG_DATA_DIRS
        gnome_schema=org.gnome.desktop.interface
        gsettings set $gnome_schema gtk-theme 'Dracula'
        '';
  };


in
{
  environment.systemPackages = with pkgs; [
    alacritty           # gpu accelerated terminal
    sway
    dbus-sway-environment
    configure-gtk
    wayland
    chromium
    glib                      # gsettings
    dracula-theme             # gtk theme
    gnome3.adwaita-icon-theme # default gnome cursors
    swaylock
    swayidle
    grim                      # screenshot functionality
    slurp                     # screenshot functionality
    wl-clipboard
    bemenu
  ];



  services.pipewire = {
    enable = true;
    alsa.enable = true;
    pulse.enable = true;
  };


  # xdg-desktop-portal works by exposing a series of D-Bus interfaces
  # known as portals under a well-known name
  # (org.freedesktop.portal.Desktop) and object path
  # (/org/freedesktop/portal/desktop).
  # The portal interfaces include APIs for file access, opening URIs,
  # printing and others.
  services.dbus.enable = true;
  xdg.portal = {
    enable = true;
    wlr.enable = true;
    # gtk portal needed to make gtk apps happy
    extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
    gtkUsePortal = true;
  };

  # enable sway window manager
  programs.sway = {
    enable = true;
    wrapperFeatures.gtk = true;
  };

}

Appending

exec dbus-sway-environment
exec configure-gtk

to the end of your sway config gets xdg-desktop-portal-wlr and gtk themes working correctly. Any suggestions about how to proceed would be greatly appreciated. I don’t want to upset anyone by going in and rewriting the nixos sway wiki page without discussing with the community first.

8 Likes

Thanks a lot for your post! I don’t pretend to have any authority over the wiki, but as a new nixos+sway user having trouble getting things working, I found your post more useful than what’s on the wiki right now.

I just wanted to add that before finding this post, I found this issue which describes exactly an issue I’m having (and which you appear to be working around in your configure-gtk script). It was marked as fixed 2 years ago, but the fix doesn’t work for me…

@jneem: glad it was helpful! I think the main thing which needs to happen is we need to not suggest that people try and create a systemd user service for sway (since then it ends up in the wrong dbus session), and use gsettings to configure gtk. Both of these are described on the sway wiki. From the sounds of it, the gtk stuff is just a bandaid and may be fixed at some point, but i think that the sway devs don’t believe people should be trying to run sway as a user systemd service :man_shrugging:

I am a little apprehensive to just go in and butcher the existing nixos sway wiki page, since there is definitely some useful information on there, especially when you read it in conjunction with a close reading of the sway wiki. Here is my full nixos config incase you are interested: https://github.com/danielbarter/nixos-config/blob/36e173ac251a3380a026c0ccb90c3612a627b761/configuration.nix.

@danielbarter Thank you from me too. I’ve recently been playing around with i3wm and then Sway under Fedora whilst I’ve been playing with NixOS separately to see if I can get everything I need set up in it and I now want to get Sway running on NixOS. Your notes and full config have been incredibly helpful.

Thanks for posting your configuration, that’s very useful! Given that the wiki tracks changes and can be rolled back, my inclination would be just to go ahead and update it :man_shrugging:

What worries me more is that the gsettings issue was supposed to have been fixed, so I don’t understand why your configure-gtk script is needed (but at least on my system, it is). Also, my sway config file has “include /etc/sway/config.d/*” near the end, and my /etc/sway/config.d/nixos.conf contains

# Import the most important environment variables into the D-Bus and systemd
# user environments (e.g. required for screen sharing and Pinentry prompts):
exec dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP"

which seems to overlap with what dbus-sway-environment does…

Looking at that PR, it seems like it was about supplying dependencies like glib to GTK apps rather than about theming. My configure GTK script is just inline with what sway currently recommends on their wiki for setting themes. They essentially say that setting certain GTK attributes is broken on the sway side and you need to work around it using gsettings. I don’t think it makes sense to fix this in nixpkgs since i think sway wants to eventually allow gtk attributes to be set in the sway config.

/etc/sway/config.d/nixos.conf is definitely is definitely the same as what my dbus-sway-environment is doing, but I also restart some of the related services, since that is what they suggest doing here. I wasn’t aware of /etc/sway/config.d/nixos.conf, which is nice to know about!

OK, I have gutted the wiki and replaced it with something which should just allow people to get up and running quickly: Sway - NixOS Wiki

Feel free to add anything further which you think would be useful.

1 Like

I’m not sure you should have removed the systemd section. What was described there wasn’t how to run sway itself as a systemd service, but rather how to set up a target that gets started after sway, so that you can manage other graphical user services (like waybar) with systemd.

@mtogp: you are totally right. In older versions of the page, there was this:

  systemd.user.services.sway = {
    description = "Sway - Wayland window manager";
    documentation = [ "man:sway(5)" ];
    bindsTo = [ "graphical-session.target" ];
    wants = [ "graphical-session-pre.target" ];
    after = [ "graphical-session-pre.target" ];
    # We explicitly unset PATH here, as we want it to be set by
    # systemctl --user import-environment in startsway
    environment.PATH = lib.mkForce null;
    serviceConfig = {
      Type = "simple";
      ExecStart = ''
        ${pkgs.dbus}/bin/dbus-run-session ${pkgs.sway}/bin/sway --debug
      '';
      Restart = "on-failure";
      RestartSec = 1;
      TimeoutStopSec = 10;
    };
  };

which will run sway on a separate dbus session. If you do this, i am not sure it is possible to get anything which requires dbus integration working (e.g most of the gtk ecosystem and webRTC screen sharing).

I hadn’t realized that part had been stripped out. I don’t personally use waybar or kanshi, so I can’t comment on whether the services being defined there work correctly, but they look pretty reasonable to me. Can anyone who uses waybar or kanshi confirm that the services defined here work? Same question for anyone running sway idle as a systemd service instead of just a child process of sway

Instead of using a system service I tried to setup gdm + sway only and it does not seem to work. gdm does not start as it complains about not find the sway session description file. There is no information in the Sway wiki page about this usecase unfortunately.
Did you try it ? (I created a topic especially for my issue in the Learn section)

These instructions don’t seem to work for me, and although I am using home-manager, that shouldn’t affect it. I checked the xdpw FAQ and I can’t figure out why screensharing doesn’t work.
I can provide logs of xdg portal crashing, though I dont know how much it can help. Also I am using sway on hybrid graphics (intel+nvidia) if that matters too

I used these instructions and can now finally get full screen sharing in zoom in chromium working. My waybar works fine, although I never used systemd before; I exec straight from sway/config, so I’m not the target audience to test.

One odd point: If I have two screens (laptop plus external), it only shows the option of a single screen. It also no longer allows showing individual application windows. I have to go to chrome://flags and disable WebRTC PipeWire support to re-renable individual windows, which requires a restart of chromium. It’s not a dealbreaker, but certainly not a smooth workflow like we had in x11 land.

After fiddling around with sway on home-manager I managed to get screensharing working on obs… but only the flatpak version. Screenshoting with slurp works fine but chromium based browsers just crash after trying to screenshare. OBS from nixpkgs just shows a black screen.

@danyeet : as far as I am aware, sway does not support nvidia graphics officially. There even used to be a flag along the lines of -my-next-gpu-wont-be-nvidia which you needed to even launch sway when there was an nvidia device on the pci bus!!! This was very annoying on machines which use integrated graphics for rendering to a display and an nvidia GPU for gpu computing, or vfio passthrough or something like that.

Also, i don’t use home manager, so don’t have anything useful to say about how it interacts with sway.

I’m still struggling to get on-the-fly theme change with gsettings working in GTK3 apps, GTK4 apps works flawlessly.

Are you achieve to change them with your config?

I track two issues related:
https://github.com/NixOS/nixpkgs/issues/168485
https://github.com/nix-community/home-manager/issues/2793#issuecomment-1101231127

I’m a GNOME user, but was curious to try Sway. I followed the new instructions on the wiki and they mostly work, thanks! One thing I had to change was to comment out xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-gtk ]; since it clashed with something else (enabled indirectly by something in my config). In any case, the pre-existing setting did include xdg-desktop-portal-gtk so no problem.

The only annoying thing is that now when I log into GNOME I have to wait significantly longer (ca. 20-30 sec.) than without the sway config (ca. 2 sec.). I checked journalctl but the cause is not immediately obvious to me.

Sounds suspiciously like a portals problem - GNOME needs xdg-portals-gnome afaik.

Thanks for the tip. If I comment out xdg.portal.gtkUsePortal = true; the GNOME starts quickly.

It seems that GNOME and Sway do not coexist well. Setting xdg.portal.wlr.enable = true; breaks screen sharing in GNOME.

1 Like