# Workarounds, Overrides & Temporary Fixes

This document tracks all known workarounds, patches, and temporary overrides in this flake.
Each entry includes the file location, reason, and whether it is still required.

**Status legend:**
- `ACTIVE` — still required, upstream fix not available
- `REDUNDANT` — upstream has fixed the issue; this override can be removed
- `UPSTREAM PENDING` — waiting on an upstream PR/issue
- `INTENTIONAL` — permanent design decision, not a workaround

---

## Overlays (upstream package overrides)

### `overlays/cosmic-settings-daemon/default.nix`
**Status:** `ACTIVE — UPSTREAM PENDING`

`cosmic-settings-daemon 1.0.8` has a buggy `Cargo.lock` that references
`https://github.com/pop-os/dbus-settings-bindings` at two different commits
(`3b86984` for `cosmic-dbus-a11y`/`locale1`/`upower_dbus`, and `0fa672f8`
for the `cosmic-settings-daemon` subcrate). `cargoSetupHook` (used by
`fetchCargoVendor`/`cargoHash`) rejects this: *"Sources are not allowed to be
defined multiple times."*

The fix overrides `cargoDeps` with `rustPlatform.importCargoLock`, which uses
a different vendoring strategy that handles multiple commits from the same repo.

**Removal condition:** When nixpkgs updates `cosmic-settings-daemon` past 1.0.8
with a fixed `Cargo.lock`, or applies `cargoLock` in its own package definition.

---

### `overlays/cosmic-applets/default.nix`
**Status:** `ACTIVE — UPSTREAM PENDING`

`cosmic-applets 1.0.8` has the same class of bug: its `Cargo.lock` references
`https://github.com/pop-os/cosmic-settings` at two different commits (`b46a55d`
for `cosmic-pipewire` and `cosmic-settings-sound-subscription`, and `55b502d`
for `cosmic-settings-a11y-manager-subscription` and several other crates).
`cargoSetupHook` rejects this with the same "Sources are not allowed to be
defined multiple times" error.

Same fix as `cosmic-settings-daemon`: overrides `cargoDeps` with
`rustPlatform.importCargoLock`.

**Removal condition:** When nixpkgs updates `cosmic-applets` past 1.0.8 with a
fixed `Cargo.lock`, or applies `cargoLock` in its own package definition.

---

### ~~`overlays/waybar/default.nix`~~ — REMOVED
**Status:** `REMOVED`

Previously added `-Dexperimental=true` to waybar's meson flags. nixpkgs now
includes `-Dexperimental=true` in its waybar definition, making the overlay
redundant. Removed.

---

### `overlays/radios/default.nix`
**Status:** `ACTIVE` (protective — needed after next `flake update`)

`radios` requires `pycountry>=24.0.0,<25.0.0` (PEP 440: `^24.0.0`). The
current locked nixpkgs has `pycountry 24.6.1` (in range), but nixpkgs HEAD
has already bumped `pycountry` to `26.2.16`, which will break `radios` after
the next `flake update`. The overlay applies `pythonRelaxDepsHook` to loosen
the upper bound.

**Removal condition:** When the upstream `radios` package (`frenck/python-radios`)
or nixpkgs relaxes the pycountry version constraint.

---

### `overlays/redis/default.nix`
**Status:** `INTENTIONAL`

Replaces `redis` with `valkey` (the Redis community fork) globally. This is a
deliberate preference for the open-source fork over the Redis 7.x+ license change.

---

### `overlays/stable/default.nix`
**Status:** `INTENTIONAL`

Injects `pkgs.stable` as an attribute pointing to the stable nixpkgs channel,
so modules can selectively pull in stable packages. Not a workaround.

---

## Flake Inputs (forks and custom branches)

### `nixpkgs-otbr` — `github:mrene/nixpkgs/openthread-border-router`
**File:** `flake.nix:8`
**Status:** `ACTIVE — UPSTREAM PENDING`

`openthread-border-router` is not yet packaged in nixpkgs-unstable. A community
member's nixpkgs fork provides the package, used by
`modules/nixos/homeassistant/services/thread/default.nix`.

The fork is ~52,000 commits behind `nixos-unstable`, so it is pulled
only via `pkgs.callPackage` from the fork's path, not as a full channel overlay.

**Removal condition:** When `openthread-border-router` is merged into nixpkgs.
Check: https://github.com/NixOS/nixpkgs/pulls?q=openthread-border-router

---

### `snowfall-lib` — `github:mjallen18/snowfall-lib`
**File:** `flake.nix:26`
**Status:** `INTENTIONAL`

Personal fork of `snowfallorg/lib` with 46 commits ahead of upstream, including:
- `fix: pass namespace argument to overlays`
- `fix: pass namespace argument to home-manager modules`
- `feat: support same username across multiple targets`
- `feat: enable per-channel configuration and fix pkgs selection`
- Performance improvements and additional features

These are custom changes required by this flake's structure that have not been
upstreamed.

---

### `steam-rom-manager` — `github:mjallen18/nix-steam-rom-manager`
**File:** `flake.nix:41`
**Status:** `INTENTIONAL`

Personal fork/packaging of nix-steam-rom-manager. The upstream
(`nix-community/nix-steam-rom-manager`) may or may not exist; this is a
maintained fork.

---

### Commented-out: `nvmd/disko` fork
**File:** `flake.nix:59-61`
**Status:** `REDUNDANT` (already disabled)

```nix
# the fork is needed for partition attributes support
# url = "github:nvmd/disko/gpt-attrs";
```

A community fork of disko with GPT partition attribute support was previously
used but has since been switched back to upstream `nix-community/disko`. The
comment can be cleaned up if the feature is no longer needed.

---

## Build Fixes & postPatch

### `packages/edk2-basetools/default.nix` — OpenSSL vendoring FIXME
**File:** `packages/edk2-basetools/default.nix:50-52`
**Status:** `UPSTREAM PENDING` (verify PR reference)

```nix
# FIXME: unvendor OpenSSL again once upstream updates
# to a compatible version.
# Upstream PR: https://github.com/tianocore/edk2/pull/10946
```

The comment references tianocore/edk2 PR #10946, but that PR's title is
*"update to openssl 3.5.1"* (now merged), not an unvendoring PR. The FIXME
comment may be referencing the wrong PR number or the issue may have evolved.
The edk2 build still vendor-patches OpenSSL compatibility; this should be
re-evaluated against the current edk2 upstream.

**Action:** Verify whether the OpenSSL vendoring is still needed with current
edk2, and update or remove the FIXME comment.

---

### `packages/bcachefs/default.nix` — Tests disabled
**File:** `packages/bcachefs/default.nix:100`
**Status:** `ACTIVE`

```nix
# FIXME: Try enabling this once the default linux kernel is at least 6.7
doCheck = false; # needs bcachefs module loaded on builder
```

Tests require a live bcachefs kernel module in the build sandbox, which is
not available. The comment mentions kernel ≥ 6.7, which is now the case
(nixpkgs is on 6.12+), but the underlying sandbox limitation still applies —
the build sandbox cannot load kernel modules regardless of kernel version.

**Action:** The `6.7` condition is now met but irrelevant; update the comment
to reflect that the real blocker is sandbox access to kernel modules.

---

### `packages/raspberrypi/linux-rpi/default.nix` — Failed kernel attempts
**File:** `packages/raspberrypi/linux-rpi/default.nix:25-43`
**Status:** `ACTIVE` (informational)

Four newer RPi kernel versions (6.15.11 through 6.19.0-rc5) are commented out
because they "fail for various reasons." The active version is pinned to an
older working commit.

**Action:** Periodically attempt to enable a newer kernel tag. The comments
serve as a history of failed attempts.

---

### `packages/raspberrypi/linux-rpi/default.nix` — DTB aliasing hack
**File:** `packages/raspberrypi/linux-rpi/default.nix:110-148`
**Status:** `ACTIVE`

```nix
# Make copies of the DTBs named after the upstream names so that U-Boot finds them.
# This is ugly as heck, but I don't know a better solution so far.
```

RPi's kernel ships DTBs with non-standard names (e.g. `bcm2708-rpi-zero-w.dtb`);
U-Boot expects canonical upstream names (e.g. `bcm2835-rpi-zero.dtb`). DTBs
are duplicated in `postFixup`.

---

### `packages/homeassistant/ha-mail-and-packages/default.nix` — Hardcoded paths
**File:** `packages/homeassistant/ha-mail-and-packages/default.nix:25-37`
**Status:** `ACTIVE`

The upstream HA integration hard-codes paths relative to its source directory,
which breaks in the Nix store. `postPatch` rewrites them to
`/var/lib/homeassistant/images/`.

---

### `packages/homeassistant/ha-wyzeapi/default.nix` — Version pin relaxation
**File:** `packages/homeassistant/ha-wyzeapi/default.nix:24-27`
**Status:** `ACTIVE`

Relaxes the minimum `wyzeapy` version pin from `0.5.28` to `0.5.27` to match
the version packaged in this flake.

---

## Raspberry Pi — Structural Overrides

### `modules/nixos/hardware/raspberry-pi/default.nix` — jemalloc 16K pages
**File:** `modules/nixos/hardware/raspberry-pi/default.nix:458-470`
**Status:** `ACTIVE` (structural)

```nix
# https://github.com/nvmd/nixos-raspberrypi/issues/64
jemalloc = prev.jemalloc.overrideAttrs (old: {
  configureFlags = ... ++ [ "${pageSizeFlag}=14" ];
});
```

RPi5 uses 16K memory pages (2^14). jemalloc must be compiled with
`--with-lg-page=14`, otherwise it will use incorrect page size assumptions
and likely crash or corrupt memory.

**References:** https://github.com/nvmd/nixos-raspberrypi/issues/64

---

### `systems/aarch64-linux/pi5/boot.nix` — 16K page kernel
**File:** `systems/aarch64-linux/pi5/boot.nix:22-35`
**Status:** `ACTIVE` (structural)

Forces `CONFIG_ARM64_16K_PAGES=y` in the kernel config via `linux_6_19.override`.
`ignoreConfigErrors = true` is required because some kernel config options are
unavailable and would otherwise fail validation.

---

### `packages/raspberrypi/ffmpeg-rpi/default.nix` — RPi hardware codec ffmpeg
**File:** `packages/raspberrypi/ffmpeg-rpi/default.nix`
**Status:** `ACTIVE` (structural)

Custom ffmpeg build from `jc-kynesim/rpi-ffmpeg` fork with RPi hardware codec
support (`--enable-v4l2-request`, `--enable-sand`, etc.). Tests disabled
(`doCheck = false`) because the `imgutils` test fails on this build.

---

## systemd Service Overrides

### `systems/x86_64-linux/matt-nixos/default.nix` — networkd-wait-online
**File:** `systems/x86_64-linux/matt-nixos/default.nix:78`
**Status:** `INTENTIONAL`

```nix
systemd.services.systemd-networkd-wait-online.enable = lib.mkForce false;
```

The `systemd-networkd-wait-online` service times out on this desktop,
blocking boot. Standard workaround for desktop systems that don't require
all interfaces to be up before proceeding.

---

### `systems/x86_64-linux/allyx/default.nix` — Jovian NixOS conflicts
**File:** `systems/x86_64-linux/allyx/default.nix:121-123`
**Status:** `ACTIVE`

```nix
systemd-networkd-wait-online.enable = lib.mkForce false;
power-profiles-daemon.enable = lib.mkForce false;
inputplumber.enable = lib.mkForce false;
```

On the ASUS ROG Ally X with Jovian NixOS and `handheld-daemon`:
- `power-profiles-daemon` conflicts with `handheld-daemon`'s power management
- `inputplumber` conflicts with `handheld-daemon`'s input handling
- `systemd-networkd-wait-online` times out as on matt-nixos

---

### `modules/nixos/services/crowdsec/default.nix` — DynamicUser conflict
**File:** `modules/nixos/services/crowdsec/default.nix:133-143`
**Status:** `ACTIVE — UPSTREAM PENDING`

```nix
systemd.services.crowdsec.serviceConfig.DynamicUser = lib.mkForce false;
systemd.services.crowdsec-firewall-bouncer.serviceConfig.DynamicUser = lib.mkForce false;
systemd.services.crowdsec-firewall-bouncer-register.serviceConfig.DynamicUser = lib.mkForce false;
```

The upstream NixOS crowdsec module uses `ReadWritePaths` (not `StateDirectory`)
on the main `crowdsec.service`, expecting `/var/lib/crowdsec` to be a real
directory. However, `crowdsec-firewall-bouncer-register` declares
`StateDirectory=crowdsec` with `DynamicUser=true`, which conflicts — it tries
to create `/var/lib/private/crowdsec` and symlink `/var/lib/crowdsec` to it,
but the directory already exists as a real path. Disabling `DynamicUser` on
all three services resolves the conflict by using the real `crowdsec` user.

Additionally, `crowdsec-firewall-bouncer-register` calls `cscli` without `-c`,
expecting `/etc/crowdsec/config.yaml` to exist, but the upstream NixOS module
uses a Nix store path via `-c` and never creates that file. The module works
around this by extracting the store path at eval time.

**Removal condition:** When the NixOS crowdsec module is fixed upstream to
handle state directory ownership consistently.

---

## Incomplete / TODO Items

These are not workarounds but known incomplete configurations:

| File | Line | Description |
|------|------|-------------|
| `systems/x86_64-linux/jallen-nas/sops.nix` | 89, 113 | Collabora and MariaDB secrets not configured |
| `systems/x86_64-linux/jallen-nas/apps.nix` | 47 | Authentik environment secrets file not wired up |
| `modules/nixos/services/sparky-fitness/default.nix` | — | ~~DB passwords not yet moved to SOPS~~ — resolved; secrets now via `mkSopsEnvFile`; run `sops secrets/nas-secrets.yaml` to add real values for `jallen-nas/sparky-fitness/{db-password,api-encryption-key,auth-secret}` |
| `modules/nixos/services/your-spotify/default.nix` | 36 | Spotify API keys not yet moved to SOPS |
| `modules/nixos/services/booklore/default.nix` | 28 | Database password not yet a SOPS secret |
| `packages/raspberrypi/udev-rules/default.nix` | 33 | `15-i2c-modprobe.rules` disabled; `i2cprobe` script not ported |
| `modules/nixos/homeassistant/services/homeassistant/default.nix` | 214 | `roborock` integration marked broken |

---

## Kernel Boot Parameters

### `systems/x86_64-linux/matt-nixos/boot.nix` — NVMe power saving
**File:** `systems/x86_64-linux/matt-nixos/boot.nix:46-48`
**Status:** `ACTIVE`

```nix
"nvme_core.default_ps_max_latency_us=0"
"pcie_aspm=off"
```

NVMe SSD power-saving states cause latency/stability issues on this machine.
Disabling ASPM and NVMe power states is a standard workaround for affected
hardware.

---

### `systems/aarch64-linux/macbook-pro-nixos/boot.nix` — Fan control
**File:** `systems/aarch64-linux/macbook-pro-nixos/boot.nix:28`
**Status:** `ACTIVE`

```nix
"melt_my_mac=1"
```

Undocumented Asahi Linux kernel parameter that enables fan control on Apple
Silicon Macs. The name is intentional (set by the Asahi kernel developers).
