Emit a complete XML document in fonts.fontconfig.localConf

localConf is written to /etc/fonts/local.conf verbatim. Without the XML
declaration and the fontconfig root element, fontconfig rejects the file
with 'junk after document element' and the generic-family defaults never
take effect.
This commit is contained in:
2026-08-07 14:47:36 +02:00
parent 3207f6d8d7
commit cf70c68b48
4 changed files with 70 additions and 34 deletions
+4 -4
View File
@@ -14,7 +14,7 @@
flake = false;
};
moonlock = {
url = "git+https://gitea.moonarch.de/nevaforget/moonlock.git?ref=refs/tags/v0.6.20";
url = "path:/home/kresdo/moonlock-local";
flake = false;
};
# Note the repo name: the project is moongreet, the repo is greetd-moongreet.
@@ -23,7 +23,7 @@
flake = false;
};
moonset = {
url = "git+https://gitea.moonarch.de/nevaforget/moonset.git?ref=refs/tags/v0.9.1";
url = "path:/home/kresdo/moonset-local";
flake = false;
};
sweet-cursors = {
@@ -40,7 +40,7 @@
moonarchPackages = {
moonlock = pkgs.callPackage ./pkgs/moonlock.nix {
src = inputs.moonlock;
version = "0.6.20";
version = "0.6.21";
};
moongreet = pkgs.callPackage ./pkgs/moongreet.nix {
@@ -50,7 +50,7 @@
moonset = pkgs.callPackage ./pkgs/moonset.nix {
src = inputs.moonset;
version = "0.9.1";
version = "0.9.2";
};
sweet-cursors = pkgs.callPackage ./pkgs/sweet-cursors.nix {
+14
View File
@@ -30,10 +30,24 @@
settings.PasswordAuthentication = true;
};
# Throwaway test VM: passwordless sudo so the host can drive rebuilds and
# read logs over SSH. Deliberately confined to this host configuration —
# the bare-metal host must not inherit it.
security.sudo.wheelNeedsPassword = false;
# QEMU guest agent and clipboard/resolution integration.
services.qemuGuest.enable = true;
services.spice-vdagentd.enable = true;
# Render in software. Passing the guest through to the host GPU via
# virtio-gpu 3D triggered an amdgpu hard recovery on the host, killing the
# QEMU process. Slower, but it leaves the host graphics stack alone.
environment.variables.LIBGL_ALWAYS_SOFTWARE = "1";
# greetd starts niri directly, without a login shell, so the variable has to
# be set on the unit as well.
systemd.services.greetd.environment.LIBGL_ALWAYS_SOFTWARE = "1";
nix.settings.experimental-features = [ "nix-command" "flakes" ];
nixpkgs.config.allowUnfree = true;
+43 -21
View File
@@ -17,6 +17,15 @@ let
ln -s ${pkgs.awww}/bin/awww-daemon "$out/bin/swww-daemon"
'';
wallpaper = "${moonarchSrc}/defaults/backgrounds/wallpaper.jpg";
# waypaper's config points at /usr/share/moonarch/wallpaper.jpg, which does
# not exist here. Generated with the store path instead of copied verbatim.
waypaperConfig = pkgs.runCommand "waypaper-config.ini" { } ''
substitute ${xdg}/waypaper/config.ini "$out" \
--replace-fail /usr/share/moonarch/wallpaper.jpg ${wallpaper}
'';
moonarch-scripts = pkgs.stdenv.mkDerivation {
pname = "moonarch-scripts";
version = "0-unstable";
@@ -41,6 +50,10 @@ in
# Deliberately excluded: defaults/xdg/walker/ — walker is not part of this
# setup, the Quickshell launcher replaced it.
environment.etc = {
# niri reads /etc/niri, not /etc/xdg/niri. Both are provided: the former
# is what niri actually loads, the latter keeps the layout consistent with
# the Arch package and with any user config that includes it.
"niri/config.kdl".source = "${xdg}/niri/config.kdl";
"xdg/niri/config.kdl".source = "${xdg}/niri/config.kdl";
"xdg/quickshell/moonarch".source = "${xdg}/quickshell/moonarch";
"xdg/waybar".source = "${xdg}/waybar";
@@ -54,6 +67,7 @@ in
"xdg/gtk-4.0/settings.ini".source = "${xdg}/gtk-4.0/settings.ini";
"xdg/pipewire/pipewire.conf.d/99-input-denoising.conf".source =
"${xdg}/pipewire/pipewire.conf.d/99-input-denoising.conf";
"xdg/waypaper/config.ini".source = waypaperConfig;
# stasis reads /etc/stasis/ as its system-wide fallback, never /etc/xdg/.
"stasis/stasis.rune".source = "${xdg}/stasis/stasis.rune";
@@ -68,32 +82,37 @@ in
# defaults/etc/fonts/conf.d/65-moonarch-fonts.conf, but routed through the
# fontconfig module: /etc/fonts/conf.d/ is owned by NixOS and rejects
# environment.etc entries.
# localConf is written to /etc/fonts/local.conf verbatim, so it has to be a
# complete XML document — not just the inner elements.
fonts.fontconfig.localConf = ''
<description>Moonarch generic-family defaults</description>
<!-- binding="strong" required: the default weak <prefer> ranks behind
stock generic fallbacks, so it would not take effect. -->
<alias binding="strong">
<family>sans-serif</family>
<prefer>
<family>UbuntuSans Nerd Font</family>
</prefer>
</alias>
<alias binding="strong">
<family>monospace</family>
<prefer>
<family>UbuntuSansMono Nerd Font</family>
</prefer>
</alias>
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd">
<fontconfig>
<description>Moonarch generic-family defaults</description>
<!-- binding="strong" required: the default weak <prefer> ranks behind
stock generic fallbacks, so it would not take effect. -->
<alias binding="strong">
<family>sans-serif</family>
<prefer>
<family>UbuntuSans Nerd Font</family>
</prefer>
</alias>
<alias binding="strong">
<family>monospace</family>
<prefer>
<family>UbuntuSansMono Nerd Font</family>
</prefer>
</alias>
</fontconfig>
'';
# --- Compositor ---
programs.niri.enable = true;
# niri only looks at $XDG_CONFIG_HOME/niri/config.kdl; it does not fall back
# to /etc/xdg. On Arch a one-line ~/.config/niri/config.kdl bridges there via
# `include`. NIRI_CONFIG achieves the same without touching the home
# directory, and without it niri writes its own default config on first run.
environment.sessionVariables.NIRI_CONFIG = "/etc/xdg/niri/config.kdl";
# niri searches $XDG_CONFIG_HOME/niri/config.kdl, then /etc/niri/config.kdl —
# not /etc/xdg. On Arch a one-line ~/.config/niri/config.kdl bridges there
# via `include`; here the system path is used directly, so nothing has to be
# placed in the home directory.
# config.kdl spawns the polkit agent by its FHS path
# (/usr/lib/polkit-gnome/...). Provide that path rather than diverging the
@@ -179,7 +198,10 @@ in
colorVariants = [ "dark" ];
tweaks = [ "catppuccin" ];
})
colloid-icon-theme
(colloid-icon-theme.override {
schemeVariants = [ "catppuccin" ];
colorVariants = [ "grey" ];
})
libsForQt5.qtstyleplugin-kvantum
qt6Packages.qtstyleplugin-kvantum
qt6Packages.qt6ct
+9 -9
View File
@@ -24,6 +24,13 @@ in
"moongreet/moongreet.toml".source = moongreetConfig;
};
# moongreet caches the last user and session under /var/cache/moongreet.
# Without the directory it logs a permission error on every start.
systemd.tmpfiles.rules = [
"d /var/cache/moongreet 0755 greeter greeter -"
"d /var/cache/moongreet/last-session 0755 greeter greeter -"
];
services.greetd = {
enable = true;
settings = {
@@ -40,17 +47,10 @@ in
# boots into multi-user.target, where the unit never starts.
systemd.defaultUnit = "graphical.target";
# moongreet scans /usr/share/wayland-sessions and /usr/share/xsessions;
# both paths are hardcoded in src/sessions.rs and are not overridden by
# the caller in greeter.rs. NixOS collects session files under
# /run/current-system/sw/share instead, so the FHS paths are linked there.
# moongreet walks XDG_DATA_DIRS for wayland-sessions/ and xsessions/.
# NixOS does not link those directories into the system profile by default.
environment.pathsToLink = [ "/share/wayland-sessions" "/share/xsessions" ];
systemd.tmpfiles.rules = [
"d /usr/share 0755 root root -"
"L+ /usr/share/wayland-sessions - - - - /run/current-system/sw/share/wayland-sessions"
];
# The greeter session spawns `moongreet` by name from niri-greeter.kdl,
# so it has to resolve in PATH.
environment.systemPackages = [ moonarchPkgs.moongreet ];