Conditional Configuration for Hyprland

Hyprland has no built-in support for conditional configuration. This makes me a bit sad as I like to maintain a single dotfile repo that works for more than one computer. Here's how I configure Hyprland based on hostname.

Conditional Configuration for Hyprland

I like to track all of my Linux dotfiles in a single repository so that it’s easy to restore state, even when completely reinstalling the operating system. Recently, I migrated from Linux Mint running i3 desktop to Linux Arch running Hyprland. There was a fair amount of customization work which went pretty well and now that I have stable installs on my laptop and desktop computers I want to add the new dotfiles to my revision control. This is where the gotcha happened. Hyprland has no mechanism for conditionally including configuration, providing some unique challenges to my preferred revision control.

After mulling it over for a few weeks, I’ve come up with a passable approach to conditionally including Hyprland config based on the system hostname. My technique is roughly as follows:

  1. Source a non-existent custom-by-hostname.conf file.
  2. Add a custom-$HOSTNAME.conf file for each of your computers.
  3. Use Hyprland to create a symlink for the correct host at startup.
  4. Bonus: configure Hypridle for different host behavior.

Let’s jump in!

Tracking Hyprland Custom Config

I installed Hyprland using the excellent ml4w-dotfiles project by Stephan Raabe. It’s a one stop shop to begin your Hyprland experience with a well-tuned desktop environment. The project even has customization in mind, including the ~/dotfiles/.config/hypr/conf/custom.conf file for this very purpose.

Add a line to ~/dotfiles/.config/hypr/conf/custom.conf to track a non-existent configuration file.

# Import settings unique to this computer
# This file will be symlinked by Hyprland at start.
source = ~/.config/hypr/conf/custom-by-hostname.conf

Add Custom Config to Hostname-Specific Files

Now add custom config to files that use the hostname of each computer. For now you may simply leave them blank but they need to exist. Here I’ve created two files:

touch ~/dotfiles/.config/hypr/conf/custom-krusty.conf
touch ~/dotfiles/.config/hypr/conf/custom-nelson.conf

The key to pull it all together is to create a symbolic link using the non-existent filename. But we won’t crate the symlink, Hyprland will.

At the top of the ~/.config/hypr/hyprland.conf file, add this directive to create the symlink:

# Import Hyprland settings unique to this computer
# This automatically symlinks the correct file based on hostname
exec-once = ln -s "./custom-$HOSTNAME.conf" ~/dotfiles/.config/hypr/conf/custom-by-hostname.conf &> /dev/null

There are several things to note about the above command. First, Hyprland will try to create the symbolic every time you login. There’s really no harm in this, we’re piping both stout and sterr to null so that there are no error messages when the symlink already exists. Second, the symlink source is relative to the destination location, so we don’t need a full path. Third, $HOSTNAME makes an assumption that your shell has a matching environment variable. If bash is your preferred shell this will work, it may not for other shells.

Bonus: Conditional config for Hypridle

I want my laptop to automatically suspend after a certain period of time, so it’s nice that ml4w-dotfiles sets this up to happen after 30 minutes. However, I don’t want my main desktop to ever suspend. This provides another unique conditional config challenge as hypridle configuration cannot be stored in the custom.conf file we used above.

The solution I found for this is to change the “listener” behavior based on the hostname. Here’s the entire block from ~/.config/hypr/hypridle.conf:

listener {
    timeout = 1800
    on-timeout = [ $HOSTNAME == "krusty" ] || systemctl suspend
}

The listener is still created with the same 30 minute timeout. However, the command that is run on this timeout period changes based on the hostname of the computer. I do not want to suspend my desktop (which is also a home server), so I start off the command checking if the hostname is krusty. If that evaluates to true, the condition is satisfied and execution will end. However, any other host name will evaluate to false, so execution will move on to the “or” part of the command after the || operators. In this way, Krusty never suspends, but Nelson does. Bob’s your uncle and my laptop battery life has never been better.

Check Out My dotfiles

Admittedly, ml4w-dotfiles uses a different approach to dotfile tracking than I do. This setup is a bit less automatic than it used to be… I may need to do a git restore after installing an ml4w-dotfiles update. However, all my settings are now under version control and they work for both of my machines.

If you’re wondering “where’s the code?”, it’s right here.

essential