Files
dotfiles/system-config

system-config

A small, declarative Arch configuration managed by Decman.

Design

  • Concerns live in packages/: each concern has a native (*-repo.txt) and AUR (*-aur.txt) list.
  • Hosts live in hosts.py: a host composes package concerns and explicit system state. desktop() owns this desktop's boot, storage, NVIDIA, input, SDDM, network-policy, and user-session configuration.
  • System files live in config/system/: shared files go in common/; hardware, sleep/logind, and boot policy go in the relevant host directory.
  • State lives in manifests/: units follow the same concern and host scopes as packages.
  • Python glue lives in modules/: package and system-state adapters only.

Decman owns the listed system files and selected durable home configuration. yadm owns remaining portable dotfiles; application state, browser profiles, NetworkManager connection profiles, and project build output remain unmanaged.

System policy

  • config/system/common/pacman/pacman.conf enables only the official core, extra, and multilib repositories. No debug repository is enabled.
  • config/system/common/makepkg/makepkg.conf sets OPTIONS with !debug, so newly built packages do not produce debug packages.
  • config/system/common/locale/ owns locale generation and system locale.
  • config/system/common/keyboard/ owns console and X11 keyboard policy.
  • config/system/laptop/sleep.conf.d/ owns sleep policy; the logind drop-in remains in config/system/laptop/systemd/.
  • config/system/laptop/power/tlp.conf owns laptop power policy. TLP reads /etc/tlp.conf after drop-ins, so a whole-file policy is required here.
  • config/system/{laptop,desktop}/boot/mkinitcpio.conf owns encrypted-root and resume initramfs hooks for each host; its module rebuilds the initramfs after a change.
  • config/system/laptop/refind/ owns the laptop ESP rEFInd configuration and encrypted-root kernel options. It is intentionally laptop-only.
  • config/system/laptop/iwlwifi.conf retains the Wi-Fi 6 stability workaround; NetworkManager owns Wi-Fi power saving for battery use.
  • config/user/{common,laptop,desktop}/ owns selected active user dotfiles. Host-specific Hyprland and Noctalia variants are selected by host composition.
  • EnvyControl's generated NVIDIA blacklist and udev files are intentionally unmanaged so GPU modes can be switched outside of Decman.

Changing the debug policy does not uninstall debug packages already installed; remove those explicitly in a separate reviewed package change.

Package concerns

Scope Concerns
Shared core, wayland, fonts, development, productivity, media, research, network, services
Laptop hardware, legacy; hardware units
Desktop shared concerns, common/hardware, and a reviewable desktop/local set; host state is in config/system/desktop/

Every package must have a named purpose. Add a new concern when an existing one does not explain a package. System and user units use the same naming: manifests/common/<concern>-{system,user}.txt or manifests/laptop/<concern>-system.txt.

Commands

From the repository root, run common workflows through the ./system-config/decman wrapper, which uses fixed Decman arguments:

./system-config/decman verify
./system-config/decman dry-run
./system-config/decman apply

dry-run and apply first run verify. They invoke Decman with --no-hooks, matching the deliberately review-first direct commands below. apply changes system state; use it only after reviewing the dry run.

The wrapper locates its configuration relative to itself, so its commands run from the system-config directory. Command output and errors stream directly to the terminal. If a child command fails, the wrapper prints the failed command and returns its exit status. A missing executable returns 127, another execution error (including a permission error) returns 126, and an interrupted workflow returns 130.

sudo decman --source source.py --dry-run --no-hooks
sudo decman --source source.py --no-hooks

verify.py proves that every currently explicit package appears exactly once in the active laptop profile. The ignored dependency lists prevent Decman's orphan cleanup from removing dependencies during adoption.

After intentional package changes, regenerate and review concern lists:

./system-config/decman refresh-package-state
yadm diff -- system-config

refresh-package-state runs split-packages, refresh-orphan-guards, and verify in that order. Those individual file-changing commands are also available through the dispatcher when only one is needed.