Ordenada is a configuration framework based on the Nix package manager that aims to make it easy to build reproducible development environments. It draws inspiration from the RDE project for GNU Guix.
Ordenada’s configuration is centered around users and features. Features are blocks of configuration that provide certain functionality for a user, such as setting up your email, adding your GnuPG keys, or configuring your window manager. Normally, you only need to enable them and all the required settings will automatically be configured for you, although there are many available options you can tweak to fit your needs. See the full list of features and options.
NOTE: Ordenada is in current development and its API is subject to change
You can install Ordenada into your NixOS configuration using Flakes. First, add its flake URL to your list of inputs.
{
inputs = {
# ...other inputs
ordenada.url = "github:migalmoreno/ordenada";
};
}
Import its list of modules into your configuration.
{
outputs =
{ nixpkgs, ordenada, ... }:
{
nixosConfigurations."<hostname>" = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
# ...other modules
ordenada.nixosModules.ordenada
];
};
};
}
Optionally, if you want to make use of Ordenada’s utility library, to e.g. create your own features, add the following to your configuration.
nixpkgs.overlays = [ ordenada.overlays.default ];
In a typical single user setup, you just need to add a global set of features
and add your user to the users
set.
{ config, pkgs, ... }:
{
ordenada = {
users = {
bob = { };
};
features = {
userInfo = {
username = "bob";
};
home.enable = true;
gnupg.enable = true;
gtk = {
enable = true;
theme = {
name = "adw-gtk3";
package = pkgs.adw-gtk3;
};
};
emacs = {
enable = true;
all-the-icons.enable = true;
appearance.enable = true;
eglot.enable = true;
modus-themes = {
enable = true;
dark = true;
};
};
irc = {
enable = true;
accounts = {
libera = {
network = "irc.libera.chat";
nick = "bob";
};
oftc = {
network = "irc.oftc.net";
nick = "bob";
};
};
};
mail = {
enable = true;
accounts = {
personal = {
primary = true;
fqda = "[email protected]";
extraConfig = {
imap = {
host = "mail.example.com";
port = 993;
};
smtp = {
host = "mail.example.com";
port = 465;
};
};
};
};
};
sway.enable = true;
waybar = {
enable = true;
modules = with config.ordenada.features.waybar.defaultModules; [
swayWorkspaces
swayWindow
pulseaudio
battery
swayLanguage
clock
swaync
];
};
};
};
}
In more complex multi-user installations, you can modify the set of user features to match each user’s needs. As shown in the example below, you could make user bob
augment the global features with ones specific to him. Alternatively, you could also create a set of user features from scratch and augment certain features as you go, like in the case of the alice
user below.
{ config, ... }:
{
ordenada = {
users = {
bob = {
features = config.ordenada.features // {
emacs.spelling.enable = true;
firefox.enable = false;
};
};
alice = {
features = with config.ordenada.features; {
userInfo = {
username = "alice";
};
inherit gnupg;
home.enable = true;
bash.enable = true;
emacs = with emacs; {
enable = true;
dired.enable = true;
org-roam.enable = true;
inherit modus-themes eglot;
};
};
};
};
features = {
userInfo = {
username = "bob";
};
# ...rest of global features
};
};
}
With the above setup, two users bob
and alice
will be configured in the system. bob
will end up with an augmented global features setup while alice
will only have the features home
, bash
, the inherited global gnupg
feature, and emacs
along with its features.
By default, all users inherit the global features. Thus, if you want to write a user features set from scratch (e.g. alice
’s example above) you don’t need to include the whole global features set again for a new user feature (e.g. the home
, bash
, and emacs
features above). However, if you want to apply the feature default settings to the user feature (i.e. those that are not explicitly set in the global feature) you’ll need to explicitly inherit from the global feature, such as the case with the gnupg
feature above.
You can use Ordenada’s utilities to extend its available features with your own. For instance, the following shows how to create a feature example
.
{
config,
lib,
pkgs,
...
}:
with pkgs.lib.ordenada;
let
cfg = config.ordenada.features.example;
in
{
options = {
ordenada.features.example = {
enable = lib.mkEnableOption "the example feature";
message = lib.mkOption {
type = lib.types.str;
description = "The message to show.";
default = "";
};
};
};
config = (
lib.mkMerge [
(lib.mkIf cfg.enable {
environment.sessionVariables = {
EXAMPLE_ENV = 1;
};
})
{
home-manager = mkHomeConfig config "example" (user: {
home.sessionVariables = lib.mkIf (hasFeature "acme" user) {
EXAMPLE_HOME_ENV = "EXAMPLE_HOME_ENV_VALUE";
};
programs.emacs = mkElispConfig {
name = "ordenada-example";
config = ''
;; < your Elisp configuration >
(setq my-elisp-value ${user.features.example.message})
'';
elispPackages = [ ];
summary = "My example Emacs feature";
};
});
}
]
);
}
The example
feature above showcases a common feature definition workflow. First, we define a list of options for this feature that we’ll be able to access from anywhere in our configuration. Then, we add a system configuration if the feature is enabled. Next, we add a home configuration via the special utility mkHomeConfig
, which allows us to configure home settings for all our Ordenada users. In this example, we set a home environment variable as long as the acme
feature is enabled (checked with the hasFeature
utility). Finally, we add Emacs Lisp configuration through the mkElispConfig
utility which will add a new Emacs configuration package for this feature with interpolated feature options (user.features.example.message
).
See the project’s homepage for the full list of configuration options.