Useful NixOS snippets
Miscellaneous Nix snippets that I'm using in my configs. While I don't have sources for these, many have been found and remixed from the NixOS Discourse and other places online.
Parameterising modules
I have a few simple modules that configure things relating to a desktop user, but that username isn't always the same. Fortunately it's easy to add custom options to cover things like this.
In your module:
{ config, pkgs, lib, ... }:
with lib;
{
# define options (in this case, "common", matching the module name)
options.common = {
user = mkOption {
description = "User to use for desktop services.";
default = "<USERNAME>";
type = types.str;
};
};
config = {
# place your usual module content here
# config.common.user can now be used here, or in other modules
# you can also interpolate within a string or attribute,
# e.g. users.users."${config.common.user}" = { ... };
}
}
Include current config in /etc
This is useful to see the config for the currently booted system, in case the configuration has been changed in the mean-time.
environment.etc.nixos-booted.source = ./.;
Pin nixpkgs to the system nixpkgs as a registry override
Prevents a user accidentally pinning an old nixpkgs version in their profile (me):
nix.registry.nixpkgs.to = { type = "path"; path = pkgs.path; };
MPD with user Pipewire for output
This required the addition of the XDG_RUNTIME_DIR
for the Pipewire library to find the server socket.
services.mpd = {
enable = true;
user = "<USERNAME>";
musicDirectory = "/path/to/music";
network.listenAddress = "any";
extraConfig = ''
audio_output {
type "pipewire"
name "PipeWire"
}
'';
};
systemd.services.mpd.environment = {
XDG_RUNTIME_DIR = "/run/user/1000"; # substitute your user ID if necessary
};
Timers
Here's an example of using systemd timers to switch RGB lights on and off via OpenRGB:
systemd.timers.morning = {
wantedBy = [ "timers.target" ];
partOf = [ "rgb-on.service" ];
timerConfig = {
OnCalendar = "07:00";
Unit = "rgb-on.service";
};
};
systemd.timers.evening = {
wantedBy = [ "timers.target" ];
partOf = [ "rgb-off.service" ];
timerConfig = {
OnCalendar = "22:30";
Unit = "rgb-off.service";
};
};
systemd.services.rgb-on = {
serviceConfig.Type = "oneshot";
script = ''
${pkgs.openrgb}/bin/openrgb -d RAM -m static -c ff0000
'';
};
systemd.services.rgb-off = {
serviceConfig.Type = "oneshot";
script = ''
${pkgs.openrgb}/bin/openrgb -d RAM -m off
'';
};
Note that you do NOT need to install openrgb
separately in your systemPackages, as Nix will build and use the package in the store path directly inside the systemd unit.
It is also possible to use multiple services by adding a target in between. e.g. How do you configure multiple systemd services to use one timer? - Server Fault
Enable TCP connection for Pulseaudio clients in Pipewire
As of recently, Pipewire is no longer configured through nix expressions, but it is still easy to add custom configs:
environment.etc."pipewire/pipewire.conf.d/pipewire-pulse-tcp.conf".text = ''
context.modules = [
{ name = libpipewire-module-protocol-pulse
args = {
server.address = [
"unix:native"
"tcp:4713"
]
}
}
]
Add a noise canceling source to Pipewire
This adds a proxy that you can use to apply noise canceling on your mic source. Note that this only uses processing power when active (e.g. used as an input, or viewed by pavucontrol
).
environment.etc."pipewire/pipewire.conf.d/noise-canceling-source.conf".text = ''
context.modules = [
{ name = libpipewire-module-filter-chain
args = {
node.description = "Noise Canceling Proxy"
media.name = "Noise Canceling source via RNNoise"
filter.graph = {
nodes = [
{
type = ladspa
name = rnnoise
plugin = "${pkgs.rnnoise-plugin}/lib/ladspa/librnnoise_ladspa.so"
label = noise_suppressor_stereo
control = {
"VAD Threshold (%)" = 50.0
"VAD Grace Period (ms)" = 200
"Retroactive VAD Grace (ms)" = 0
}
}
]
}
audio.position = [ "FL", "FR" ]
capture.props = {
node.name = "capture.rnnoise_source"
node.passive = true
audio.rate = 48000
}
playback.props = {
node.name = "rnnoise_source"
media.class = Audio/Source
audio.rate = 48000
}
}
}
]
'';