Fedora is one of the few distributions where installing Sway gives you a working desktop on the first login. The sway-config-fedora package adds a Waybar panel, an idle lock, media and brightness keys, screenshot bindings, and a Rofi launcher. Everything is split into drop-in files you can override one at a time. The catch is that most Sway guides tell you to copy /etc/sway/config into your home directory and edit it, which works but freezes the core bindings and variables at whatever Fedora shipped that day.
This guide installs Sway on Fedora Workstation next to GNOME, logs in through GDM, and walks through what Fedora’s layered config actually loads. From there it shows how to override single pieces of it and how to build a custom Waybar config. It finishes with the errors that come up along the way. If you are starting from a fresh machine, the Fedora 45 install guide and the post-install checklist cover the base system first. Every command and screenshot below came from a Fedora 45 Workstation running Sway 1.12 and Waybar 0.15.0, with the Fedora 44 package set checked against the same repositories.
Pick how much of the Sway desktop to install
Fedora packages Sway three ways, and the right one depends on what is already on the machine. Two package groups exist in the repositories plus a dedicated spin ISO. The group sizes below are from a dnf5 install --assumeno dry run on a stock Fedora 45 Workstation:
| Option | What you get | Packages on Workstation | Use it when |
|---|---|---|---|
@swaywm + sway-config-fedora | Sway, swaybg, swayidle, swaylock, Waybar, foot, dunst, grim/slurp, Rofi, portals, Fedora’s config | 52 (25 MiB) | Adding Sway to a GNOME or KDE install |
@sway-desktop-environment | All of the above plus SDDM, Thunar, xfce4-panel pieces, Blueman, mpv, NetworkManager applets | 107 (138 MiB) | A minimal or Server install that has no display manager yet |
| Fedora Sway Spin ISO | The full environment, SDDM as the login screen | Fresh install | A dedicated Sway machine |
On a GNOME machine, skip the full environment. It pulls in SDDM alongside GDM, and a second display manager on a GNOME box is just something to disable later. The dry run shows it plainly:
sudo dnf5 install --assumeno @sway-desktop-environment | grep -E '^ (sddm|Thunar|xfce4-panel) '
SDDM, Thunar and xfce4-panel are all in the transaction:
Thunar x86_64 0:4.20.10-2.fc45 fedora 10.7 MiB
sddm x86_64 0:0.21.0-16.fc45 fedora 1.6 MiB
xfce4-panel x86_64 0:4.20.8-4.fc45 fedora 8.4 MiB
Install Sway on Fedora Workstation
One command. The swaywm group brings the compositor and its tools, and sway-config-fedora is the package that turns it into Fedora’s preconfigured desktop. The sway package only requires “a” config package, and sway-config-upstream (the plain upstream sample with swaybar) satisfies that too, so name Fedora’s explicitly:
sudo dnf5 install -y @swaywm sway-config-fedora
If GNOME Software had an update queued, dnf warns that it just invalidated it. It does not affect the Sway install:
Warning: Pending offline transaction has been invalidated.
To reschedule, run: dnf5daemon-server
Complete!
Confirm the versions that landed:
rpm -q sway wlroots waybar sway-config-fedora foot rofi
On Fedora 45 the compositor sits on wlroots 0.20:
sway-1.12-2.fc45.x86_64
wlroots-0.20.2-2.fc45.x86_64
waybar-0.15.0-6.fc45.x86_64
sway-config-fedora-0.4.3-4.fc45.noarch
foot-1.28.0-1.fc45.x86_64
rofi-2.0.0-3.fc45.x86_64
The package also drops a session file at /usr/share/wayland-sessions/sway.desktop. Its Exec line is start-sway, not sway. That wrapper matters later because it sets environment variables before the compositor starts.
Log in to Sway from GDM
Log out of GNOME, click your user, then open the gear icon in the bottom right corner before typing the password. This catches people out: on our Workstation the Session Type menu still listed only GNOME and GNOME Classic after the install. GDM reads the session list when the greeter starts, so a greeter that was already running never sees sway.desktop. Restart it from a terminal (this ends any graphical session on the machine, so save your work) or reboot:
sudo systemctl restart gdm
After the restart, Sway appears as a third choice:

GDM remembers the choice per user, so later logins go straight back into Sway until you pick GNOME again. Sway comes up on Fedora’s wallpaper with Waybar across the top, and Super+Return opens a foot terminal before you have written any config. This is the packaged bar with two terminals open, one listing the drop-ins:

The default bar shows workspaces on the left and the focused window title in the middle. On the right are the idle inhibitor, volume, network, power profile, CPU, memory, keyboard layout and clock. Temperature, backlight and battery modules switch themselves off when the hardware has no sensor for them, which is why a VM or desktop shows fewer modules than a laptop. The network address is blacked out in this capture.
How Fedora’s Sway config is layered
/etc/sway/config holds only the core i3-style bindings. Its last line hands everything else to a helper script:
include '$(/usr/libexec/sway/layered-include "/usr/share/sway/config.d/*.conf" "/etc/sway/config.d/*.conf" "${XDG_CONFIG_HOME:-$HOME/.config}/sway/config.d/*.conf")'
layered-include collects files from three directories, keyed by file name, and later directories win. A file in ~/.config/sway/config.d/ named 60-bindings-screenshot.conf replaces the packaged one of the same name instead of adding to it. The result is loaded in sorted file-name order. These are the drop-ins Fedora ships in /usr/share/sway/config.d/:
| File | What it does |
|---|---|
50-rules-browser.conf | Marks Firefox, Chromium and Brave windows and inhibits idle while they are fullscreen |
50-rules-pavucontrol.conf, 50-rules-policykit-agent.conf | Floats the volume mixer and the polkit password prompt |
60-bindings-volume.conf, 60-bindings-media.conf, 60-bindings-brightness.conf | XF86 volume, media and brightness keys (volume and play also work on the lock screen) |
60-bindings-screenshot.conf | Print, Alt+Print and Ctrl+Print through grimshot |
65-mode-passthrough.conf | Super+Pause passes every key to the focused window (handy for nested VMs) |
90-bar.conf | Starts Waybar as the bar |
90-swayidle.conf | Locks after 300 seconds and blanks the screen 60 seconds later |
95-autostart-policykit-agent.conf, 95-xdg-desktop-autostart.conf, 95-xdg-user-dirs.conf | Polkit agent, XDG autostart entries, and the XDG user directories |
The bindings every new Sway user needs first come straight from /etc/sway/config. Super is the modifier (Mod4):
| Keys | Action |
|---|---|
Super+Return | Open a foot terminal |
Super+D | Rofi launcher (apps and commands in one list) |
Super+Shift+Q | Close the focused window |
Super+H/J/K/L or arrows | Move focus; add Shift to move the window |
Super+1 to Super+0 | Switch workspace; add Shift to send the window there |
Super+B / Super+V | Split the next window horizontally / vertically |
Super+S / Super+W / Super+E | Stacking / tabbed / toggle split layout |
Super+F | Fullscreen |
Super+Shift+Space | Toggle floating |
Super+R | Resize mode (Escape to leave) |
Super+Shift+C | Reload the config |
Super+Shift+E | Exit Sway (asks first) |
Override Fedora’s defaults with your own drop-ins
Leave /etc/sway/config alone and put your changes in ~/.config/sway/config.d/. Package updates to sway-config-fedora then keep flowing, and your file only carries what you changed. Create the directory:
mkdir -p ~/.config/sway/config.d
Open a local drop-in. The 10- prefix sorts it ahead of Fedora’s 90-swayidle.conf, and that ordering is what lets the timeout variables take effect:
vim ~/.config/sway/config.d/10-local.conf
This is the exact file used on the test machine. It raises the lock timeout, maps Caps Lock to Escape, enables tap-to-click, sets the resolution and wallpaper, and adds thin borders with small gaps:
# Lock after 10 minutes, blank the screen one minute later
set $lock_timeout 600
set $screen_timeout 60
input type:keyboard {
xkb_layout us
xkb_options caps:escape
}
input type:touchpad {
tap enabled
natural_scroll enabled
}
output Virtual-1 mode 1920x1080 bg /usr/share/backgrounds/f45/default/f45-01-night.jxl fill
default_border pixel 2
gaps inner 6
font pango:Noto Sans 10
Virtual-1 is the output name of the test VM. List your own outputs and their modes with swaymsg -t get_outputs and use that name, or use output * to match every screen. Fedora 45 ships its wallpapers as JPEG XL, and swaybg loaded the .jxl file directly.
Reload with Super+Shift+C or from a terminal inside the session:
swaymsg reload
The input, output and border changes apply immediately. Two things did not. The gaps inner value was not applied to the workspace that was already open, and swayidle kept running with the old timeout, because exec lines run once at login and a reload does not restart them:
ps -o args= -C swayidle
After the reload the process still had the packaged 300 second value:
swayidle -w timeout 300 swaylock -f timeout 360 swaymsg "output * power off" resume swaymsg "output * power on" timeout 60 pgrep -xu "$USER" swaylock >/dev/null && swaymsg "output * power off" resume pgrep -xu "$USER" swaylock >/dev/null && swaymsg "output * power on" before-sleep swaylock -f lock swaylock -f unlock pkill -xu "$USER" -SIGUSR1 swaylock
Log out with Super+Shift+E and back in. The same check on the new session shows timeout 600 swaylock -f timeout 660, and the gaps apply to workspace 1. To see exactly which files Sway loaded and in what order, read the include list the helper generated under the runtime directory:
cat "$(ls -t "$XDG_RUNTIME_DIR"/sway/layered-include-*.conf | head -1)"
Your drop-in sorts first, followed by the systemd pieces from /etc and Fedora’s packaged files:
include '/home/sysadmin/.config/sway/config.d/10-local.conf'
include '/etc/sway/config.d/10-systemd-cgroups.conf'
include '/etc/sway/config.d/10-systemd-session.conf'
include '/usr/share/sway/config.d/50-rules-browser.conf'
include '/usr/share/sway/config.d/50-rules-pavucontrol.conf'
include '/usr/share/sway/config.d/50-rules-policykit-agent.conf'
include '/usr/share/sway/config.d/60-bindings-brightness.conf'
include '/usr/share/sway/config.d/60-bindings-media.conf'
include '/usr/share/sway/config.d/60-bindings-screenshot.conf'
include '/usr/share/sway/config.d/60-bindings-volume.conf'
include '/usr/share/sway/config.d/65-mode-passthrough.conf'
include '/usr/share/sway/config.d/90-bar.conf'
include '/usr/share/sway/config.d/90-swayidle.conf'
include '/usr/share/sway/config.d/95-autostart-policykit-agent.conf'
include '/usr/share/sway/config.d/95-xdg-desktop-autostart.conf'
include '/usr/share/sway/config.d/95-xdg-user-dirs.conf'
Replace one packaged drop-in
To change a packaged file rather than add to it, copy it under the same name and edit the copy. This swaps the Print key from a full-screen capture to an area selection that is saved and copied to the clipboard:
cp /usr/share/sway/config.d/60-bindings-screenshot.conf ~/.config/sway/config.d/
sed -i 's/Print exec grimshot save output/Print exec grimshot savecopy area/' ~/.config/sway/config.d/60-bindings-screenshot.conf
swaymsg reload
The regenerated include list now points at /home/sysadmin/.config/sway/config.d/60-bindings-screenshot.conf, and the /usr/share copy is no longer loaded. With the default bindings, grimshot writes to the XDG Pictures directory, so screenshots land in ~/Pictures with a timestamped file name.
Configure Waybar on Fedora
Waybar reads ~/.config/waybar/config.jsonc and style.css when they exist and falls back to /etc/xdg/waybar/. The packaged config carries every example module upstream ships (MPD, a Spotify media script, a power menu that expects files you do not have), so a short config of your own is easier to maintain than an edited copy. Create the directory and the config:
mkdir -p ~/.config/waybar
vim ~/.config/waybar/config.jsonc
This config moves the clock to the centre, keeps the network address in the tooltip instead of on the bar, and adds a disk module. Plain text labels replace the Font Awesome glyphs, which rarely survive a copy from a web page:
{
"position": "top",
"height": 32,
"spacing": 6,
"reload_style_on_change": true,
"modules-left": ["sway/workspaces", "sway/mode", "sway/scratchpad"],
"modules-center": ["clock"],
"modules-right": ["idle_inhibitor", "pulseaudio", "network", "cpu", "memory", "disk", "sway/language", "tray"],
"sway/workspaces": {
"disable-scroll": true,
"all-outputs": true
},
"clock": {
"format": "{:%a %d %b %H:%M}",
"tooltip-format": "<tt><small>{calendar}</small></tt>"
},
"idle_inhibitor": {
"format": "{icon}",
"format-icons": { "activated": "AWAKE", "deactivated": "IDLE" }
},
"pulseaudio": {
"format": "VOL {volume}%",
"format-muted": "VOL muted",
"on-click": "pavucontrol"
},
"network": {
"format-ethernet": "NET {ifname}",
"format-wifi": "WIFI {essid} {signalStrength}%",
"format-disconnected": "NET offline",
"tooltip-format": "{ifname}: {ipaddr}/{cidr} via {gwaddr}"
},
"cpu": { "format": "CPU {usage}%", "interval": 5 },
"memory": { "format": "MEM {used:0.1f}G", "interval": 10 },
"disk": { "format": "DISK {percentage_used}%", "path": "/" },
"tray": { "spacing": 8 }
}
Then the stylesheet:
vim ~/.config/waybar/style.css
A dark bar with the focused workspace highlighted and each module drawn as a rounded pill:
* {
font-family: 'Noto Sans', sans-serif;
font-size: 13px;
}
window#waybar {
background-color: rgba(30, 30, 46, 0.92);
color: #cdd6f4;
}
#workspaces button {
padding: 0 8px;
color: #a6adc8;
border-radius: 0;
}
#workspaces button.focused {
color: #1e1e2e;
background-color: #89b4fa;
}
#clock, #pulseaudio, #network, #cpu, #memory, #disk, #language, #idle_inhibitor, #tray {
padding: 0 10px;
margin: 4px 0;
border-radius: 6px;
background-color: #313244;
}
#network.disconnected {
color: #f38ba8;
}
Waybar reloads both files on SIGUSR2, so there is no need to reload Sway:
pkill -SIGUSR2 -x waybar
journalctl -b --no-pager | grep waybar | tail -4
The journal confirms Waybar switched from /etc/xdg/waybar to the files in your home directory:
Sep 28 21:15:21 fedora-ws01 waybar[4733]: [2026-09-28 21:15:21.402] [info] Reloading...
Sep 28 21:15:21 fedora-ws01 waybar[4733]: [2026-09-28 21:15:21.408] [info] Using configuration file /home/sysadmin/.config/waybar/config.jsonc
Sep 28 21:15:21 fedora-ws01 waybar[4733]: [2026-09-28 21:15:21.408] [info] Using CSS file /home/sysadmin/.config/waybar/style.css
Sep 28 21:15:21 fedora-ws01 waybar[4733]: [2026-09-28 21:15:21.537] [info] Bar configured (width: 1920, height: 32) for output: Virtual-1
With the drop-in from the previous section active after a fresh login, three terminals tile with 6 pixel gaps under the new bar (fastfetch on the left, btop and the drop-in file stacked on the right):

Launch apps and switch layouts
Super+D opens Rofi in combi mode, which merges desktop applications (drun) and every binary on your PATH (run) into one filtered list. Typing a few letters is enough:

Layouts apply to the container holding the focused window. Focus the right column and press Super+W, and its two terminals collapse into tabs while the left window keeps its split:

Super+E puts it back to a split. Screen sharing requests from browsers go to xdg-desktop-portal-wlr: Fedora’s /usr/share/xdg-desktop-portal/sway-portals.conf assigns it the ScreenCast and Screenshot interfaces, sends Secret to gnome-keyring, disables Inhibit, and leaves the rest to the GTK portal. Both portal services were running on the test session without any setup.
Sway on Fedora 45 vs Fedora 44
The install commands and group names are identical on both releases, and sway-config-fedora is the same 0.4.3 upstream release. The versions below are the newest builds each release’s repositories offered at the time of testing:
| Package | Fedora 45 | Fedora 44 |
|---|---|---|
| sway | 1.12 | 1.11 |
| sway-config-fedora | 0.4.3-4 | 0.4.3-3 |
| waybar | 0.15.0-6 | 0.15.0-2 |
| foot | 1.28.0 | 1.27.0 |
| rofi | 2.0.0-3 | 2.0.0-2 |
| swaylock | 1.8.6 | 1.8.6 |
| xdg-desktop-portal-wlr | 0.8.4 | 0.8.4 |
Both releases ship the same sway-config-fedora 0.4.3 drop-ins, so the config layout in this guide is identical; the Fedora 44 side was checked against its repositories, not run in a session. One packaging difference: on Fedora 44 the swaywm-extended group lists SDDM as mandatory, while Fedora 45 makes it a default package. If you plan to move a Fedora 44 Sway machine forward, the Fedora 44 to 45 upgrade guide covers the system upgrade itself.
Sway errors on Fedora and their fixes
Each of these came up while building the setup above.
“There are errors in your config file”
A bad line in any drop-in makes Sway draw a red swaynag bar across the top of the screen after a reload. A single typo (gap instead of gaps) was enough. Click Toggle details to see the file and line:

Sway skips only the broken line and loads the rest, so the session keeps working. Fix the file and reload. To check a config before reloading, sway -C validates it, but over SSH or from a TTY it fails with “No backend was able to open a seat” before reading anything. Forcing the headless backend gets around that:
WLR_BACKENDS=headless sway -C 2>&1 | grep -v 'render node'
The broken drop-in is reported with its path:
00:00:00.059 [ERROR] [sway/config.c:814] Error on line 1 'gap inner 10': Unknown/invalid command 'gap' (/home/sysadmin/.config/sway/config.d/20-typo.conf)
00:00:00.059 [ERROR] [sway/config.c:440] Error(s) loading config!
Do not trust the exit code in a script. Sway 1.12 returned 0 from sway -C with that error present, so grep the output for Error instead.
Sway is missing from the GDM session list
Covered above: the greeter was started before the package installed the session file. sudo systemctl restart gdm or a reboot fixes it. If Sway is still missing, check that /usr/share/wayland-sessions/sway.desktop exists. It ships in the config package (sway-config-fedora or sway-config-upstream), not in sway itself.
Sway in a VM: “Failed to find any DRM render node”
Virtual GPUs without 3D acceleration (QXL, virtio without virgl) have no render node, and wlroots’ default GLES2 renderer cannot start without one. Fedora’s start-sway wrapper already handles KVM guests. It detects the hypervisor and exports a software renderer before launching Sway, which the journal records on every login:
journalctl -b --no-pager -t sway | grep 'environment variables'
On the QXL test VM the wrapper chose pixman and the legacy DRM interface:
Sep 28 21:13:11 fedora-ws01 sway[4000]: environment variables for wlroots: WLR_RENDERER=pixman WLR_DRM_NO_ATOMIC=1
This is also why logging in through GDM or SDDM beats running sway directly from a TTY: running sway by hand skips the wrapper and its VM detection. From a TTY, start start-sway instead. On other hypervisors the wrapper only sets WLR_NO_HARDWARE_CURSORS=1. If you run a different VM platform, add your own variables to ~/.config/sway/environment, which start-sway sources at every login.
NVIDIA: “Proprietary Nvidia drivers are in use”
Older Sway releases refused to start on the proprietary NVIDIA driver. Sway 1.12 starts, logs !!! Proprietary Nvidia drivers are in use !!!, and raises a red swaynag error bar that reads “Proprietary GPU drivers are not supported by sway. Do not report issues.” These messages are taken from the Fedora 45 Sway 1.12 binary; we did not run it on NVIDIA hardware. The bar goes away when Sway is launched with --unsupported-gpu. Fedora’s /etc/sway/environment carries that flag commented out. Enable it for your user only by putting this line in ~/.config/sway/environment:
SWAY_EXTRA_ARGS="$SWAY_EXTRA_ARGS --unsupported-gpu"
Setting SWAY_UNSUPPORTED_GPU=true in the same file does the same job. The nouveau driver and AMD and Intel GPUs need neither. The same check also fires for the proprietary DisplayLink driver.
Waybar modules show blank icons
Waybar’s icons are Font Awesome private-use characters. fontawesome-7-free-fonts arrives as a weak dependency of waybar, so the packaged config renders fine, but glyphs copied from a web page or chat usually arrive as empty strings, and the module shows its value with a blank gap. Either paste the glyph from Waybar’s own example config in /etc/xdg/waybar/config.jsonc, or use text labels as in the config above. Temperature, backlight and battery modules that vanish entirely are a different case: the journal logs “Disabling module” (or “No batteries.”) because the machine has no matching sensor.
For other desktops on the same base, the GNOME Tweaks and extensions guide covers the GNOME side of this machine, and LXQt on Fedora is the lighter stacking alternative if a tiling compositor is not for you.