Verification scope: the nixpkgs
nixos-unstablemodules and upstream documentation consulted in October 2026. Group lists, package counts, and service defaults change with the revision; when deploying, use the nixpkgs and Home Manager source pinned by your project as the authority. No build, activation, or desktop runtime tests were performed for this article.
The problem#
Where does GNOME store its settings, such as themes, wallpaper, peripherals, and Night Light? Will a rebuild lose them? How can they become declarative and reproducible?
Storage mechanism: dconf#
GNOME stores its configuration in dconf, a key-value database whose physical file is ~/.config/dconf/user (binary). The dconf and gsettings command-line tools access it.
dconf dump /exports the key-value pairs explicitly saved in the user database; this is not the same as all effective settings, nor does it guarantee that every value differs from its schema defaultdconf read /path/to/keyreads a single value- The GNOME Settings interface changes this database
The key property: it is runtime state, outside /nix/store; rebuilds preserve it, but it is not tracked in git.
Three levels of precedence#
Three layers determine a GSettings key’s value, from lowest to highest priority:
1. schema 默认值(包自带的 XML schema)
2. GSettings override(NixOS 生成的"系统默认",如壁纸、favorite-apps)
3. 用户 dconf 数据库值 ← 优先级最高What this means NixOS’s
extraGSettingsOverridessets layer 2 defaults: a new machine automatically gets these settings after a rebuild, but existing values in the current user’s dconf database take precedence and are not reverted. These are therefore "persistent defaults" rather than "enforced locks".
Two declarative interfaces on the NixOS side#
services.desktopManager.gnome.extraGSettingsOverrides (NixOS layer, overridable defaults)
services.desktopManager.gnome.extraGSettingsOverridePackages = [
pkgs.gsettings-desktop-schemas
pkgs.gnome-settings-daemon
];
services.desktopManager.gnome.extraGSettingsOverrides = ''
[org.gnome.desktop.interface]
show-battery-percentage=true
clock-show-weekday=true
[org.gnome.settings-daemon.plugins.color]
night-light-enabled=true
night-light-schedule-from=22.0
'';home-manager dconf.settings (home layer, written back at activation)
# home/theme.nix 的用法
dconf.settings = {
"org/gnome/desktop/interface" = {
color-scheme = "prefer-dark";
gtk-theme = "adw-gtk3-dark";
};
};The distinction matters
extraGSettingsOverrides: defaults; subsequent manual changes by the user are not overwritten (permissive)- home-manager
dconf.settings: writes the declared keys during every Home Manager activation, restoring declared values over the user’s manual changes (write-back at activation)Use Home Manager for themes that should be written back at activation, and extraGSettingsOverrides for default preferences that users may adjust. Home Manager’s write-back is not a continuous lock: users can still make changes afterward, and the next activation reapplies the declaration. To actually restrict user changes, use dconf’s system profile/locks mechanism.
A method for persistence#
Turn manually adjusted settings into declarations:
dconf dump / > user-settings.ini # 导出用户数据库显式保存的值- Select the settings the user deliberately changed, such as themes, peripherals, and behavioral preferences
- Distinguish application state from stable preferences: window dimensions are usually not migrated; whether to migrate keyboard layouts, shortcuts, or the application grid layout depends on the migration’s purpose, so do not exclude them categorically
- Check whether another declaration already manages the setting, such as themes in theme.nix; avoid duplication
- Use gsettings to find the corresponding schema ID, key name, and type. Convert dconf path groups into schema groups, then put them in
extraGSettingsOverrides(overridable defaults); include the packages that provide those schemas
Choosing the right level
- Appearance/interaction preferences → extraGSettingsOverrides (reproducible defaults)
- Reapply at every activation → Home Manager dconf.settings
- Actually restrict user changes → dconf system profile/locks
- Internal application state → decide according to the migration goal; avoid putting all frequently changing runtime state into declarations
Related articles#
- Declarative GNOME management — the GNOME module layer
- NixOS declaration and runtime layers — dconf is a typical example of the runtime layer
Export formats and checking effective values#
A dconf dump / section such as [org/gnome/desktop/interface] is a database path, whereas a GSettings override uses [org.gnome.desktop.interface], a schema ID. Schemas may use different paths or be relocatable, so you cannot mechanically replace every slash with a dot. Use gsettings list-schemas, gsettings list-keys, gsettings describe, and gsettings range to establish the mapping.
If an existing user value masks a new default, back up first, then use gsettings reset <SCHEMA_ID> <KEY> to clear the user value for that specific key. Do not reset the entire dconf database just to apply one theme. After building, you still need activation/a new login and a check with gsettings get to verify the effective value.
References & further reading
- Nixpkgs GNOME module ↗
- Nixpkgs GNOME documentation ↗
- GLib GSettings and vendor overrides ↗
- Home Manager dconf module ↗
- Managing GNOME dconf defaults ↗
Adapted from technical notes. Examples use generic names.