Polybar replaces the bar of an X11 tiling window manager with one you build from modules: workspaces, the focused window title, CPU, memory, disk, volume, network, a clock and a tray. Fedora packages it, so the old routine of cloning the source and running a build script is gone. What has changed on Fedora is the desktop underneath. Workstation’s GNOME session is Wayland only, and Polybar draws through X11. This guide pairs it with i3 instead, writes a config that survives both current releases, and starts one bar per monitor from i3. The steps were run on Fedora 45 and Fedora 44 in October 2026 with Polybar 3.7.2 and i3 4.25.1.
Check that you are on an X11 session
Polybar needs an X server to draw on. Since Fedora 43, Workstation ships GNOME as Wayland only, with the X11 session packages removed. So the stock Workstation desktop is the wrong host. Use one of these:
- The Fedora i3 Spin, which already runs i3 on X11.
- A minimal or Server install of Fedora 45 or 44 with the
i3package group added, as below. That is what we tested. On Workstation, GDM stays the active login manager after the group install. - Another X11 window manager such as bspwm or Openbox. The Polybar part of this guide still applies; only the i3 wiring changes.
On Sway or another Wayland compositor, use Waybar instead. Our Sway and Waybar setup on Fedora covers that path. Once Polybar is installed, you can see the dependency for yourself: started without an X display, it stops at once:
env -u DISPLAY polybar main
The error names the missing display:
polybar|error: Uncaught exception, shutting down: X connection error... (what: Can't parse display string)
Install i3 and Polybar
Skip this group install on the i3 Spin. Elsewhere, add i3 with the Xorg server, the LightDM login screen, i3status, dmenu, the Xfce terminal and feh:
sudo dnf install @i3
sudo systemctl set-default graphical.target
On a minimal base this is the big step: 478 packages and 467 MiB of downloads on Fedora 45, 486 packages on Fedora 44, about 1 GiB installed on both. Reboot, choose the i3 session at the LightDM login screen, and log in. i3 starts with its own i3bar at the bottom.
Polybar comes from the main Fedora repository:
sudo dnf install polybar
It is a small package with two extra libraries:
Updating and loading repositories:
Repositories loaded.
Package Arch Version Repository Size
Installing:
polybar x86_64 0:3.7.2-10.fc45 fedora 2.8 MiB
Installing dependencies:
jsoncpp x86_64 0:1.9.6-3.fc44 fedora 285.6 KiB
libmpdclient x86_64 0:2.26-2.fc45 fedora 193.4 KiB
Transaction Summary:
Installing: 3 packages
Total size of inbound packages is 1 MiB. Need to download 1 MiB.
After this operation, 3 MiB extra will be used (install 3 MiB, remove 0 B).
[1/3] jsoncpp-0:1.9.6-3.fc44.x86_64 100% | 491.2 KiB/s | 110.0 KiB | 00m00s
[2/3] libmpdclient-0:2.26-2.fc45.x86_64 100% | 297.5 KiB/s | 72.0 KiB | 00m00s
[3/3] polybar-0:3.7.2-10.fc45.x86_64 100% | 2.3 MiB/s | 927.7 KiB | 00m00s
--------------------------------------------------------------------------------
[3/3] Total 100% | 559.6 KiB/s | 1.1 MiB | 00m02s
Running transaction
[1/5] Verify package files 100% | 600.0 B/s | 3.0 B | 00m00s
[2/5] Prepare transaction 100% | 33.0 B/s | 3.0 B | 00m00s
[3/5] Installing libmpdclient-0:2.26-2. 100% | 31.8 MiB/s | 195.2 KiB | 00m00s
[4/5] Installing jsoncpp-0:1.9.6-3.fc44 100% | 70.1 MiB/s | 287.1 KiB | 00m00s
[5/5] Installing polybar-0:3.7.2-10.fc4 100% | 15.9 MiB/s | 2.8 MiB | 00m00s
Complete!
Check the build and the features compiled in:
polybar --version
Fedora 45 and Fedora 44 ship the same release with i3, PulseAudio and network support enabled:
polybar 3.7.2
Features: +alsa +curl +i3 +mpd +network(libnl) +pulseaudio +xkeyboard
The package installs two binaries, polybar and polybar-msg, plus a sample config at /etc/polybar/config.ini. That sample is identical to the upstream example config.
Install fonts that work on both releases
The bar needs a text font and an icon font. JetBrains Mono and Font Awesome are both packaged:
sudo dnf install fontawesome-fonts-all jetbrains-mono-fonts-all
This catches people out: the two releases ship different Font Awesome generations, and the family name carries the major version. Fedora 45 has Font Awesome 7. Fedora 44 has Font Awesome 6. A config that names one of them breaks on the other. Ask fontconfig what a Font Awesome 6 name resolves to on Fedora 45:
fc-match 'Font Awesome 6 Free:style=Solid'
It silently falls back to a text font, so every icon on the bar turns into an empty box:
NotoSans[wght].ttf: "Noto Sans" "Regular"
The fix is a fontconfig family list. Name both generations, newest first:
fc-match 'Font Awesome 7 Free,Font Awesome 6 Free:style=Solid'
Fedora 45 picks version 7:
Font Awesome 7 Free-Solid-900.otf: "Font Awesome 7 Free" "Solid"
Fedora 44 picks version 6 from the same string:
Font Awesome 6 Free-Solid-900.otf: "Font Awesome 6 Free" "Solid"
The config below uses that list, so one file works on both releases and keeps working after an upgrade.
Run the sample config once
Polybar reads ~/.config/polybar/config.ini and falls back to /etc/polybar/config.ini when that file does not exist. Before editing anything, list the outputs Polybar can see:
polybar --list-monitors
Our lab VM has one display:
Virtual-1: 1280x800+0+0 (primary)
The sample config defines one bar, called example. Start it for a few seconds to read the log:
timeout 6 polybar example
We ran this one over SSH with only DISPLAY set, which explains the first error. The rest are what a fresh install shows:
polybar|notice: Parsing config file: /etc/polybar/config.ini
polybar|notice: Listening for IPC messages (PID: 1333)
polybar|notice: Loading module 'xworkspaces' of type 'internal/xworkspaces'
polybar|notice: Loading module 'xwindow' of type 'internal/xwindow'
polybar|notice: Loading module 'filesystem' of type 'internal/fs'
polybar|notice: Loading module 'pulseaudio' of type 'internal/pulseaudio'
polybar|error: Disabling module "pulseaudio" (reason: Could not connect pulseaudio context.)
polybar|notice: Loading module 'xkeyboard' of type 'internal/xkeyboard'
polybar|notice: Loading module 'memory' of type 'internal/memory'
polybar|notice: Loading module 'cpu' of type 'internal/cpu'
polybar|notice: Loading module 'wlan' of type 'internal/network'
polybar|error: Disabling module "wlan" (reason: No interface found for type 'wireless')
polybar|notice: Loading module 'eth' of type 'internal/network'
polybar|notice: module/eth: Discovered wired interface eth0
polybar|notice: Loading module 'date' of type 'internal/date'
polybar|notice: Loaded 8 modules
polybar|notice: Loaded font "monospace" (name=DejaVu Sans Mono, offset=2, file=/usr/share/fonts/dejavu-sans-mono-fonts/DejaVuSansMono.ttf)
polybar|warn: background_manager: Failed to get root pixmap, default to black (is there a wallpaper?)
polybar|warn: background_manager: Failed to get root pixmap, default to black (is there a wallpaper?)
polybar|warn: background_manager: Failed to get root pixmap, default to black (is there a wallpaper?)
polybar|warn: background_manager: Failed to get root pixmap, default to black (is there a wallpaper?)
polybar|notice: Received signal(15): Terminated
polybar|notice: Termination signal received, shutting down...
Each of those lines is covered in the error section at the end. None of them stops the bar.
Build your own config from the sample
Copy the sample into your home directory. From here on, Polybar ignores the file in /etc:
mkdir -p ~/.config/polybar && cp /etc/polybar/config.ini ~/.config/polybar/
Rename the bar to main, and let the launch script choose the monitor through an environment variable. An empty MONITOR means the primary output:
sed -i 's|^\[bar/example\]|[bar/main]|' ~/.config/polybar/config.ini
sed -i '/^\[bar\/main\]/a monitor = ${env:MONITOR:}' ~/.config/polybar/config.ini
Replace the single monospace font with JetBrains Mono for text and the Font Awesome list for icons. The ;2 suffix moves the glyphs down two pixels so they sit centred in the bar:
sed -i 's|^font-0 = .*|font-0 = "JetBrains Mono:size=10;2"\nfont-1 = "Font Awesome 7 Free,Font Awesome 6 Free:style=Solid:size=10;2"|' ~/.config/polybar/config.ini
Pick the right-hand modules. This drops the keyboard layout indicator and adds the system tray, which the sample defines but does not show:
sed -i 's|^modules-right = .*|modules-right = filesystem pulseaudio memory cpu wlan eth date systray|' ~/.config/polybar/config.ini
Swap the VOL, RAM and CPU text labels for icons. Font Awesome glyphs live in the Unicode private use area, and they tend to vanish when copied from a web page. The command writes them as UTF-8 byte escapes instead, which GNU sed turns into the real characters:
sed -i 's|"VOL "|"\xef\x80\xa8 "|; s|"RAM "|"\xef\x94\xb8 "|; s|"CPU "|"\xef\x8b\x9b "|' ~/.config/polybar/config.ini
The three escapes are the volume, memory and microchip icons. Finally, the wired network module prints your local IP address by default. Show traffic instead, which is more useful at a glance and keeps the address out of screenshots on a wired machine:
sed -i '/^\[module\/eth\]/,/^\[/ s|%local_ip%|%downspeed:8% %upspeed:8%|' ~/.config/polybar/config.ini
Review the bar section after the edits:
grep -nE '^\[bar/main\]|^monitor|^font-|^modules-' ~/.config/polybar/config.ini
The line numbers match the sample, with the two inserted lines:
28:[bar/main]
29:monitor = ${env:MONITOR:}
52:font-0 = "JetBrains Mono:size=10;2"
53:font-1 = "Font Awesome 7 Free,Font Awesome 6 Free:style=Solid:size=10;2"
55:modules-left = xworkspaces xwindow
56:modules-right = filesystem pulseaudio memory cpu wlan eth date systray
Every other module and colour comes from the sample. The Polybar wiki documents each module type and its settings when you want to go further.
Write a launch script
i3 should start the bar through a script, so a reload never stacks a second bar on top of the first. Create it:
nano ~/.config/polybar/launch.sh
Add this content:
#!/usr/bin/env bash
# Stop running bars, then start one bar per connected monitor
polybar-msg cmd quit >/dev/null 2>&1
while pgrep -u "$UID" -x polybar >/dev/null; do sleep 0.2; done
for m in $(polybar --list-monitors | cut -d: -f1); do
MONITOR=$m polybar --reload main 2>&1 | tee -a "${XDG_RUNTIME_DIR:-/tmp}/polybar-$m.log" & disown
done
It asks any running bar to quit over IPC, waits for it to exit, then starts one main bar per monitor reported by --list-monitors. --reload restarts the bar whenever you save config.ini. Each monitor gets its own log under /run/user/. Make it executable:
chmod +x ~/.config/polybar/launch.sh
Start Polybar from i3
i3 reads ~/.config/i3/config. On the first login, i3-config-wizard offers to write that file. If you dismissed it, copy the system config there first:
mkdir -p ~/.config/i3 && cp /etc/i3/config ~/.config/i3/
Comment out the whole bar { } block so i3bar stops starting, then append the launcher:
sed -i '/^bar {/,/^}/ s/^/# /' ~/.config/i3/config
echo 'exec_always --no-startup-id $HOME/.config/polybar/launch.sh' >> ~/.config/i3/config
exec_always runs on every i3 restart, not just at login, which is what lets a restart pick up bar changes. The sample config turns on pseudo-transparency, and without a wallpaper Polybar logs “Failed to get root pixmap” four times on every start. feh came in with the i3 group and reads Fedora’s JPEG XL backgrounds. Set one once, which also writes ~/.fehbg:
feh --bg-fill /usr/share/backgrounds/default.jxl
Then restore the wallpaper on every start, by inserting that line above the Polybar launcher. i3 starts the two commands in order but does not wait for the first, so at login the bar can occasionally win the race and log the warning once; polybar-msg cmd restart clears it:
sed -i '/polybar\/launch.sh/i exec_always --no-startup-id $HOME/.fehbg' ~/.config/i3/config
tail -2 ~/.config/i3/config
The two lines end the file in this order:
exec_always --no-startup-id $HOME/.fehbg
exec_always --no-startup-id $HOME/.config/polybar/launch.sh
Restart i3 in place. Open windows stay where they are:
i3-msg restart
The bar appears at the top of the screen. Read its log:
cat "$XDG_RUNTIME_DIR"/polybar-*.log
The script appends with tee -a, so the file keeps every earlier start. This is a fresh log from a single start: every module loads, both fonts resolve, and no pixmap warning appears. On Fedora 45 the icon font resolves to Font Awesome 7:
polybar|notice: Parsing config file: /home/josphat/.config/polybar/config.ini
polybar|notice: Listening for IPC messages (PID: 6302)
polybar|notice: Loading module 'xworkspaces' of type 'internal/xworkspaces'
polybar|notice: Loading module 'xwindow' of type 'internal/xwindow'
polybar|notice: Loading module 'filesystem' of type 'internal/fs'
polybar|notice: Loading module 'pulseaudio' of type 'internal/pulseaudio'
polybar|notice: pulseaudio: using default sink auto_null
polybar|notice: Loading module 'memory' of type 'internal/memory'
polybar|notice: Loading module 'cpu' of type 'internal/cpu'
polybar|notice: Loading module 'wlan' of type 'internal/network'
polybar|error: Disabling module "wlan" (reason: No interface found for type 'wireless')
polybar|notice: Loading module 'eth' of type 'internal/network'
polybar|notice: module/eth: Discovered wired interface eth0
polybar|notice: Loading module 'date' of type 'internal/date'
polybar|notice: Loading module 'systray' of type 'internal/tray'
polybar|notice: Loaded 9 modules
polybar|notice: Loaded font "JetBrains Mono:size=10" (name=JetBrains Mono, offset=2, file=/usr/share/fonts/jetbrains-mono-fonts/JetBrainsMono-Regular.otf)
polybar|notice: Loaded font "Font Awesome 7 Free,Font Awesome 6 Free:style=Solid:size=10" (name=Font Awesome 7 Free, offset=2, file=/usr/share/fonts/fontawesome-7-free-fonts/Font Awesome 7 Free-Solid-900.otf)
The only error left is the wireless module, because the VM has no Wi-Fi card. On a laptop it shows the network name and, unlike the wired module edited above, the local IP address too. This is Fedora 45 with the default wallpaper:

Up close, the icons come from Font Awesome and the text from JetBrains Mono. The underlined workspace is the focused one, and the tray holds the NetworkManager and PulseAudio applets that the i3 group autostarts:

The same config on Fedora 44, with two terminals open on workspace 2 and the window title shown on the left:

The terminal on the right runs fish with the bobthefish theme. Our guide to fish and Oh My Fish on Fedora sets that up.
Control the bar with polybar-msg
The sample config sets enable-ipc = true, so a running bar takes commands. Hide and show it:
polybar-msg cmd toggle
Each call reports the process it reached:
Successfully wrote command 'toggle' to PID 4399
Modules accept actions too. This flips the clock between the short and long date formats, the same as clicking it:
polybar-msg action "#date.toggle"
Bind the toggle to a key for full-screen work. The Fedora i3 config in /etc/i3/config uses Alt as the modifier, and Alt+b is free. If the wizard wrote your config and you chose the Win key, use $mod+b instead:
echo 'bindsym Mod1+b exec --no-startup-id polybar-msg cmd toggle' >> ~/.config/i3/config
i3-msg reload
Press Alt+b once to hide the bar and again to bring it back. Two more options are handy while you tune the config. polybar --dump=height main prints a resolved setting and exits. polybar --png=bar.png main saves a snapshot after three seconds, which is easier to share than a cropped screenshot.
Remove Polybar and bring i3bar back
Undo the i3 changes first, so the next restart does not try to run a missing binary. Delete the launcher and wallpaper lines, then uncomment the bar block:
sed -i '/polybar/d; /\.fehbg/d' ~/.config/i3/config
sed -i '/^# bar {/,/^# }/ s/^# //' ~/.config/i3/config
The first command also removes the Alt+b binding, since it mentions polybar. Stop the running bar and restart i3:
polybar-msg cmd quit
i3-msg restart
i3bar returns at the bottom of the screen. Now remove the package:
sudo dnf remove polybar
dnf takes the two libraries with it:
Package Arch Version Repository Size
Removing:
polybar x86_64 0:3.7.2-10.fc45 fedora 2.8 MiB
Removing unused dependencies:
jsoncpp x86_64 0:1.9.6-3.fc44 fedora 285.6 KiB
libmpdclient x86_64 0:2.26-2.fc45 fedora 193.4 KiB
Transaction Summary:
Removing: 3 packages
After this operation, 3 MiB will be freed (install 0 B, remove 3 MiB).
Running transaction
[1/4] Prepare transaction 100% | 47.0 B/s | 3.0 B | 00m00s
[2/4] Removing polybar-0:3.7.2-10.fc45. 100% | 4.7 KiB/s | 111.0 B | 00m00s
[3/4] Removing jsoncpp-0:1.9.6-3.fc44.x 100% | 3.3 KiB/s | 10.0 B | 00m00s
[4/4] Removing libmpdclient-0:2.26-2.fc 100% | 70.0 B/s | 12.0 B | 00m00s
Complete!
Your config and launch script stay in ~/.config/polybar, ready for a reinstall.
Polybar error messages and fixes
These are the messages we hit while building this setup, with the cause of each.
Undefined bar: main. Available bars: example
Polybar read a config that has no [bar/main] section. Usually ~/.config/polybar/config.ini is missing or misnamed, so Polybar fell back to the sample in /etc. Forcing the sample reproduces it:
polybar -c /etc/polybar/config.ini main
The error lists the bars that file does define:
polybar|notice: Parsing config file: /etc/polybar/config.ini
polybar|error: Uncaught exception, shutting down: Undefined bar: main. Available bars: example
Check the path, and check that the bar name in the launch script matches the section header.
Disabling module “pulseaudio” (reason: Could not connect pulseaudio context.)
Fedora runs PipeWire with its PulseAudio server per user, and the socket lives under XDG_RUNTIME_DIR. Started from an SSH session or a cron job without that variable, Polybar cannot find it. Started by i3, it connects and logs the default sink, as in the log above.
Disabling module “wlan” (reason: No interface found for type ‘wireless’)
The machine has no wireless card, or the card is not up. It is harmless. On a desktop without Wi-Fi, drop wlan from modules-right to quiet the log.
background_manager: Failed to get root pixmap, default to black
pseudo-transparency = true in the sample config copies the wallpaper behind the bar, and there is no wallpaper yet. Set one with feh before Polybar starts, as shown earlier, or set pseudo-transparency = false under [settings].
Icons show as empty boxes
The icon font name in config.ini does not exist on this release, and fontconfig substituted a text font. Polybar logs the font it actually loaded, so check the Loaded font lines first. Use the Font Awesome 7 and 6 family list from this guide rather than a single name. For other icon sets, the Nerd Fonts guide covers patched fonts that bundle text and icons in one family. If you are still building out the rest of the desktop, our Fedora 45 post-install checklist and the terminal emulator roundup are good next stops.