Compare commits

...
18 Commits
Author SHA1 Message Date
nevaforget a145e5cc40 chore(flake): bump moonarch for the workspace window list in the bar 2026-10-15 18:19:03 +02:00
nevaforget 9da0457f3c feat(browsers): search.moonarch.de as default search engine, list trimmed to DuckDuckGo and Wikipedia 2026-10-14 18:49:13 +02:00
nevaforget 0e880cd3f3 feat(desktop): sshfs installed 2026-10-14 18:30:23 +02:00
nevaforget 1a385d5152 feat(desktop): tiddl installed, pinned to PR #427 for HiRes stereo 2026-10-14 18:30:23 +02:00
nevaforget 6f19047803 feat(thinkpad): sshfs installed
Flake inputs updated.
2026-10-14 18:14:48 +02:00
nevaforget c9ec8e759b fix(thinkpad): Nix fetches the DisplayLink driver itself
nixpkgs builds displaylink with requireFile, so every driver version bump
(6.2.0-30 -> 6.3.0-48) stopped the system build until the zip was put into
the store by hand. pkgs/displaylink.nix overlays requireFile with fetchurl,
taking name and hash from nixpkgs and the URL from its requireFile message.
Applied in nixosModules.moonarch, since the NixOS module reads
pkgs.displaylink directly.
2026-10-14 18:14:48 +02:00
nevaforget c3b90fba7d chore(flake): bump moonarch for the thunar daemon at login 2026-10-09 08:53:38 +02:00
nevaforget 459f6d8d82 fix(desktop): drop the swww-compat symlinks, waypaper calls awww directly
moonarch switched the waypaper backend from swww to awww (f90dd92), so the
swww/swww-daemon symlinks onto awww have nothing left to serve.

Flake inputs updated.
2026-10-07 08:11:09 +02:00
nevaforget 95c65d29dc fix(browsers): PDFs open in Firefox, not Chromium 2026-10-02 23:56:05 +02:00
nevaforget 4d2fbef15a fix(browsers): browser.nova.enabled off in Firefox 2026-10-02 15:20:34 +02:00
nevaforget 932896856b perf(boot): the boot menu waits one second, not five
systemd-boot stood at its default 5 second timeout on every boot, 5.9s of
loader in systemd-analyze on the desktop. One second still shows the menu
without a key held down, which through the desktop's KVM may not register in
time, so an older generation stays selectable when an update does not boot.

obs-studio, discord and vesktop on the desktop. Flake inputs updated.
2026-10-02 15:20:34 +02:00
nevaforget d16070a4a7 fix(desktop): xdg-open goes through the portal, so FHS sandboxes get Firefox
acli auth login opened Chromium. buildFHSEnv binds only an allowlist of /etc
entries into its bubblewrap sandbox, and /etc/xdg is not on it, so the
mimeapps.list from xdg.mime is invisible there and xdg-open takes the first
http handler in mimeinfo.cache. The same holds for Steam and AppImages.
xdg.portal.xdgOpenUsePortal hands the URL to the OpenURI portal, which
resolves it on the host (NixOS/nixpkgs#160923).

acli and kubectl on the ThinkPad. Flake inputs updated.
2026-09-30 19:25:09 +02:00
nevaforget 1077a745c3 fix(desktop): amdgpu in the initrd, so Plymouth draws at native resolution
Without it the passphrase prompt came up on the framebuffer the firmware left
behind: one monitor, its resolution, switching over only once amdgpu loaded.
The ThinkPad gets the same setting from nixos-hardware's amd profile.
2026-09-28 15:58:53 +02:00
nevaforget 153bae47ea perf(network): nothing waits for a routable address at boot
NetworkManager-wait-online holds network-online.target until a connection is
routable, and multi-user.target sits behind it through docker.service, the only
active unit that pulls the target in.
2026-09-28 15:42:05 +02:00
nevaforget dddf236ace feat(theme): a splash theme of our own, images in viewnior, a stop timeout for stasis
The Catppuccin splash showed the NixOS logo and the loading animation and
nothing else. The NixOS plymouth module links boot.plymouth.logo into every
theme directory named catppuccin-<flavour>, and the two-step module has no
alignment key for that header image, so its distance from the animation is not
the theme's to set. A theme under a name of its own is outside that loop.
moonarch-plymouth joins as a flake input; pkgs/moonarch-plymouth.nix rewrites
the descriptor's FHS ImageDir to the store path.

Images opened in Chromium although viewnior has been installed since 3e40a70:
no mimeapps.list named image/* at all, so xdg-open took the first candidate
from mimeinfo.cache. xdg.mime points gif, jpeg, png and webp at
viewnior.desktop. webp needs addedAssociations besides, which viewnior.desktop
does not declare, and webp-pixbuf-loader, without which gdk-pixbuf cannot
decode it.

stasis does not answer SIGTERM as part of the session teardown, and the default
90 seconds left the whole user manager waiting on it: niri received its own
SIGTERM only once stasis had been killed, 88 seconds in the journal.
TimeoutStopSec = 5. What it holds is an idle timer, so nothing is lost when it
goes down hard.

glab on the ThinkPad.
2026-09-28 14:52:05 +02:00
nevaforget de70d1794e fix(theme): Kvantum's theme where Qt5 looks for it, qt5ct as the platform theme 2026-09-28 08:23:48 +02:00
nevaforget e7f76aaf03 feat(theme): a themed boot splash, and amdgpu back in the ThinkPad's initrd 2026-09-28 08:23:48 +02:00
nevaforget 3d5ac11aa2 feat(browsers): drop the thumbnail from the tab hover preview 2026-09-28 08:16:38 +02:00
14 changed files with 565 additions and 39 deletions

No files matched your search

+255
View File
@@ -1,5 +1,260 @@
# Decisions
## 2026-10-07 – Nix fetches the DisplayLink driver itself
- **Who**: Dominik, ClaudeCode
- **Why**: nixpkgs builds `displaylink` with `requireFile`. Because Synaptics
forbids redistribution, nixpkgs does not download the archive itself
(nixpkgs 48291b066d, NixOS/nixpkgs#28279). The 6.2.0-30 -> 6.3.0-48 bump
therefore stopped the system build until the zip was put into the store by
hand. The earlier comment claimed this was needed once per machine, but it is
needed for every driver version.
- **Tradeoffs**:
- Considered pinning URL and hash in the flake, but that means maintenance on
every version.
- Considered keeping the manual download.
- Considered a nixpkgs PR switching to `fetchurl`, which runs into the
licence argument.
- Considered a different dock, but foreign docks are used on the road.
- Chosen: read the URL with a regex from the `requireFile` message, where
nixpkgs keeps it current. This depends on the message wording. If the line
disappears, evaluation stops with an error.
- **How**:
- `pkgs/displaylink.nix` is an overlay that replaces `requireFile` with
`fetchurl`. It takes name and hash from nixpkgs.
- It is applied for all hosts in `nixosModules.moonarch`, because the NixOS
module reads `pkgs.displaylink` directly.
## 2026-09-30 – xdg-open goes through the portal, so FHS sandboxes get Firefox
- **Who**: Dominik, ClaudeCode
- **Why**: `acli auth login` opened Chromium. acli is a `buildFHSEnv` wrapper,
which binds only an allowlist of `/etc` entries into its bubblewrap sandbox;
`/etc/xdg` is not on it, so the `mimeapps.list` from `xdg.mime` is invisible
there and `xdg-mime` falls back to `mimeinfo.cache`, which yields
`chromium-browser.desktop`. Reproduced on the host by querying with
`XDG_CONFIG_DIRS` pointed away from `/etc/xdg`. Affects every FHS env
(Steam, AppImages), not only acli.
- **Tradeoffs**: Considered binding `/etc/xdg` into acli via `extraBwrapArgs`
(fixes one package only), linking a second copy of `mimeapps.list` into
`/run/current-system/sw/etc/xdg` (a self-made workaround), stripping
Chromium's http claim (fixes the browser only), and `xdg-settings` (manual,
per user and machine). All rejected in favour of the option nixpkgs added
for exactly this (NixOS/nixpkgs#160923).
- **How**: `xdg.portal.xdgOpenUsePortal = true` in `modules/desktop.nix`. It
sets `NIXOS_XDG_OPEN_USE_PORTAL=1`; nixpkgs' patched `xdg-open` then hands
the URL to the OpenURI portal, which resolves it on the host with the host's
`mimeapps.list`. Verified: the thinkpad system builds and carries the
variable. The runtime check (`acli auth login` opening Firefox) needs a
switch and a new login, since it is a session variable.
## 2026-09-28 – Nothing waits for a routable address at boot
- **Who**: Dominik, ClaudeCode
- **Why**: The ThinkPad took 54.7s to boot. Two of those posts are not the
configuration's to shorten: 14.7s of firmware, and 14.2s inside the initrd
where the machine waits for the LUKS passphrase to be typed — the prompt
stands at 4.97s after kernel start, `systemd-cryptsetup` runs at 19.20s.
What is left is 14.4s of userspace, and `NetworkManager-wait-online.service`
holds 10.6s of it: it keeps `network-online.target` until a connection is
routable, and `multi-user.target` sits behind that target through
`docker.service`. Of the two units that pull the target in, `docker.service`
is the only active one; `fwupd-refresh.service` is not running.
- **Tradeoffs**: The first approach was to detach `docker.service` from the
target instead, which leaves the wait in place for anything else that may
want it. It needs `lib.mkForce` on both `after` and `wants`, so the upstream
unit's dependency list is copied into this flake and drifts silently on the
next nixpkgs bump. Disabling the wait is one line and nothing to keep in
sync. What it costs: docker starts without a guarantee that an address is
already routable.
- **How**: `systemd.services.NetworkManager-wait-online.enable = false` in
`modules/network.nix`, with the measurement in the comment beside it.
Plymouth was not touched: `plymouth-quit-wait.service` shows 2.4s in
`systemd-analyze blame` but does not appear in the critical chain.
## 2026-09-28 – Images open in the viewer, not in the browser
- **Who**: Dominik, ClaudeCode
- **Why**: Images opened in Chromium although `viewnior` has been installed
since `3e40a70`. No `mimeapps.list` named `image/*` at all, so `xdg-open` took
the first candidate from `mimeinfo.cache` — `chromium-browser.desktop`, ahead
of `viewnior.desktop` by name.
- **Tradeoffs**: Declared in `modules/desktop.nix` next to the viewer, not
beside the Firefox types in `modules/browsers.nix`; both modules add to the
same attribute set and the keys do not overlap.
- **How**: `xdg.mime.defaultApplications` for gif, jpeg, png and webp on
`viewnior.desktop`, plus `addedAssociations` for webp, which
`viewnior.desktop` does not declare, and
`programs.gdk-pixbuf.modulePackages = [ pkgs.webp-pixbuf-loader ]`, without
which gdk-pixbuf cannot decode it.
## 2026-09-28 – The splash in our own colours, and what Plymouth would not give
- **Who**: Dominik, ClaudeCode
- **Why**: The first boot on the new theme showed four things: the keyboard
layout label at the password prompt was too large, it should sit further
down, the entry field was pixelated, and the palette was the upstream blue
rather than the Catppuccin lavender the rest of the system runs on.
- **Tradeoffs**: Three of the four are files the theme ships, so they are
drawn here and committed — not generated in the package recipe. That keeps
the recipe untouched and puts every asset where it can be looked at. The
cost is that `keymap-render.png` now has to match Plymouth's offset table
by hand; the README says so, and the band from the original upload had
failed exactly that way.
The fourth is not a file. Plymouth places the layout indicator at
`y = dialog_bottom + …` (`two-step/plugin.c`) and has no alignment key for
it, so it cannot be moved without moving the entry field with it. Making
the images taller and putting their content at the bottom would work in
principle, but reaching the screen's lower edge from the middle needs over
a thousand pixels of empty image. Dropped.
- **How**: `keymap-render.png` redrawn at 2304×24 — one layout, `de`, at the
offset the table gives it (2253, 51 wide) — against 26537×50 upstream;
`keyboard.png` scaled to match. `entry.png` redrawn at its original
305×75 with smooth edges. Both frame series, 81 `animation-*` and 51
`progress-*`, moved to lavender with `-modulate 130,125,105`, which lands
on `#b0c1ee` against the target `#b4befe`. Background and progress bar in
the descriptor follow `#1e1e2e`, `#313244`, `#b4befe`.
## 2026-09-28 – A stop timeout for stasis
- **Who**: Dominik, ClaudeCode
- **Why**: Every reboot hung for a minute and a half. The journal names it:
`stasis.service: State 'stop-sigterm' timed out. Killing.`, 88 seconds after
the last system service went down, and niri received its own SIGTERM only
once stasis had been killed — the whole user manager was waiting on that one
unit. Stopped by hand with `systemctl --user stop stasis` it exits in zero
seconds, so the unit is not at fault; as part of the session teardown it
does not answer.
- **Tradeoffs**: The cause sits in the program. stasis registers SIGTERM
through `signal_hook` and honours it in normal operation, so fixing it means
changing somebody else's Rust daemon and carrying a patch. A short stop
timeout treats the symptom instead — acceptable here because what stasis
holds is an idle timer, and nothing is lost when it goes down hard. The
alternative, leaving the default 90 seconds, costs that time on every
reboot.
- **How**: `TimeoutStopSec = 5` in the unit in `modules/services.nix`, with
the measurement recorded beside it so the number is not mistaken for a
guess.
## 2026-09-28 – A splash theme of our own, and a flake input after all
- **Who**: Dominik, ClaudeCode
- **Why**: The Catppuccin splash showed the NixOS logo and the loading
animation and nothing else, the two of them touching. The cause is not the
theme's configuration: `nixos/modules/system/boot/plymouth.nix` links
`boot.plymouth.logo` into every theme directory named `catppuccin-<flavour>`
as `header-image.png`, and the `two-step` module that theme runs on has
alignment keys for `watermark`, `title`, `dialog` and the progress bar —
none for the header image, whose distance from the animation the module
decides on its own. The theme itself contributes only the throbber frames:
it sets `WatermarkVerticalAlignment` but ships no `watermark.png`, so those
lines take no effect.
- **Tradeoffs**: (1) **A padded logo** — the same PNG with transparent space
below it. One line, but the spacing then lives inside an image file and
imagemagick joins the build. (2) **A derived theme under another name**,
with the logo going in as `watermark.png`. Uses the slot Plymouth intends
for a logo, but builds a package only to sidestep a loop over theme names.
(3) **Patching that loop in nixpkgs**, where the cause sits, which needs an
overridden module and a changed theme value on top. (4) **A theme of our
own**, which removes the question entirely: the loop matches only Catppuccin
and Spinner names, so every other theme is left alone. Chosen.
This reverses the reasoning of the 2026-09-25 entry below, which took
nixpkgs' `catppuccin-plymouth` precisely to avoid a new input. The theme
wanted here is not in nixpkgs, and carrying it as a source repo is the same
shape the flake already uses for Betterfox and the cursors.
- **How**: `gitea.moonarch.de/nevaforget/moonarch-plymouth-theme`, derived
from tobilinuxer's *Linux Distro Logos - macOS Boot Style*
(opendesktop.org/p/2106821) under the X11 license, which permits the change;
the copyright notice travels with it in `LICENSE`. Renamed to `moonarch` in
the descriptor's filename, its `Name=` entry and its `ImageDir`, the images
untouched. It runs on `two-step` as well, but brings a progress bar and a
138-frame animation and no watermark, so nothing is drawn that it did not
bring itself. `pkgs/moonarch-plymouth.nix` rewrites the descriptor's FHS
`ImageDir` to the store path, the way nixpkgs' own theme packages do.
## 2026-09-25 – amdgpu back in the ThinkPad's initrd, for Plymouth's sake
- **Who**: Dominik, ClaudeCode
- **Why**: With the splash enabled, Plymouth came up on eDP-1 in the mode the
firmware had left behind, stretched over a panel with four times the pixels.
The boot log has both halves: `simpledrm` owns the framebuffer while the
initrd runs, and amdgpu only takes eDP-1 twenty-five seconds later, on the way
into the real root. Plymouth draws in the initrd, so it never saw the panel's
own resolution. The cause was `hardware.amdgpu.initrd.enable = false`, set on
this host to keep the LUKS passphrase prompt in the firmware's large text mode
rather than at 3840x2400, where the 8x16 console font is a fifth as tall.
- **Tradeoffs**: The two wants are opposed — the console text is readable in the
firmware mode, Plymouth is only sharp in the native one. Plymouth draws the
passphrase prompt itself and scales with the panel, so as long as it runs the
text mode buys nothing; with `plymouth.enable=0` on the kernel line, or a
Plymouth that fails, the tiny prompt is back. That case is rare and reachable,
the splash is every boot.
- **How**: The line is gone rather than set to `true`: nixos-hardware's amd
profile already sets `lib.mkDefault true`, and a build without it comes out at
the same store path. A comment in its place records what dropping it costs, so
the reasoning is not lost with the line.
## 2026-09-25 – A boot splash, themed from nixpkgs rather than a new flake input
- **Who**: Dominik, ClaudeCode
- **Why**: The boot was the one part of the system still showing stock text,
the LUKS passphrase prompt among it. With systemd in the initrd, Plymouth
draws that prompt itself, so the splash covers the whole way from firmware to
the greeter rather than stopping at the disk.
- **Tradeoffs**: (1) **catppuccin/nix** offers `catppuccin.plymouth.enable`,
but this flake does not have that input, and taking it on for a boot splash
means carrying a second theming source next to the packages already used
here. (2) **nixpkgs' `catppuccin-plymouth`** is the same upstream theme as a
plain package, with a `variant` argument and no new input. Chosen. (3) The
cost either way is that boot messages are hidden, so a stalled boot shows a
still image first; `plymouth.enable=0` on the kernel line takes it back
without rebuilding, and the previous generation is in the boot menu.
- **How**: `boot.plymouth` in `modules/theme.nix`, beside the other theme
packages, on flavour Mocha like them. `quiet` was already on the kernel
command line and the module adds `splash` on its own, so the kernel
parameters needed no change.
## 2026-09-25 – Kvantum's theme where Qt5 looks for it, and one platform theme for both Qt versions
- **Who**: Dominik, ClaudeCode
- **Why**: VLC came up in a style that is not Catppuccin. Two causes, measured
at the running process with `strace` and `QT_DEBUG_PLUGINS`.
The style plugin was never the problem: Kvantum's Qt5 build loads, and it
reads `/etc/xdg/Kvantum/kvantum.kvconfig`, so it knows the theme's name. It
then asks for the theme in four places — `~/.config/Kvantum`, `~/.themes`,
`~/.local/share/themes` and its own store path — and in none of them is it
installed. `/run/current-system/sw/share/Kvantum`, where it is, is never
looked at: the patch that teaches Kvantum `XDG_DATA_DIRS` no longer reaches
the Qt5 build after an upstream change (NixOS/nixpkgs#355277, still open,
from tsujan/Kvantum@6a4053a). Not finding its theme, Kvantum draws its
built-in default.
Behind that, a second one: `QT_QPA_PLATFORMTHEME` was `qt6ct`, and Qt5 reads
that variable too. A Qt5 client finds only the Qt6 plugin, cannot load it,
and ends up with no platform theme at all — no icon theme, no fonts, stock
dialogs. This was never specific to VLC; it held for every Qt5 client.
- **Tradeoffs**: (1) **Overriding the Qt5 plugin package** so its own
`share/Kvantum` carries the theme would keep everything system-wide and leave
no state in the home directory, but it is a construction nobody else runs,
and it rebuilds the plugin locally. (2) **A wrapper around VLC** setting
`gtk3` as its platform theme would need no new package and no new config, but
it fixes one application where the gap is general. (3) The published
solutions for the Qt5 case — the nixpkgs issue's thread and catppuccin/nix —
all place the theme under `$XDG_CONFIG_HOME/Kvantum`, and pair it with the
qt5ct/qt6ct combination that nixpkgs itself ships as
`qt.platformTheme = "qt5ct"`. Chosen for being the trodden path.
- **How**: A `systemd.user.tmpfiles` rule links
`~/.config/Kvantum/catppuccin-mocha-lavender` to the theme in the system
profile, `L+` like the cursor rule beside it so it follows the profile
instead of freezing at one store path. `QT_QPA_PLATFORMTHEME` is now `qt5ct`,
which each Qt version answers with the plugin built for it;
`libsForQt5.qt5ct` is installed alongside `qt6ct`, and
`/etc/xdg/qt5ct/qt5ct.conf` carries the same style, icon theme and dialog
setting as `qt6ct.conf`.
## 2026-09-25 – One portal config, and the file dialog on the GTK backend
- **Who**: Dominik, ClaudeCode
+2 -1
View File
@@ -20,13 +20,14 @@ files therefore serves every system that pulls it in.
flake.nix Inputs and outputs
pkgs/ Build recipes
sweet-cursors.nix cursor theme
moonarch-plymouth.nix boot splash theme
moonarch-scripts.nix battery and camera helpers
betterfox.nix Firefox preference set
modules/
user.nix moonarch.user option, set per host
disk.nix partitioning: GPT, optional LUKS2, btrfs subvolumes
desktop.nix compositor, /etc deployment, portals, the rest of the packages
theme.nix GTK, Qt, Kvantum, cursors, fonts
theme.nix GTK, Qt, Kvantum, Plymouth, cursors, fonts
browsers.nix Firefox with its preconfiguration, Chromium, handler
shell.nix zsh and the command line tools
lock.nix gtklock and its PAM stack
Generated
+28 -11
View File
@@ -40,11 +40,11 @@
"moonarch": {
"flake": false,
"locked": {
"lastModified": 1790177314,
"narHash": "sha256-2YTKIvK8gtoDf+zE0QyLyoWT8KQW82O0WQ4pWkHgX6g=",
"lastModified": 1792080970,
"narHash": "sha256-0clf//IhVjtzauSLdzziV2PJ4FWmXegrKxQm8EcHCz8=",
"ref": "refs/heads/main",
"rev": "2774d0947de08376651c05fb1b68907c7e3ffd61",
"revCount": 188,
"rev": "4398ecb4db0453ec01d3c107230881d0c094716e",
"revCount": 193,
"type": "git",
"url": "https://gitea.moonarch.de/nevaforget/moonarch.git"
},
@@ -53,16 +53,32 @@
"url": "https://gitea.moonarch.de/nevaforget/moonarch.git"
}
},
"moonarch-plymouth": {
"flake": false,
"locked": {
"lastModified": 1790599371,
"narHash": "sha256-4eudA/FgaCTVO+dluJcTfEBsPFOiEThKu0V4UA8YPjw=",
"ref": "refs/heads/main",
"rev": "5307ddd8056e8403355bf9b3d68b6fbd2c57d718",
"revCount": 9,
"type": "git",
"url": "https://gitea.moonarch.de/nevaforget/moonarch-plymouth-theme.git"
},
"original": {
"type": "git",
"url": "https://gitea.moonarch.de/nevaforget/moonarch-plymouth-theme.git"
}
},
"nixos-hardware": {
"inputs": {
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1789978172,
"narHash": "sha256-FIRXajv1pPZ+l6On6ekkmcQ6le0Zi0ncRUoR3nB0vKA=",
"lastModified": 1791721963,
"narHash": "sha256-BYhx89XJltnRyQeuDKHVL5eSqbbfAcOKuDts7QRsrxQ=",
"owner": "NixOS",
"repo": "nixos-hardware",
"rev": "9ebcb7766700d7e006d9505247bd7ce0426f4232",
"rev": "60a624466c08787ee8303393b7d4752d1826f14f",
"type": "github"
},
"original": {
@@ -86,11 +102,11 @@
},
"nixpkgs_2": {
"locked": {
"lastModified": 1790046670,
"narHash": "sha256-MYiI+CzL0tuWgRPjGsKCDHqYs2T3OzMlMQWOYWG0qso=",
"lastModified": 1791734076,
"narHash": "sha256-i5qk1kLiit98rRbh1AXmWBNT9QXC/y4l5Wk/u5EdpDQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "6774f7bc253789b113a4f39285dc0fa100abeacc",
"rev": "7fd4004d0511991fff3a0524856a9be09e28c5f0",
"type": "github"
},
"original": {
@@ -105,6 +121,7 @@
"betterfox": "betterfox",
"disko": "disko",
"moonarch": "moonarch",
"moonarch-plymouth": "moonarch-plymouth",
"nixos-hardware": "nixos-hardware",
"nixpkgs": "nixpkgs_2",
"sweet-cursors": "sweet-cursors"
@@ -116,7 +133,7 @@
"lastModified": 1777359446,
"narHash": "sha256-DqFak+NN9bxBSTWD+6luEjSIQo1FAkw5HeJRCQvnBuk=",
"ref": "refs/heads/main",
"rev": "74ce3688e55318dec0af8e25f376e613243ed6c3",
"rev": "21c0f0655443650a48dc444a251afae1e0cc8dc8",
"revCount": 2,
"type": "git",
"url": "https://gitea.moonarch.de/nevaforget/Sweet-cursors.git"
+12
View File
@@ -32,6 +32,10 @@
url = "git+https://gitea.moonarch.de/nevaforget/Sweet-cursors.git";
flake = false;
};
moonarch-plymouth = {
url = "git+https://gitea.moonarch.de/nevaforget/moonarch-plymouth-theme.git";
flake = false;
};
};
outputs = { self, nixpkgs, ... }@inputs:
@@ -50,6 +54,11 @@
version = "0-unstable";
};
moonarch-plymouth = pkgs.callPackage ./pkgs/moonarch-plymouth.nix {
src = inputs.moonarch-plymouth;
version = "0-unstable";
};
moonarch-scripts = pkgs.callPackage ./pkgs/moonarch-scripts.nix {
src = inputs.moonarch;
};
@@ -116,6 +125,9 @@
./modules/zed.nix
];
# Lets Nix fetch the DisplayLink driver itself, see pkgs/displaylink.nix.
nixpkgs.overlays = [ (import ./pkgs/displaylink.nix) ];
_module.args = {
moonarchSrc = inputs.moonarch;
moonarchPkgs = moonarchPackages;
+17 -4
View File
@@ -28,6 +28,11 @@
boot.loader.systemd-boot.enable = true;
boot.loader.systemd-boot.configurationLimit = 10;
# The menu stood for the default 5 seconds on every boot — 5.9s of loader in
# `systemd-analyze`. One second still leaves it reachable without a key held
# down, which through the KVM may not register in time; an older generation
# stays selectable when an update does not boot.
boot.loader.timeout = 1;
boot.loader.efi.canTouchEfiVariables = true;
boot.kernelPackages = pkgs.linuxPackages_zen;
boot.kernelParams = [ "quiet" ];
@@ -95,9 +100,11 @@
# microcode in its BIOS.
hardware.cpu.amd.updateMicrocode = true;
# The GPU is AMD, so amdgpu and Mesa cover it and there is nothing to declare:
# the kernel module is in the default initrd and Mesa comes with the graphics
# stack. An NVIDIA card would have needed videoDrivers and hardware.nvidia.
# The GPU is AMD, so Mesa comes with the graphics stack. An NVIDIA card would
# have needed videoDrivers and hardware.nvidia. amdgpu does not reach the
# initrd on its own, and without it Plymouth draws on the firmware framebuffer:
# one monitor, its resolution.
hardware.amdgpu.initrd.enable = true;
services.fstrim.enable = true;
@@ -125,7 +132,13 @@
# the pipewire group only, and this account is not one.
security.rtkit.enable = true;
environment.systemPackages = [ pkgs.bitwig-studio ];
environment.systemPackages = with pkgs; [
bitwig-studio
obs-studio
discord
vesktop
(callPackage ../../pkgs/tiddl.nix { })
];
nix.settings.experimental-features = [ "nix-command" "flakes" ];
nixpkgs.config.allowUnfree = true;
+21 -9
View File
@@ -18,16 +18,24 @@
# 3840x2400 panel that is 480 columns of unreadable text. "0" selects the
# standard 80x25 mode, which every firmware has to provide.
boot.loader.systemd-boot.consoleMode = "0";
# The default leaves the menu standing for 5 seconds on every boot. One second
# still shows it without a key held down, so an older generation stays
# selectable when an update does not boot.
boot.loader.timeout = 1;
boot.loader.efi.canTouchEfiVariables = true;
boot.kernelPackages = pkgs.linuxPackages_zen;
boot.kernelParams = [ "quiet" ];
# nixos-hardware puts amdgpu into the initrd, so the panel is already at its
# native 3840x2400 when LUKS asks for the passphrase and the 8x16 console font
# is a fifth of the height it has on the firmware framebuffer. Without the
# driver the prompt is drawn in the mode the firmware left behind and the
# driver loads a moment later, on the way into the real root.
hardware.amdgpu.initrd.enable = false;
# No hardware.amdgpu.initrd.enable here: nixos-hardware's amd profile already
# sets it, so the panel is at its native 3840x2400 by the time LUKS asks for
# the passphrase. Plymouth draws in the initrd and needs that — without the
# driver it gets the mode the firmware left behind, scaled over a panel with
# four times the pixels.
#
# Setting it to false, as this host did before, buys back the console text
# underneath: at 3840x2400 the 8x16 font is a fifth of the height it has on
# the firmware framebuffer, so a passphrase prompt that arrives as text —
# with Plymouth off, or failed — is barely readable.
networking.hostName = "thinkpad";
networking.networkmanager.enable = true;
@@ -99,6 +107,10 @@
pnpm
uv
python3
glab
acli
kubectl
sshfs
];
# The nixos-hardware profile only sets hardware.cpu.amd.updateMicrocode as a
@@ -114,9 +126,9 @@
# displaylink.nix, which pulls in evdi, the service and the udev rules; the
# option is read on its own and does not start an X server.
#
# pkgs.displaylink is unfree and fetched with requireFile, because Synaptics
# forbids redistribution. The archive has to be placed in the store by hand
# once per machine, see DECISIONS.md.
# pkgs.displaylink is unfree and nixpkgs fetches it with requireFile, because
# Synaptics forbids redistribution. The overlay in pkgs/displaylink.nix lets
# Nix download the archive itself, for every new driver version.
services.xserver.videoDrivers = [ "displaylink" "modesetting" ];
services.fstrim.enable = true;
+34 -2
View File
@@ -29,6 +29,8 @@ in
preferencesStatus = "default";
preferences = {
"general.autoScroll" = true;
"browser.tabs.hoverPreview.showThumbnails" = false;
"browser.nova.enabled" = false;
# Only the offer to translate. Translating by hand from the context menu
# keeps working.
@@ -92,7 +94,35 @@ in
ImproveSuggest = false;
};
SearchEngines.Default = "DuckDuckGo";
# The own search instance, added and made the default. Default only sets
# where Firefox starts; switching in the search settings keeps working.
# No IconURL: the favicon sits behind the Authelia login, so Firefox
# could not fetch it when it applies the policy.
SearchEngines = {
Add = [
{
Name = "moonarch";
URLTemplate = "https://search.moonarch.de/search?q={searchTerms}";
Method = "GET";
Alias = "@m";
}
];
Default = "moonarch";
# Everything Firefox 157 ships for German locale and region, except
# DuckDuckGo and Wikipedia (de). Hidden from the list, not uninstalled;
# names as the search settings show them, a typo is silently ignored.
Remove = [
"Bing"
"eBay"
"Ecosia"
"Google"
"LEO Eng-Deu"
"Perplexity"
"Reddit"
"Startpage"
"YouTube"
];
};
OfferToSaveLogins = false;
# Startup and the home button both land on a blank page. StartPage
@@ -128,12 +158,14 @@ in
# Both browsers claim x-scheme-handler/http in their desktop entries, and
# with two candidates xdg-open picks by whatever order it finds them in.
# These four types are exactly what firefox.desktop declares.
# The first four types are exactly what firefox.desktop declares; PDFs go to
# Firefox's built-in viewer as well.
xdg.mime.defaultApplications = {
"text/html" = "firefox.desktop";
"application/xhtml+xml" = "firefox.desktop";
"x-scheme-handler/http" = "firefox.desktop";
"x-scheme-handler/https" = "firefox.desktop";
"application/pdf" = "firefox.desktop";
};
environment.systemPackages = [
+21 -8
View File
@@ -5,13 +5,6 @@
let
xdg = "${moonarchSrc}/defaults/xdg";
# waypaper calls `swww`/`swww-daemon`, but the maintained successor ships as
# `awww`. The symlinks keep the shared config working unchanged.
swww-compat = pkgs.runCommand "swww-compat" { } ''
mkdir -p "$out/bin"
ln -s ${pkgs.awww}/bin/awww "$out/bin/swww"
ln -s ${pkgs.awww}/bin/awww-daemon "$out/bin/swww-daemon"
'';
wallpaper = "${moonarchSrc}/defaults/backgrounds/wallpaper.jpg";
@@ -118,6 +111,14 @@ in
# awake. programs.niri leaves this interface unassigned, so stating it here
# does not collide with the module's definition.
config.niri."org.freedesktop.impl.portal.Inhibit" = "none";
# buildFHSEnv sandboxes (acli, Steam, AppImages) bind only an allowlist of
# /etc entries, and /etc/xdg is not on it, so an xdg-open inside them never
# sees the xdg.mime defaults and takes the first handler in mimeinfo.cache —
# Chromium for http. With this set, nixpkgs' xdg-open hands the URL to the
# OpenURI portal instead, which resolves it on the host. See
# NixOS/nixpkgs#160923.
xdgOpenUsePortal = true;
};
# The file dialog every portal client opens — Firefox's save dialog among
@@ -173,7 +174,6 @@ in
wlsunset
brightnessctl
awww
swww-compat
waypaper
# Terminal
@@ -191,8 +191,21 @@ in
stasis
claude-code
galculator
sshfs
];
xdg.mime = {
defaultApplications = {
"image/gif" = "viewnior.desktop";
"image/jpeg" = "viewnior.desktop";
"image/png" = "viewnior.desktop";
"image/webp" = "viewnior.desktop";
};
addedAssociations."image/webp" = "viewnior.desktop";
};
programs.gdk-pixbuf.modulePackages = [ pkgs.webp-pixbuf-loader ];
# Polkit agent for privilege prompts inside the session.
security.polkit.enable = true;
# The setuid pkexec wrapper is opt-in and off by default. Without it pkexec
+7
View File
@@ -11,6 +11,13 @@
# is what hands the keyring password to the connection.
networking.networkmanager.plugins = [ pkgs.networkmanager-openvpn ];
# NetworkManager-wait-online holds network-online.target until a connection is
# routable, and multi-user.target waits behind it — measured at 10.6s in the
# journal, against 14.4s for the whole of userspace. Of the units that pull the
# target in, docker.service is the only active one; fwupd-refresh.service is
# not running.
systemd.services.NetworkManager-wait-online.enable = false;
hardware.bluetooth.enable = true;
services.blueman.enable = true;
+6
View File
@@ -272,6 +272,12 @@ in
ExecReload = "${lib.getExe pkgs.stasis} reload";
Restart = "on-failure";
RestartSec = 2;
# Stopped by hand it exits at once; stopped as part of the session it
# does not answer SIGTERM, and the default 90 seconds left the whole
# user manager waiting on it — niri received its own SIGTERM only once
# stasis had been killed. Measured at 88s in the journal. What it holds
# is an idle timer, so nothing is lost when it goes down hard.
TimeoutStopSec = 5;
IPAddressDeny = "any";
ProtectProc = "invisible";
ProcSubset = "pid";
+49 -4
View File
@@ -1,4 +1,4 @@
# ABOUTME: GTK, Qt, Kvantum, cursors and fonts — the look, in one place.
# ABOUTME: GTK, Qt, Kvantum, Plymouth, cursors and fonts — the look, in one place.
# ABOUTME: Same theme derivations the greeter uses, so the two cannot drift apart.
{ pkgs, moonarchSrc, moonarchPkgs, moonarchThemes, ... }:
@@ -34,17 +34,36 @@ let
#
# Verified under strace: a Qt6 client opens the theme's .kvconfig straight
# out of the package's store path. The patch only takes in the Qt6 build
# (NixOS/nixpkgs#355277) — a Qt5 client, here only VLC, falls back to the
# default style.
# (NixOS/nixpkgs#355277) — a Qt5 client searches four roots instead:
# ~/.config/Kvantum, ~/.themes, ~/.local/share/themes and its own store path.
# The tmpfiles rule further down puts the theme in the first of them, which is
# where the published solutions for this put it.
kvantumTheme = pkgs.catppuccin-kvantum.override {
accent = "lavender";
variant = "mocha";
};
# The theme name as both the package directory and the .kvconfig entry spell
# it, so the link target below cannot drift from what Kvantum looks up.
kvantumThemeName = "catppuccin-mocha-lavender";
in
{
environment.etc = {
"xdg/Kvantum/kvantum.kvconfig".source = "${xdg}/Kvantum/kvantum.kvconfig";
"xdg/qt6ct/qt6ct.conf".source = "${xdg}/qt6ct/qt6ct.conf";
# No counterpart in moonarch's defaults: Arch ships qt5ct's own config, and
# this file only has to exist because Qt5 and Qt6 read one variable between
# them, see QT_QPA_PLATFORMTHEME below. Same settings as qt6ct.conf.
"xdg/qt5ct/qt5ct.conf".text = ''
# ABOUTME: System qt5ct config — Qt5 icon theme + Kvantum style, matching qt6ct.conf.
# ABOUTME: Deployed to /etc/xdg/qt5ct/qt5ct.conf; a user copy in ~/.config/qt5ct wins by XDG precedence.
[Appearance]
style=kvantum
icon_theme=Colloid-Grey-Catppuccin-Dark
standard_dialogs=default
'';
"xdg/gtk-3.0/settings.ini".source = gtkSettings "3.0";
"xdg/gtk-4.0/settings.ini".source = gtkSettings "4.0";
};
@@ -90,6 +109,20 @@ in
}];
};
# The boot splash. `quiet` is already on the kernel command line and the module
# puts `splash` there itself, so nothing else has to change for it to show.
# With systemd in the initrd, which this configuration uses, systemd asks for
# the LUKS passphrase and Plymouth draws that prompt; the script initrd instead
# shows it as text before the splash comes up.
# The theme carries a name of its own, outside the catppuccin-<flavour> set
# that the NixOS plymouth module links its logo into, so the splash shows
# what the theme brings and nothing besides.
boot.plymouth = {
enable = true;
theme = "moonarch";
themePackages = [ moonarchPkgs.moonarch-plymouth ];
};
# Qt applications are wrapped, so each one looks for plugins in its own
# closure and never finds a style installed alongside it — which is why VLC
# kept coming up in the stock Qt style. Enabling this puts the profile's Qt5
@@ -108,7 +141,12 @@ in
# everything started from its launcher — never sees them, and Qt applications
# come up unstyled. Set here they travel through /etc/profile into
# niri-session's import-environment, and from there into the user manager.
environment.sessionVariables.QT_QPA_PLATFORMTHEME = "qt6ct";
# qt5ct, not qt6ct: Qt5 and Qt6 both read this one variable, and a Qt5 client
# asked for "qt6ct" finds only a Qt6 plugin it cannot load, so it comes up
# with no platform theme at all — no icon theme, no fonts, stock dialogs.
# Under "qt5ct" each version loads the plugin built for it; that pairing is
# what nixpkgs ships as qt.platformTheme "qt5ct", which installs both.
environment.sessionVariables.QT_QPA_PLATFORMTHEME = "qt5ct";
environment.sessionVariables.QT_STYLE_OVERRIDE = "kvantum";
# Same gap, cursors: niri's cursor block reaches xwayland-satellite, so X11
@@ -132,6 +170,12 @@ in
# link on every activation, unlike the 'C' rules elsewhere, which keeps it
# following the theme instead of freezing at today's one.
"L+ %h/.icons/default - - - - /run/current-system/sw/share/icons/Sweet-cursors"
# Kvantum's Qt5 build never looks at XDG_DATA_DIRS, so the theme installed
# system-wide is invisible to it; ~/.config/Kvantum is the first place it
# does look. 'L+' for the same reason as the rule above: the link follows
# the system profile instead of freezing at one store path.
"L+ %h/.config/Kvantum/${kvantumThemeName} - - - - /run/current-system/sw/share/Kvantum/${kvantumThemeName}"
];
environment.systemPackages = with pkgs; [
@@ -143,6 +187,7 @@ in
libsForQt5.qtstyleplugin-kvantum
qt6Packages.qtstyleplugin-kvantum
kvantumTheme
libsForQt5.qt5ct
qt6Packages.qt6ct
qt6.qt5compat
+26
View File
@@ -0,0 +1,26 @@
# ABOUTME: Overlay that lets Nix fetch the DisplayLink driver itself.
# ABOUTME: Swaps nixpkgs' requireFile for fetchurl, with name, hash and URL taken from nixpkgs.
# nixpkgs builds displaylink with requireFile, so every new driver version
# stops the build until the archive is put into the store by hand. nixpkgs keeps
# name, hash and download URL current, but the URL only appears inside the
# requireFile message ("nix-prefetch-url --name <name> <url>"). Reading it from
# there means nothing in this flake has to be maintained per version. Should
# nixpkgs drop that line, evaluation stops here instead of falling back to the
# manual step.
final: prev: {
displaylink = prev.displaylink.override {
requireFile =
args:
let
url = builtins.match ".*nix-prefetch-url --name [^ ]+ (https://[^[:space:]]+).*" args.message;
in
if url == null then
throw "displaylink: the nixpkgs requireFile message has no direct-download URL any more, see pkgs/displaylink.nix"
else
final.fetchurl {
inherit (args) name hash;
url = builtins.head url;
};
};
}
+37
View File
@@ -0,0 +1,37 @@
# ABOUTME: Nix build recipe for the Moonarch Plymouth boot splash.
# ABOUTME: Rewrites the descriptor's FHS ImageDir to wherever the theme lands.
{ lib, stdenvNoCC, src, version }:
stdenvNoCC.mkDerivation {
pname = "moonarch-plymouth";
inherit version src;
dontBuild = true;
dontConfigure = true;
# The theme's own name, which boot.plymouth.theme has to match. It stays
# outside the catppuccin-<flavour> set that the NixOS plymouth module links
# its logo into, so nothing is added to the splash that the theme did not
# bring itself.
installPhase = ''
runHook preInstall
dir="$out/share/plymouth/themes/moonarch"
install -dm755 "$dir"
cp -r images "$dir/images"
# ImageDir in the repo names an FHS path; plymouthd reads it verbatim.
substitute moonarch.plymouth "$dir/moonarch.plymouth" \
--replace-fail /usr/share/plymouth/themes/moonarch "$dir"
runHook postInstall
'';
meta = {
description = "Moonarch Plymouth boot splash";
homepage = "https://gitea.moonarch.de/nevaforget/moonarch-plymouth-theme";
license = lib.licenses.x11;
platforms = lib.platforms.linux;
};
}
+50
View File
@@ -0,0 +1,50 @@
# ABOUTME: tiddl, a CLI downloader for Tidal up to HiRes FLAC (24-bit/192 kHz).
# ABOUTME: Not in nixpkgs; pinned to the branch of upstream PR #427.
{ lib
, python3Packages
, fetchFromGitHub
, ffmpeg
}:
python3Packages.buildPythonApplication {
pname = "tiddl";
version = "3.4.4-unstable-pr427";
pyproject = true;
# Release 3.4.4 asks Tidal for playback with a single client profile, which
# hands back the Dolby Atmos stream for any track that has one, and the
# default Atmos filter then skips it: whole albums download nothing, and MAX
# never arrives. PR #427 (oskvr37/tiddl) requests stereo through a Hi-Res
# profile instead, from the same login. Back to a release tag once it is
# merged.
src = fetchFromGitHub {
owner = "ssupt";
repo = "tiddl";
rev = "a7739f736b9b46f06e33e7b8a4eb350ec840050a"; # feat/single-auth-capability-sessions
hash = "sha256-1wUxVaDv6PH2IZ3W6aezjswI1CosTqmx2xmiUdPKKP0=";
};
build-system = with python3Packages; [ setuptools wheel ];
dependencies = with python3Packages; [
aiofiles
aiohttp
m3u8
mutagen
pydantic
requests
requests-cache
typer
];
# HiRes arrives as DASH segments; tiddl calls ffmpeg to extract the FLAC.
makeWrapperArgs = [ "--prefix PATH : ${lib.makeBinPath [ ffmpeg ]}" ];
meta = {
description = "Download Tidal tracks up to HiRes FLAC";
homepage = "https://github.com/oskvr37/tiddl";
license = lib.licenses.asl20;
mainProgram = "tiddl";
};
}