Options Reference
Table of Contents
Every Emanix-specific setting lives under the emanix.* namespace.
Most are Home Manager options, set inside home-manager.users.<user> — or,
better, passed through mkHost's homeModules. Three groups are NixOS-level
instead, and are marked as such below: emanix.username, emanix.firstboot.*,
emanix.hardware.gpu and emanix.installer.*.
Nothing here is set by a role, because there are no roles. A host gets the defaults unless the flake consuming Emanix says otherwise.
Settings for Emacs itself — the status bar, the prose renderer, buffer groups —
are not options. They are Emacs variables, set from your own Emacs Lisp; see
Emacs Settings. The EMANIX_* environment
variables are listed at the end of this page.
1. Core
1.1. emanix.username — NixOS level
| Type | string |
| Default | — (required) |
Which user the distribution configures. Read by modules/base.nix and
modules/ewm.nix to address home-manager.users.<name>.
Do not set it by hand. Pass username to mkHost; it sets this from the
same argument, so the option and the composed system cannot disagree.
1.2. emanix.role
| Type | enum: workstation / server / wsl |
| Default | workstation |
What shape of box this is. It selects nothing. No module is imported because
of it and no behaviour in the distribution branches on it. It is metadata: set
by mkHost from its role argument, exported to the shell as EMANIX_ROLE,
and interpreted by the consuming flake, which may well gate real things on it.
Like username, this is an argument rather than an opinion — so it is set
plainly, not with mkDefault. Overriding it to disagree with the value
mkHost was called with produces an incoherent host.
1.3. emanix.gui
| Type | bool |
| Default | true |
This machine has a graphical session. Gates the cursor theme, the Wayland tools, GUI applications, the screen locker, and terminal config.
1.4. emanix.hardware.gpu — NixOS level
| Type | enum: amd / intel, or null |
| Default | null |
The graphics driver to force-load in the initrd, so a compositor started
from tty1 does not lose the DRM-master race. null contributes nothing, which
is correct for a headless or virtualised host.
Setting it asserts that hardware.enableRedistributableFirmware is true —
forcing a driver into the initrd without its firmware blobs is a black screen,
and boot.initrd.allowMissingModules hides that at build time. See
Architecture for why a distribution ships the
capability and not the fact.
1.5. emanix.ewm.enable
| Type | bool |
| Default | false |
This machine's Emacs is the system-owned EWM build. When false, the home layer installs the non-EWM pgtk Emacs (31.1) instead and runs the daemon as a systemd user service.
This is the single switch between "Emacs is my desktop" and "Emacs is an editor
with a daemon". Enabling it also means importing nixosModules.ewm from the
flake — the option gates the home side; the module supplies the compositor
service. See Components.
1.6. emanix.theme
| Type | enum of palette names |
| Default | catppuccin-mocha |
Active theme. An enum, not a string: the value is a lookup key for the theme plan, and the consumers of that plan degrade silently on a name that matches nothing, so a typo used to build cleanly and surface later as a theme that quietly did not apply. Now it is an eval error naming the valid set. See Theming.
1.7. emanix.emacs.extraPackages
| Type | function of the package set |
| Default | epkgs: [ ] |
Emacs packages the consuming flake adds to the distribution's Emacs build:
home-manager.users.<user>.emanix.emacs.extraPackages = epkgs: [ epkgs.s ];.
It takes the package set rather than a plain list, so the consumer never names
the Emacs variant — which base a host runs (pwayl/Skia 31.1 under EWM, pgtk 31.1
otherwise) is the distribution's choice.
A package the distribution does not ship is added the same way:
epkgs: [ epkgs.weblorg ], for example.
1.8. emanix.emacs.base
| Type | package |
| Default | — (none; evaluation fails if nothing sets it) |
The Emacs derivation this host's Emacs packages are built from. Do not set it
in a host config. It is set by whichever module owns the host's Emacs:
nixosModules.ewm (the pwayl/Skia build) on EWM hosts, and the home layer's
daemon module (pgtk) everywhere else. A consumer reads it when it has to build
an Emacs package itself, so that package is byte-compiled by the same Emacs that
loads it. There is deliberately no default: a default would be a variant
decision nobody made, and a host that sets neither fails to evaluate rather than
quietly building the wrong Emacs.
2. Source paths — emanix.src.*
Where things live on disk. Two different checkouts matter, and conflating them
is the classic mistake: path is this distribution's checkout,
dotfilesPath is your flake's.
| Option | Type | Default | Meaning |
|---|---|---|---|
emanix.src.path |
string | ~/projects/emanix |
The Emanix source checkout, used for live-editable config |
emanix.src.dotfilesPath |
string | ~/dotfiles |
The consumer's checkout — the flake that imports Emanix |
emanix.src.themesDir |
string | generated store path | The rendered theme tree. Read-only by default; override to supply your own |
emanix.src.binDir |
string | ${src.dotfilesPath}/bin |
Where the consumer's scripts live; put on PATH by the shell |
emanix.src.liveElisp |
bool | true |
Symlink the Emacs Lisp out of the Nix store |
2.1. On liveElisp
Symlinks the Lisp out of the Nix store, straight from the Emanix checkout, so edits take effect on restart with no rebuild.
Set false on a host with no checkout; the Lisp is then copied into the store and editing it requires a rebuild.
This is a deliberate seam, one of two in the distribution — the other is
emanix.emacs.extraPackages: it trades
generation-pinning for edit latency on the files that get edited most. The
content is still version-controlled — it is simply not content-hashed into the
system generation, so a rollback does not roll the Lisp back with it.
It also means moving or renaming the checkout breaks Emacs until the next rebuild, because the symlink target vanishes. Move and rebuild as one step.
3. Opt-in components
3.1. emanix.ghostty.enable
| Type | bool |
| Default | emanix.gui |
Install and configure the GPU-accelerated terminal. Defaults to the GUI flag, which is why it appears automatically on a graphical host — but it is a separate option so a headless-but-terminal host can opt in surgically. A WSL host under WSLg is the usual case: no compositor, but a real terminal is still wanted.
4. Installer — NixOS level
| Option | Type | Default |
|---|---|---|
emanix.installer.flake |
path | the distribution's own flake |
emanix.installer.keysDir |
string or null | null |
These configure the installer ISO that nixosModules.installer builds (see
Installation). flake is the flake repository the
ISO stages at /etc/emanix/flake; a consumer points it at its own flake.
keysDir is the absolute path of a keys/ directory of host key pairs to stage
at /etc/emanix/keys, and null stages none. It must be a string naming the
working tree, not a path inside the flake source: the private halves are
gitignored, so a store-derived path stages only the .pub files and yields an
ISO that cannot install. Reading it requires nix build --impure.
5. Identity
| Option | Type | Default |
|---|---|---|
emanix.git.userName |
string | emanix user |
emanix.git.userEmail |
string | user@example.invalid |
The defaults are deliberately useless. A distribution must not ship somebody's name, and an invalid address is better than a plausible wrong one — it fails loudly the first time you push.
6. First boot — NixOS level
Both options configure one command, emanix-firstboot, which is put on the
system PATH of the installed machine. The distribution owns the convention and
the build-time check. It does not own the content: joining a mesh, pairing file
sync and cloning your flake are your decisions, so you supply the script and the
packages it needs.
6.1. emanix.firstboot.text
| Type | lines (a string; several definitions are joined with newlines) |
| Default | a stub that prints three lines and does nothing else |
The body of the emanix-firstboot script, as shell. It is built with
writeShellApplication, so it is shellchecked at build time and runs with
errexit, nounset and pipefail: a broken script fails your build, not the
first boot — the one moment nobody is watching a screen they can debug from.
The default stub prints a heading, then No first-boot steps are configured.,
then Set emanix.firstboot.text in your consuming flake. A distribution cannot
know what your first boot needs — a network to join, a configuration repository
to clone, secrets to place — and a guessed script is wrong for everyone but its
author.
emanix.firstboot = {
runtimeInputs = [ pkgs.git ];
text = ''
git --version
printf 'first boot done\n'
'';
};
6.2. emanix.firstboot.runtimeInputs
| Type | list of packages |
| Default | [ ] |
The packages whose bin/ directories are put at the front of the script's
PATH, ahead of the PATH it inherits. The default is empty on purpose: an
earlier version listed three tools while the script used one, which is the kind
of drift an unused input never announces. List what text calls, and nothing
else.
6.3. Where it applies
- You run
emanix-firstbootyourself, once, after the first boot. Nothing runs it for you. - A host the installer generated in interactive mode sets neither option, so the command exists and prints the stub message. See Installation: it is for a fleet, not for a machine the installer just invented.
- The installer ISO does not carry it. It runs on the installed system, where
your
textacts on the machine you built.
7. Environment variables
The distribution exports a small set of EMANIX_* variables. They exist so that
code which cannot read the Nix configuration — Emacs, a shell script, the
installer — can still find the facts the configuration decides.
| Variable | Set by | Read by | Meaning |
|---|---|---|---|
EMANIX |
home/zsh.nix: shell and systemd user manager |
nothing in the distribution | The Emanix checkout, from emanix.src.path |
EMANIX_THEMES_DIR |
home/zsh.nix (shell, user manager); modules/ewm.nix (EWM login) |
emanix-theme.el, for every theme file it reads and links |
The rendered theme tree, from emanix.src.themesDir. Unset, Emacs falls back to ~/dotfiles/themes, a last resort that is usually absent |
EMANIX_THEME |
home/zsh.nix (shell, user manager); modules/ewm.nix (EWM login) |
emanix-theme.el |
The host's build-time theme, from emanix.theme. Consulted once, to give a machine with no runtime state the theme its flake configures. It never overrides a theme you switched to |
EMANIX_BIN_DIR |
home/zsh.nix (shell, user manager); modules/ewm.nix (EWM login) |
The shell, which puts it first on PATH; config.el (the calendar-sync binding); emanix-ewm-slots.el (Firefox fallback); a consuming flake's own Emacs Lisp |
The consumer's script directory, from emanix.src.binDir. Unset, the Emacs readers fall back to a bare relative path that resolves nowhere |
EMANIX_DOTFILES |
home/zsh.nix (shell, user manager); modules/ewm.nix (EWM login) |
emanix-welcome.el, as the first candidate for the configuration repository |
The consumer's checkout, from emanix.src.dotfilesPath. Unset, the welcome buffer falls through to ~/flake and /etc/nixos and may report "no config repo yet" |
EMANIX_ROLE |
home/zsh.nix, shell only |
nothing in the distribution | The emanix.role label, for interactive use and for a consuming flake that chooses to branch on it |
EMANIX_REPO |
You | fresh-emanix-install |
A path to the flake the installer should use. Tried first; it is used only if it holds a flake.nix. Otherwise the installer tries its own parent directory, /etc/emanix/flake and common mount points |
EMANIX_TARGET_ROOT |
The installer's own tests | fresh-emanix-install |
Where the target system is mounted. Defaults to /mnt; nothing outside the tests sets it |
Three delivery paths exist because three kinds of process start Emacs:
- Login shell —
programs.zsh.sessionVariablesinhome/zsh.nix. - systemd user manager —
systemd.user.sessionVariablesin the same file. The non-EWM Emacs daemon is a user service that never passes through a login shell. Home Manager writes these to~/.config/environment.d/, which the manager reads at start: changing one needssystemctl --user daemon-reloadand a restart of the service, not just a rebuild. - EWM login —
environment.sessionVariablesinmodules/ewm.nix. EWM starts from the tty1 login shell, outside both paths above. Without this path,EMANIX_THEMES_DIRread as unset in the compositor's Emacs and every theme file silently missed.
EMANIX travels the first two paths and EMANIX_ROLE only the first, because
nothing in Emacs reads either.
A consuming flake may define variables of its own under the same prefix. The
reference consumer uses EMANIX_ISO_KEYS to hand its keys directory to the
impure ISO build; that is the consumer's convention, and the distribution never
reads it. Variables used only by the distribution's own checks are not listed.
8. A note on the namespace
The namespace was named after an individual until 2026-08-14. That was both awkward to adopt and wrong in principle: the namespace is the distribution's public API, and nobody setting up their own machine wants to configure it under someone else's name.
The rename was verified as a no-op by comparing derivation paths across every
host rather than by rebuilding: two were byte-identical, and the third differed
only in three user-facing error strings that now name the correct option. The
2026-08-30 rename from eminix.* to emanix.* was proven the same way, by
closure diff — the only entries that moved were the ones carrying the name.