tonybtw.com

tonybtw.com

https://git.tonybtw.com/tonybtw.com.git git://git.tonybtw.com/tonybtw.com.git
11,826 bytes raw
1
#+title: How to Install Suckless Programs on NixOS | Dwm, Dmenu, St
2
#+author: Tony, btw
3
#+date: 2025-09-14
4
#+HUGO_TITLE:
5
#+HUGO_FRONT_MATTER_FORMAT: yaml
6
#+HUGO_CUSTOM_FRONT_MATTER: :image "/img/suckless-nixos.png" :showTableOfContents true
7
#+HUGO_BASE_DIR: ~/repos/tonybtw.com
8
#+HUGO_SECTION: tutorial/suckless-nixos
9
#+EXPORT_FILE_NAME: index
10
#+OPTIONS: toc:nil broken-links:mark
11
#+HUGO_AUTO_SET_HEADLINE_SECTION: nil
12
#+DESCRIPTION: This is the 5th installment of the NixOS Tutorials. We discuss dev shells and how to implement suckless utilities in NixOS, such as dwm, dmenu, and st.
13
14
* Intro
15
What's up guys, my name is Tony, and today I'm going to give you a quick and painless guide on installing suckless utilities on NixOS, the right way.
16
17
Disclaimer: This guide is heavily nix and programming oriented. If you aren't tapped into this type of content, I suggest jumping over to a channel more suitable for you such as MR.BEAST or Ms. Rachel
18
19
NixOS is great, but the hardest part of most people's journey into it is installing DWM, Dmenu, St, and other suckless utilities. This is because of how Nix stores binaries, and how there is no 'config file' with sucless software, in the same way as other software such as qtile, i3, hyprland, etc. This is by design, in a good way, because Suckless Software is meant to be minimal and extensible, so the source code is the config.
20
21
#+begin_src quote
22
"Unfortunately, the tendency for complex, error-prone and slow software seems to be prevalent in the present-day software industry. We intend to prove the opposite with our software projects." - suckless philosophy
23
#+end_src
24
25
Let's get into it.
26
27
* Dependencies
28
Part of this tutorial is going to be assuming you already have flakes, and home manager set up. If you watched my nixos from scratch series, it covers all of that. If not, I highly suggest just cloning the nixos-from-scratch repo, and following along this tutorial with that config directory already set up.
29
30
1. [[https://www.github.com/tonybanters/nixos-from-scratch][NixOS From Scratch Repo]]
31
2. [[https://www.youtube.com/watch?v=2QjzI5dXwDY][YouTube Guide]]
32
33
* DWM
34
Let's get started with dwm. You don't need a flake or home manager to set this up, its actually quite easy.
35
36
** Configuration.nix
37
38
First, we need to add this block in our services.xserver.windowManager set.
39
40
#+begin_src nix
41
services.xserver.windowManager.dwm = {
42
    enable = true;
43
    package = pkgs.dwm.overrideAttrs {
44
        src = ./config/dwm;
45
    };
46
};
47
#+end_src
48
49
So the entire block will look like this:
50
#+begin_src nix
51
  services = {
52
53
    displayManager = {
54
      ly.enable = true;
55
    };
56
57
    xserver = {
58
      enable = true;
59
      autoRepeatDelay = 200;
60
      autoRepeatInterval = 35;
61
      windowManager.qtile.enable = true;
62
      windowManager.dwm = {
63
        enable = true;
64
        package = pkgs.dwm.overrideAttrs {
65
          src = ./config/dwm;
66
        };
67
      };
68
    };
69
70
    picom.enable = true;
71
  };
72
#+end_src
73
74
75
** Cloning Dwm
76
Now we need to ensure our dwm folder exists and is in fact in ~/nixos-dotfiles/config
77
78
#+begin_src sh
79
git clone https://git.suckless.org/dwm ~/nixos-dotfiles/config/dwm
80
#+end_src
81
82
While we have cloned this, before we actually build dwm, let's just change 1 or 2 things so we can show that this works:
83
84
let's open `config.h` with vim here, `nvim ~/nixos-dotfiles/config/dwm/.`
85
86
We'll change the font here, and we'll change the terminal to alacritty (since we don't have st installed yet.) Also, we'll change our modkey to super.
87
88
#+begin_src c
89
static const char *fonts[] = {"JetBrainsMono Nerd Font:size=16"};
90
// ...
91
static const char *termcmd[]  = { "alacritty", NULL };
92
#+end_src
93
94
** Rebuild
95
96
It's literally that easy. Now dwm will be enabled at the display manager as soon as we rebuild. So let's run:
97
98
#+begin_src sh
99
sudo nixos-rebuild switch --flake ~/nixos-dotfiles#nixos-btw
100
#+end_src
101
102
Remember to replace #nixos-btw with whatever your host is specified in your flake. If you aren't using flakes, just run it without the --flake parameter.
103
104
Now we can log out of qtile, or just reboot, and we see Dwm as an option in our display manager.
105
My logout keybind in qtile is Super Control Q, so I'll hit that right now and there we go.
106
107
So we see DWM here in our ly config, and thats perfect. Exactly what we're expecting. Let's hop into it to see if the stuff we changed in config.def.h changed.
108
109
Boom, there we go. We see our jetbrains mono nerd font, and we see its size has been adjusted.
110
111
* How to Patch DWM in NixOS
112
Let's cover how to patch dwm in nixos, the nix way. I will demonstrate this with a quick patch, and then I'll just clone my version of dwm, so we can move onto st and dmenu.
113
114
Let's make a folder called patches in our dwm config folder.
115
116
Open alacritty with Alt Shift Enter
117
118
#+begin_src sh
119
mkdir ~/nixos-dotfiles/config/dwm/patches
120
#+end_src
121
122
Now we can open up firefox. since we dont have dmenu, lets just run firefox from our terminal.
123
124
#+begin_src sh
125
firefox & disown
126
#+end_src
127
128
And let's go to [[https://dwm.suckless.org/patches/][Dwm's Patches Directory]]
129
130
Let's grab the vanity gaps patch as an example here. So we'll go down to vanity gaps, and we'll
131
right click-> save link as on this version of it, and lets save it into that patches folder we just created. Now we can exit firefox with super shift c.
132
133
There’s a way to put patches straight into the Nix set, but I prefer to do it the old-school way — just patching directly in our folder. Honestly, what’s the point of pointing to our own dwm folder if we aren’t going to patch it ourselves?
134
135
Back in our Alacritty terminal, lets cd into that dwm directory and apply the patch.
136
137
#+begin_src sh
138
cd ~/nixos-dotfiles/config/dwm
139
patch -i patches/<tab>
140
#+end_src
141
142
And based on the output, we see the patch was succesful.
143
144
#+begin_src output
145
patching file config.def.h
146
Hunk #1 succeeded at 3 with fuzz 1.
147
Hunk #2 succeeded at 43 with fuzz 2 (offset 1 line).
148
Hunk #3 succeeded at 92 (offset 1 line).
149
patching file dwm.c
150
Hunk #1 succeeded at 86 (offset -1 lines).
151
Hunk #2 succeeded at 119 (offset -1 lines).
152
Hunk #3 succeeded at 205 (offset -1 lines).
153
Hunk #4 succeeded at 213 (offset -1 lines).
154
Hunk #5 succeeded at 645 (offset -1 lines).
155
Hunk #6 succeeded at 1051 (offset -1 lines).
156
Hunk #7 succeeded at 1530 (offset -1 lines).
157
Hunk #8 succeeded at 1711 (offset -1 lines).
158
patching file vanitygaps.c
159
#+end_src
160
161
Alright, let's reload rebuild switch one more time here, and reload dwm to show that the patch worked.
162
163
#+begin_src sh
164
sudo nixos-rebuild switch --flake ~/nixos-dotfiles#nixos-btw
165
#+end_src
166
167
Alt Shift Q to reload dwm here. And we'll jump back into it. Now we can just open 2 terminals here and we see the gaps. Great. Let's move onto st and dmenu.
168
169
* Install ST and DMENU
170
First of all, lets actually create a nixos module for the suckless utilities.
171
172
modules/suckless.nix:
173
#+begin_src nix
174
{ pkgs, ... }:
175
176
{
177
  home.packages = with pkgs; [
178
    (pkgs.st.overrideAttrs (_: {
179
      src = ../config/st;
180
      patches = [ ];
181
    }))
182
    (pkgs.dmenu.overrideAttrs (_: {
183
      src = ../config/dmenu;
184
      patches = [ ];
185
    }))
186
    slock
187
    surf
188
  ];
189
}
190
#+end_src
191
192
And let's add it to our home.nix file:
193
#+begin_src
194
195
  imports =
196
    [
197
      ./modules/neovim.nix
198
      ./modules/suckless.nix
199
    ];
200
201
#+end_src
202
203
Now we just need to clone st, and dmenu into our config directory.
204
#+begin_src sh
205
cd ~/nixos-dotfiles/config
206
git clone https://git.suckless.org/st
207
git clone https://git.suckless.org/dmenu
208
#+end_src
209
210
So if we run `sudo nixos-rebuild switch --flake ~/nixos-dotfiles#nixos-btw`
211
we should have st and dmenu ready to go. Now it's time to talk about DevShells
212
213
* DevShell to configure ST and Dmenu
214
215
A dev shell is sort of like a container, but its declarative. I can drop devShell parameters into a flake, and someone else can take my flake, and immediately hop into that devShell with the same environment as me. This makes it really easy to reproduce the expected environment, and move forward with the development process. Let's do it the nix way.
216
217
** ST
218
219
Let's set up our dev shell by opening our flake.nix and adding this in the outputs section:
220
221
#+begin_src nix
222
...
223
    let
224
      system = "x86_64-linux";
225
      pkgs = import nixpkgs { inherit system; };
226
    in
227
    {
228
      devShells.${system}.suckless = pkgs.mkShell {
229
        # toolchain + headers/libs
230
        packages = with pkgs; [
231
          pkg-config
232
          xorg.libX11
233
          xorg.libXft
234
          xorg.libXinerama
235
          fontconfig
236
          freetype
237
          harfbuzz
238
          gcc
239
          gnumake
240
        ];
241
      };
242
      ...
243
#+end_src
244
245
Now we can run nixos-rebuild switch again, and jump into this devshell to start working on our st.
246
247
#+begin_src sh
248
sudo nixos-rebuild switch --flake ~/nixos-dotfiles#nixos-btw
249
cd ~/nixos-dotfiles
250
#+end_src
251
252
To run this devShell, its very simple. lets just run
253
#+begin_src sh
254
nix develop .#suckless
255
cd config/st
256
#+end_src
257
258
We're now in a nix development shell with the packages that we specified in our flake. We can open st by just typing st (our current version of st). We see, its the default st. Let's open up config.def.h and make some changes, and build st again.
259
260
Let's just change the font and make it huge, so you can see this works.
261
#+begin_src c
262
static char *font = "JetBrainsMono Nerd Font:pixelsize=24:antialias=true:autohint=true";
263
#+end_src
264
265
Alright, let's save this file, and run `make`. Looks like it built correctly, so we can now run
266
this new version of st by typing `./st`, and there we go. Beautiful new build of st right there. Let's check out this beautiful default colorscheme with nitch. Wow. Amaazing
267
268
So basically, once we're happy with our changes, we can quit out of this devshell, and rebuild our system again. Just type `make clean` first, so we can get rid of any extraneous files, and then exit.
269
270
Now we run nixos-rebuild switch again, and we can just open st, and now our nixos is pointing to our new build of st.
271
272
** DMENU
273
274
For dmenu, we can use the same devShell as before. So let's enter it again here:
275
276
#+begin_src sh
277
nix develop .#suckless
278
cd config/dmenu
279
#+end_src
280
281
Let's change some stuff here to show what the devshell does again
282
#+begin_src c
283
static const char *fonts[] = {
284
	"JetBrainsMono Nerd Font:size=16"
285
};
286
static const char *prompt      = NULL;      /* -p  option; prompt to the left of input field */
287
static const char *colors[SchemeLast][2] = {
288
	/*     fg         bg       */
289
    [SchemeNorm] = { "#7dcfff", "#24283b" },
290
    [SchemeSel]  = { "#000000", "#7aa2f7" },
291
    [SchemeOut]  = { "#000000", "#7dcfff" },
292
};
293
294
static unsigned int lines      = 10;
295
#+end_src
296
297
We can run make now, and lets test our new build:
298
299
#+begin_src sh
300
ls | ./dmenu
301
#+end_src
302
303
And if we wanted to apply a patch here, we would do the same thing as before.
304
305
Once we're happy with what it looks like, we can exit our shell again, but first lets make clean to get rid of the unnecessary files.
306
307
#+begin_src
308
make clean; exit.
309
sudo nixos-rebuild switch --flake ~/nixos-dotfiles#nixos-btw
310
ls | dmenu
311
#+end_src
312
313
And there we go. We see our dmenu binary is actualy pointing to the dmenu we just built. Awesome
314
315
* Final Thoughts
316
317
In the next installment of "NixOS From Scratch", we'll create 2 package variables, and use unstable to update stuff that we don't care if it breaks our system, and lock the core utils to stable.
318
319
This has been heavily 'programming oriented', but this will leapfrog you forward in your nixos journey. Let me know if you like this sort of content, or what else you would like to see.
320
321
Thanks so much for checking out this tutorial. If you got value from it, and you want to find more tutorials like this, check out
322
my youtube channel here: [[https://youtube.com/@tony-btw][YouTube]], or my website here: [[https://www.tonybtw.com][tony,btw]]
323
324
You can support me here: [[https://ko-fi.com/tonybtw][kofi]]