a keyd service in Guix
It took a really long time to figure this out, but I can finally use keyd in Guix.
I started out with a manually created keyd.conf file and I manually invoked keyd with sudo so I could get my default bindings. This also helped to verify some of the pieces worked before I started.
about the keyd config
I tend to use small keyboards and so I’ve gotten used to what might sound like a peculiar mapping. I like the caps lock key to be a super if held down or a tab if pressed. I like the tab key to be an escape key or an alt key. And I like the left shift double as an escape key when tapped. Here’s what the keyd.conf would look like for this:
[ids]
*
[main]
capslock=overload(meta, tab)
esc=tilde
leftshift=overload(shift, esc)
tab=overload(alt, esc)
I wanted to define a service to create the etc file for me instead of manually placing such a file.
the Guix config
It took weeks of trial and error and I can’t even explain how I got here or even if it’s really correct. I couldn’t understand the documentation I was able to find and when I tried to use AI to generate something, nothing that it generated seemed to do anything. But this is the service that I ended up defining:
(define keyd-service-type
(service-type
(name 'keyd)
(extensions
(list (service-extension etc-service-type
(lambda (config)
`(("keyd/keyd.conf"
,(plain-file "keyd.conf" config)))))
(service-extension shepherd-root-service-type
(lambda (config)
(list (shepherd-service
(provision '(keyd))
(documentation "keyd keyboard remapping daemon")
(requirement '(user-processes))
(auto-start? #t)
(start #~(make-forkexec-constructor
(list #$(file-append keyd "/bin/keyd"))
#:log-file "/var/log/keyd.log"))
(stop #~(make-kill-destructor))
(respawn? #f)))))))
(default-value (apply string-append (list
"[ids]" "\n"
"*" "\n\n"
"[main]" "\n"
"capslock=overload(meta, tab)" "\n"
"esc=tilde" "\n"
"leftshift=overload(shift, esc)" "\n"
"tab=overload(alt, esc)" "\n"
)))
(description "Run keyd keyboard remapping daemon")))
Working backwards, a default config is defined with my personalized settings. A service is defined to make use of the keyd Guix package and to use those default settings.
While reading through the keyd man page I learned there was a special key combo to kill keyd in case the config was so bad the system wasn’t usable. With that in mind I decided the service should NOT respawn if the daemon were to exit.
That’s a block near the top of my config.scm file that defines the system. Additionally, I needed to add the following further up so some of the symbols would resolve properly:
(use-service-modules admin)
(use-package-modules linux)
I can’t remember what the errors were that came up without them.
To make use of this service, I needed to add it to the services list. Originally, this list looked like this:
(services %desktop-services)
So I added the new one thusly:
(services
(cons*
(service keyd-service-type)
%desktop-services))
what’s the point
Of keyd? I think that’s obvious, better mappings! Of Guix? I really like the GNU philosophy – despite that I don’t care too much for many of the tools – and I really like determinant, reproducible systems. So I’m a step closer to understanding a new ecosystem. A painfully slow and meager step, but a step none-the-less.
Tags: index, guix
#index
#guix
Navigation
index
tags
prev ⏰
⏰ next
created: 2026-05-09
(re)generated: 2026-05-22
page source