Rebase to flake parts #10

This commit is contained in:
2026-05-15 00:24:13 -03:00
parent f02606902c
commit fba5a7a2aa
24 changed files with 565 additions and 83 deletions
Generated
+4 -4
View File
@@ -23,11 +23,11 @@
]
},
"locked": {
"lastModified": 1776686554,
"narHash": "sha256-TaJnAbwSnfJ9My8Df8o6MKswuc3dq6qGF+zTZF906Eg=",
"lastModified": 1778241768,
"narHash": "sha256-vyKpTnkTD0GId4PZUg21oBdWZhuHl/c3YgO5Ruehq2M=",
"ref": "refs/heads/main",
"rev": "c1a35069ee41595f8549fb529d29647565a30e75",
"revCount": 99,
"rev": "735b1cc776a8d7e26763bf1ac121866b326bd98f",
"revCount": 104,
"type": "git",
"url": "https://git.chiasson.cloud/Olivier/cursor-nixos-flake"
},
@@ -752,6 +752,14 @@ in {
"trailing_diamond": "\ue0b4",
"type": "session"
},
{
"type": "text",
"style": "diamond",
"background": "#3A456E",
"foreground": "#ffbebc",
"template": "\u007B\u007B if .Env.IN_NIX_SHELL \u007D\u007Din nix-shell\u007B\u007B end \u007D\u007D",
"trailing_diamond": "\ue0b4"
},
{
"background": "#3A456E",
"foreground": "#bc93ff",
@@ -1,9 +1,15 @@
# Export large Jellyfin media trees to nix-server. Local path must already exist
# (e.g. /mnt/test/jellyfin/{movies,tv}). On nix-server this is mounted at /mnt/nixdesk-jellyfin.
# NFS exports from nixdesk (14900k) to nix-server (192.168.2.238):
# - /mnt/test/jellyfin → nix-server /mnt/nixdesk-jellyfin (Jellyfin bulk libraries)
# - /mnt/media → nix-server /mnt/media (Btrfs MediaLibrary disk; see media-disk.nix)
#
# After deploy: ensure Jellyfin can read files over NFS — typical fix:
# chmod -R a+rX /mnt/test/jellyfin
{ ... }:
# NTFS on nixdesk uses uid=olivier + gid=nfsmedia (990); dirs here are olivier:nfsmedia 2775 so
# local writes and NFS all_squash (anonuid=olivier, anongid=990) get rwx via owner or group.
#
# Legacy trees may still need a one-time `chgrp -R nfsmedia` / `chmod -R g+rwX` on deep folders.
{ config, pkgs, ... }:
let
olivierUid = config.users.users.olivier.uid or 1000;
in
{
# Avoid UID/GID mismatches across machines: map all NFS writes from nix-server to a single
# local system user/group on this server.
@@ -14,10 +20,32 @@
group = "nfsmedia";
};
systemd.tmpfiles.settings."14900k-jellyfin-media-dirs" = {
"/mnt/test/jellyfin"."d" = { mode = "2775"; user = "nfsmedia"; group = "nfsmedia"; };
"/mnt/test/jellyfin/movies"."d" = { mode = "2775"; user = "nfsmedia"; group = "nfsmedia"; };
"/mnt/test/jellyfin/tv"."d" = { mode = "2775"; user = "nfsmedia"; group = "nfsmedia"; };
# olivier: owner for local use; nfsmedia: group matches NTFS gid=990 and NFS all_squash (990).
systemd.tmpfiles.settings."14900k-nfs-export-paths" = {
"/mnt/test"."d" = { mode = "2775"; user = "olivier"; group = "nfsmedia"; };
"/mnt/test/jellyfin"."d" = { mode = "2775"; user = "olivier"; group = "nfsmedia"; };
"/mnt/test/jellyfin/movies"."d" = { mode = "2775"; user = "olivier"; group = "nfsmedia"; };
"/mnt/test/jellyfin/tv"."d" = { mode = "2775"; user = "olivier"; group = "nfsmedia"; };
"/mnt/media"."d" = { mode = "2775"; user = "olivier"; group = "nfsmedia"; };
"/mnt/media/Movies"."d" = { mode = "2775"; user = "olivier"; group = "nfsmedia"; };
"/mnt/media/TV"."d" = { mode = "2775"; user = "olivier"; group = "nfsmedia"; };
"/mnt/media/Videos"."d" = { mode = "2775"; user = "olivier"; group = "nfsmedia"; };
};
# After exports are up, ensure group nfsmedia can write throughout library roots (idempotent;
# scoped to library folders only — not whole disks). Runs on each `nixos-rebuild switch`.
system.activationScripts.nfs-export-group-write = {
deps = [ "specialfs" ];
text = ''
for d in \
/mnt/media/TV /mnt/media/Movies /mnt/media/Videos \
/mnt/test/jellyfin/tv /mnt/test/jellyfin/movies
do
[ -d "$d" ] || continue
${pkgs.acl}/bin/setfacl -R -m g:nfsmedia:rwx "$d" 2>/dev/null || true
${pkgs.acl}/bin/setfacl -R -d -m g:nfsmedia:rwx "$d" 2>/dev/null || true
done
'';
};
# Fixed ports so the firewall can allow NFS v3 helpers (see networking.firewall below).
@@ -26,9 +54,12 @@
mountdPort = 4000;
lockdPort = 4001;
statdPort = 4002;
# fsid= stabilizes file handles across server reboots/remounts of this tree (avoids client ESTALE).
# fsid= unique per export tree (avoids client ESTALE when multiple paths are exported).
# Squash nix-server clients to olivier:nfsmedia so Jellyfin can write .nfo/posters into
# existing olivier-owned library folders (990-only squash was "other" r-x on typical 755 trees).
exports = ''
/mnt/test/jellyfin 192.168.2.238(rw,sync,no_subtree_check,crossmnt,root_squash,all_squash,anonuid=990,anongid=990,fsid=1)
/mnt/test/jellyfin 192.168.2.238(rw,sync,no_subtree_check,crossmnt,root_squash,all_squash,anonuid=${toString olivierUid},anongid=990,fsid=1)
/mnt/media 192.168.2.238(rw,sync,no_subtree_check,crossmnt,root_squash,all_squash,anonuid=${toString olivierUid},anongid=990,fsid=2)
'';
};
@@ -0,0 +1,34 @@
# Extra local disks. Declared here, not in hardware.nix (hardware.nix is generated).
{ config, lib, ... }:
let
# Stable UID so NTFS `uid=` matches `users.users.olivier` (override if your account is not 1000).
olivierUid = config.users.users.olivier.uid or 1000;
in
{
users.users.olivier.uid = lib.mkDefault 1000;
fileSystems."/mnt/media" = {
device = "/dev/disk/by-uuid/17d8a981-db3b-415e-a0f7-7dbc519e04ab";
fsType = "btrfs";
options = [
"subvol=@"
"compress=zstd"
"noatime"
];
};
# LABEL="Deep Storage Unit". Owner olivier, group nfsmedia (990) so:
# - local logins write as user 1000 (owner rwx);
# - NFS (all_squash → uid/gid 990) matches group 990 → rwx (see jellyfin-nfs-export).
fileSystems."/mnt/test" = {
device = "/dev/disk/by-uuid/BC12E55E12E51DE0";
fsType = "ntfs-3g";
options = [
"rw"
"force"
"uid=${toString olivierUid}"
"gid=990"
"umask=0002"
];
};
}
+8
View File
@@ -17,6 +17,7 @@
./_private/peripherals.nix
# ./_private/printing-epson.nix
./_private/displays.nix
./_private/media-disk.nix
./_private/jellyfin-nfs-export.nix
];
@@ -108,8 +109,13 @@ services.cloudflare-warp.enable = true;
# Native install (avoid flatpak sandbox issues for QSV/VAAPI).
handbrake
qbittorrent
# Diagnostics
libva-utils # vainfo
vlc
element-desktop
thunderbird
];
@@ -136,6 +142,7 @@ services.cloudflare-warp.enable = true;
self.homeManagerModules.wisdomAppsDiscord
self.homeManagerModules.wisdomAppsSpotify
self.homeManagerModules.wisdomAppsLocalsend
self.homeManagerModules.wisdomAppsSpacedrive
self.homeManagerModules.wisdomAppsPokeclicker
self.homeManagerModules.wisdomDesktopScreenshot
self.homeManagerModules.wisdomDesktopGtkQtTheming
@@ -171,6 +178,7 @@ services.cloudflare-warp.enable = true;
spotify.enable = true;
spotify.openDiscoveryFirewall = true;
localsend.enable = true;
spacedrive.enable = true;
pokeclicker.enable = true;
};
+6 -3
View File
@@ -7,9 +7,12 @@
powerManagement.enable = true;
# ─────────────────────── logind: lid & power button ───────────────────────
# Closing the lid suspends, even on AC — Duet 3 is a tablet, treat it like one.
# Short press on power: suspend (matches ChromeOS/iOS); long press: poweroff.
# The DMS bar power menu is the way to reboot / shut down explicitly.
# Tablet form factor: lid close = suspend (even on AC), short power-press = suspend, long
# power-press = poweroff. Niri's own power-key handler must stay disabled — see the
# `input.disable-power-key-handling` flag in `_private/touch-tablet.nix` — otherwise niri's
# `block` inhibitor on `handle-power-key` pre-empts logind and turns the wake-from-suspend
# press (which the EC re-delivers as KEY_POWER) into an immediate re-suspend loop
# (https://github.com/niri-wm/niri/issues/2233).
services.logind.settings.Login = {
HandleLidSwitch = "suspend";
HandleLidSwitchExternalPower = "suspend";
+34 -17
View File
@@ -1,17 +1,10 @@
# Host-only: ideapad tablet ergonomics — touchscreen calibration, IIO sensors, virtual keyboard,
# and per-session helper daemons (tablet-mode toggle + auto-rotation via iio-sensor-proxy) for both
# Niri and Hyprland.
# touch-controller resume fix, and per-session helper daemons (tablet-mode toggle + auto-rotation
# via iio-sensor-proxy) for both Niri and Hyprland. Lives at the NixOS layer because the hardware
# bits are system-wide; the per-compositor autostart hooks are gated on `chiasson.desktop.<wm>.enable`
# so they stay dormant if you pick the other session at the greeter.
#
# Why all of this lives at the *NixOS* layer (not the home-manager catalog under wisdom/):
# - The hardware bits (`hardware.sensor.iio.enable`, the udev calibration matrix) are system-wide
# and tied to this exact device, so they belong with the host module.
# - The compositor helpers run via session-specific autostart hooks (Niri `spawn-at-startup`,
# Hyprland `exec-once`); the wiring is gated on the matching `chiasson.desktop.<wm>.enable`,
# so picking a different session at the greeter just leaves them dormant.
#
# Two compositor flavours of each daemon:
# - Hyprland (CW transforms via `hyprctl`) — original; matches the old NixOS-New setup.
# - Niri (CCW transforms via `niri msg output`) — needed because Niri is the V2 default.
# Hyprland uses CW transforms via `hyprctl`; Niri uses CCW transforms via `niri msg output`.
{
config,
lib,
@@ -268,15 +261,33 @@ in
# ─────────────────────── Hardware ───────────────────────
hardware.sensor.iio.enable = true;
# Touchscreen calibration — solved empirically with `niri msg output DSI-1 transform normal`
# in the natural kb-down pose. The panel's touch hardware reports raw coordinates already
# aligned with the panel-native frame (HW(visual_top_left) = (0,0), etc.), so identity is
# correct. `niri input.touch.map-to-output = "DSI-1"` then handles per-orientation rotation
# on top — never re-tune this matrix per orientation; rotate the *output* instead.
# Touchscreen calibration — identity matrix is correct: hardware coordinates are already aligned
# with the panel-native frame, and per-orientation rotation is handled by `niri msg output`,
# not by re-tuning this matrix. Rotate the *output*, never this matrix.
services.udev.extraRules = ''
SUBSYSTEM=="input", ENV{ID_INPUT_TOUCHSCREEN}=="1", ENV{LIBINPUT_CALIBRATION_MATRIX}="1 0 0 0 1 0"
'';
# ─────────────────────── Touch controller resume fix ───────────────────────
# The hid-over-i2c touch controller at i2c bus 4-0001 wedges across S3 suspend: after resume it
# re-enumerates with the correct capabilities but reports zero events on touch. Cycling the
# `i2c_hid_of` driver (unbind + bind) un-wedges it. systemd-sleep runs every executable in
# `/etc/systemd/system-sleep/` with `$1 = pre|post`; we only act on `post`. Driver name is
# discovered at runtime so a future kernel rename to `i2c_hid` doesn't break this.
environment.etc."systemd/system-sleep/ideapad-touch-rebind".source =
pkgs.writeShellScript "ideapad-touch-rebind" ''
set -eu
[ "$1" = post ] || exit 0
dev=4-0001
dev_dir=/sys/bus/i2c/devices/$dev
[ -L "$dev_dir/driver" ] || exit 0
drv=$(${pkgs.coreutils}/bin/basename "$(${pkgs.coreutils}/bin/readlink "$dev_dir/driver")")
echo "ideapad-touch-rebind: cycling $drv for $dev" >&2
echo "$dev" > "/sys/bus/i2c/drivers/$drv/unbind" || true
${pkgs.coreutils}/bin/sleep 0.3
echo "$dev" > "/sys/bus/i2c/drivers/$drv/bind"
'';
# ─────────────────────── User-facing tools ───────────────────────
# System-wide so any user session (Niri or Hyprland) can launch wvkbd / hyprctl / niri-msg helpers.
environment.systemPackages = [
@@ -297,6 +308,12 @@ in
chiasson.desktop.niri.extraSettings = lib.mkIf config.chiasson.desktop.niri.enable {
input.touch.map-to-output = "DSI-1";
# Required for logind's `HandlePowerKey` in `_private/platform.nix` to take effect: otherwise
# niri grabs a `block` inhibitor on `handle-power-key` and suspends via D-Bus, including on
# the EC's wake-from-suspend KEY_POWER event → instant re-suspend loop.
# https://github.com/niri-wm/niri/issues/2233
input."disable-power-key-handling" = _: { };
# wrapper-modules schema: each entry is a `command argv` list of strings (or a single string).
spawn-at-startup = [
[ "ideapad-niri-autorotate-daemon" ]
+10 -16
View File
@@ -1,10 +1,9 @@
{ self, inputs, ... }: {
# Lenovo Chromebook Duet 3 (`lenovo-wormdingler`) on Mobile NixOS.
#
# Phase 1 (minimal bootstrap) lived here previously; we now run the full V2 stack:
# mobile-nixos device + Niri/Hyprland/DMS, DankGreeter, Waydroid (tablet-class), wvkbd,
# IIO sensors, touchscreen calibration, attic cache, sops, and the standard user catalog.
# Full V2 stack: mobile-nixos device + Niri/Hyprland/DMS, DankGreeter, wvkbd, IIO sensors,
# touchscreen calibration + resume-rebind, attic cache, sops, and the standard user catalog.
# Host-only quirks live in `_private/touch-tablet.nix` and `_private/platform.nix`.
flake.nixosModules.ideapadConfiguration =
{
self,
@@ -102,9 +101,8 @@
};
# ─────────────────────── Desktop ───────────────────────
# Both compositors enabled; DankGreeter lets you pick at login. Default = Niri (V2 convention),
# Hyprland session is where the tablet-mode + autorotate daemons in `_private/touch-tablet.nix`
# actually run (they hook `exec-once`).
# Both compositors are enabled DankGreeter picks at login, V2 default is Niri.
# Per-session tablet-mode / autorotate daemons live in `_private/touch-tablet.nix`.
chiasson.desktop = {
niri.enable = true;
hyprland.enable = true;
@@ -113,6 +111,7 @@
shell = "dms";
shells.dms = {
enableWvkbdToggle = true;
enableRbwLockToggle = true;
# Cross-build on the 14900k via binfmt and push back over LAN — much faster than
# rebuilding aarch64 closure on the Snapdragon. Mirrors the old NixOS-New flow:
# ssh out to nixdesk, run nixos-rebuild --target-host pointing back at us.
@@ -126,15 +125,6 @@
];
};
# Tablet-class screen → constrain Waydroid to a sane portrait-ish frame and use gesture nav
# instead of 3-button so it feels like the ChromeOS tablet UI.
#waydroid = {
# enable = true;
# multiWindows = false;
# width = 1600;
# height = 960;
# navigationMode = "gestures";
#};
};
# ─────────────────────── Users / HM ───────────────────────
@@ -146,10 +136,12 @@
self.homeManagerModules.wisdomTerminalsKitty
self.homeManagerModules.wisdomBrowsersZen
self.homeManagerModules.wisdomEditorsKate
self.homeManagerModules.wisdomEditorsCursor
self.homeManagerModules.wisdomShellFish
self.homeManagerModules.wisdomShellOhMyPosh
self.homeManagerModules.wisdomAppsSpotify
self.homeManagerModules.wisdomAppsLocalsend
self.homeManagerModules.wisdomAppsSpacedrive
self.homeManagerModules.wisdomDesktopScreenshot
{
chiasson.home = {
@@ -161,8 +153,10 @@
filebrowsers.dolphin.enable = true;
browsers.zen.enable = true;
editors.kate.enable = true;
editors.cursor.enable = true;
apps.spotify.enable = true;
apps.localsend.enable = true;
apps.spacedrive.enable = true;
desktop = {
screenshot = {
enable = true;
@@ -0,0 +1,38 @@
# Dispatcharr — IPTV / M3U / EPG / HDHomeRun-style proxy (Docker, AIO image).
# Docs: https://dispatcharr.github.io/Dispatcharr-Docs/
# Compose reference: https://github.com/Dispatcharr/Dispatcharr/blob/main/docker/docker-compose.aio.yml
#
# Web UI: http://<host>:9191
# After deploy: create an admin user, add playlists / EPG; point Jellyfin at the tuner/M3U URLs
# Dispatcharr shows in its UI.
{ lib, pkgs, ... }:
{
systemd.tmpfiles.settings."nix-server-dispatcharr-data" = {
"/var/lib/dispatcharr"."d" = {
mode = "0755";
user = "root";
group = "root";
};
};
systemd.services.docker-dispatcharr.preStart = lib.mkBefore ''
${pkgs.coreutils}/bin/mkdir -p /var/lib/dispatcharr
'';
virtualisation.oci-containers.containers.dispatcharr = {
image = "ghcr.io/dispatcharr/dispatcharr:latest";
ports = [ "9191:9191" ];
volumes = [
"/var/lib/dispatcharr:/data"
];
environment = {
DISPATCHARR_ENV = "aio";
REDIS_HOST = "localhost";
CELERY_BROKER_URL = "redis://localhost:6379/0";
DISPATCHARR_LOG_LEVEL = "info";
TZ = "America/Moncton";
};
};
networking.firewall.allowedTCPPorts = [ 9191 ];
}
@@ -1,27 +0,0 @@
# NFS read-only mount of nixdesk (14900k) bulk storage for extra Jellyfin libraries.
# Source: ssh inventory hostName for 14900k. Export is defined in
# modules/hosts/14900k/_private/jellyfin-nfs-export.nix
#
# In Jellyfin (in addition to local /var/lib/media/...), add e.g.:
# Movies → /mnt/nixdesk-jellyfin/movies
# Shows → /mnt/nixdesk-jellyfin/tv
{ ... }:
let
# Must match LAN IP of the NFS server (flake `sshInventory` → hosts."14900k".hostName).
nfsExportHost = "192.168.2.25";
in
{
fileSystems."/mnt/nixdesk-jellyfin" = {
device = "${nfsExportHost}:/mnt/test/jellyfin";
fsType = "nfs";
options = [
"rw"
"noatime"
"nofail"
"_netdev"
"x-systemd.automount"
"x-systemd.idle-timeout=600"
];
};
}
@@ -1,5 +1,5 @@
# Jellyfin (native NixOS service). Local media: /var/lib/media (group `media`; jellyfin + server).
# Dashboard: Movies → /var/lib/media/movies, Shows → /var/lib/media/tv (see jellyfin-remote-storage.nix
# Dashboard: Movies → /var/lib/media/movies, Shows → /var/lib/media/tv (see nixdesk-nfs-client.nix
# for bulk libraries on nixdesk at /mnt/nixdesk-jellyfin/{movies,tv}).
# Do not use "Mixed Movies and Shows" (deprecated): https://jellyfin.org/docs/general/server/media/mixed-movies-and-shows
# Dedicated disk: fileSystems."/var/lib/media" in hardware.nix, then fix ownership.
@@ -53,8 +53,9 @@
# not writable by uid jellyfin (it only had group `jellyfin`), so deletes fail.
systemd.services.jellyfin.serviceConfig = {
SupplementaryGroups = [ "media" ];
# Jellyfin libraries may live on NFS (e.g. /mnt/nixdesk-jellyfin). PrivateUsers breaks
# uid mapping for NFS auth in practice; disable so deletes use the real host jellyfin uid.
# Jellyfin libraries on NFS (e.g. /mnt/media, /mnt/nixdesk-jellyfin). PrivateUsers breaks
# uid mapping for NFS auth in practice; disable so metadata writes use the real jellyfin uid
# (squashed to olivier:nfsmedia on nixdesk exports).
PrivateUsers = lib.mkForce false;
};
}
@@ -0,0 +1,41 @@
# NFS mounts of nixdesk (14900k) bulk storage for nix-server. Exports live in
# modules/hosts/14900k/_private/jellyfin-nfs-export.nix
#
# Jellyfin library paths (see also services/jellyfin.nix):
# Movies → /mnt/nixdesk-jellyfin/movies
# Shows → /mnt/nixdesk-jellyfin/tv
#
# If you see "Stale file handle" under /mnt after changing exports or fsid on nixdesk, drop the
# old client mount and let automount reattach, e.g.:
# sudo umount -l /mnt/nixdesk-jellyfin
# ls /mnt/nixdesk-jellyfin
# (or reboot nix-server.)
{ ... }:
let
nfsExportHost = "192.168.2.25";
# nfsvers+tcp: predictable Linux↔Linux; lookupcache=none: fewer stale dentries after export changes.
nfsClientOpts = [
"rw"
"noatime"
"nofail"
"_netdev"
"nfsvers=3"
"tcp"
"lookupcache=none"
"x-systemd.automount"
"x-systemd.idle-timeout=3600"
];
in
{
fileSystems."/mnt/nixdesk-jellyfin" = {
device = "${nfsExportHost}:/mnt/test/jellyfin";
fsType = "nfs";
options = nfsClientOpts;
};
fileSystems."/mnt/media" = {
device = "${nfsExportHost}:/mnt/media";
fsType = "nfs";
options = nfsClientOpts;
};
}
+2 -1
View File
@@ -20,7 +20,7 @@
./_services/swiftshare.nix
./_services/immich.nix
./_services/jellyfin.nix
./_services/jellyfin-remote-storage.nix
./_services/nixdesk-nfs-client.nix
./_services/ddrm-media-server.nix
./_services/sonarr.nix
./_services/prowlarr.nix
@@ -28,6 +28,7 @@
./_services/radarr.nix
./_services/qbittorrent.nix
./_services/seerr.nix
./_services/dispatcharr.nix
];
boot.loader.grub = {
+3
View File
@@ -95,6 +95,9 @@
};
defaultSession = "niri";
shell = "dms";
shells.dms = {
enableRbwLockToggle = true;
};
};
chiasson.system = {
@@ -0,0 +1,37 @@
{ config, ... }:
{
# cockpit-file-sharing expects a live Samba stack: /etc/samba/smb.conf, smbd, and
# `include = registry` in [global] for net registry share management.
services.samba = {
enable = true;
openFirewall = true;
winbindd.enable = false;
settings.global = {
workgroup = "WORKGROUP";
"server string" = config.networking.hostName;
include = "registry";
};
};
services.nfs.server = {
enable = true;
mountdPort = 4000;
lockdPort = 4001;
statdPort = 4002;
};
networking.firewall.allowedTCPPorts = [
111
2049
4000
4001
4002
];
networking.firewall.allowedUDPPorts = [
111
2049
4000
4001
4002
];
}
@@ -0,0 +1,60 @@
{
acl,
bash,
coreutils,
dpkg,
fetchurl,
findutils,
hostname,
iproute2,
jq,
lib,
nfs-utils,
python3Packages,
samba,
stdenv,
systemd,
}:
stdenv.mkDerivation {
pname = "cockpit-file-sharing";
version = "4.5.6-1";
src = fetchurl {
url = "https://github.com/45Drives/cockpit-file-sharing/releases/download/v4.5.6-1/cockpit-file-sharing_4.5.6-1jammy_all.deb";
hash = "sha256-ViTdhiCmqwuBvAfzT8hr2kqZqyWkV9OZ9FEPD10ajF8=";
};
nativeBuildInputs = [ dpkg ];
unpackPhase = "dpkg-deb -x $src source";
installPhase = ''
runHook preInstall
mkdir -p $out/share/cockpit
cp -r source/usr/share/cockpit/file-sharing $out/share/cockpit/
runHook postInstall
'';
passthru.cockpitPath = [
acl
bash
coreutils
findutils
hostname
iproute2
jq
nfs-utils
python3Packages.botocore
samba
systemd
];
meta = {
description = "Cockpit plugin to manage Samba and NFS file sharing (45Drives)";
homepage = "https://github.com/45Drives/cockpit-file-sharing";
license = lib.licenses.gpl3Plus;
platforms = lib.platforms.linux;
sourceProvenance = with lib.sourceTypes; [ binaryNativeCode ];
};
}
@@ -0,0 +1,22 @@
{ config, pkgs, ... }:
let
cockpitFileSharing = pkgs.callPackage ./cockpit-file-sharing/package.nix { };
in
{
imports = [ ./cockpit-file-sharing-services.nix ];
services.cockpit = {
enable = true;
openFirewall = true;
allowed-origins = [
"https://${config.networking.hostName}:${toString config.services.cockpit.port}"
"https://192.168.2.60:${toString config.services.cockpit.port}"
];
plugins = with pkgs; [
cockpit-files
cockpit-machines
cockpit-podman
cockpitFileSharing
];
};
}
@@ -0,0 +1,35 @@
# Pi 5 / CM5 onboard Wi-Fi (brcmfmac). Without a regulatory domain the driver scans
# disallowed channels and spams: brcmf_set_channel: set chanspec … fail, reason -52
# (open raspberrypi/linux#6049). Wi-Fi often still works; logs and scans are noisy.
{ pkgs, ... }:
let
wifiCountry = "CA"; # change if you are not in Canada
in
{
boot.kernelParams = [
"cfg80211.ieee80211_regdom=${wifiCountry}"
];
# Firmware country code (config.txt) — picked up before userspace regdom.
hardware.raspberry-pi.extra-config = ''
country=${wifiCountry}
'';
# Apply regdom before NetworkManager starts scanning.
systemd.services.wifi-regulatory-domain = {
description = "Set Wi-Fi regulatory domain for brcmfmac";
wantedBy = [ "multi-user.target" ];
before = [ "NetworkManager.service" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
script = ''
${pkgs.iw}/bin/iw reg set ${wifiCountry}
'';
};
networking.networkmanager.wifi.powersave = false;
networking.networkmanager.wifi.scanRandMacAddress = false;
networking.networkmanager.connectionConfig."wifi.bgscan" = "0";
}
+2
View File
@@ -29,7 +29,9 @@
self.nixosModules."client-services"
./_private/platform.nix
./_private/wifi-brcmfmac.nix
./_private/services.nix
./_private/cockpit.nix
./_private/activation.nix
./_private/4g/default.nix
];
+20
View File
@@ -19,6 +19,14 @@
}) names
);
inboundUsersAttr = usersLib.inboundHostsAttr selected;
# HM configures fish in ~/.config/fish but no longer sets /etc/passwd or /etc/shells.
hmFishUsers =
if !hmAvailable then { }
else
lib.filterAttrs (
name: hmUser: (hmUser.programs.fish.enable or false) && builtins.elem name names
) config.home-manager.users;
in
{
config = lib.mkMerge [
@@ -46,6 +54,18 @@
chiasson.ssh.inbound.enable = true;
chiasson.ssh.inbound.userAuthorizedHosts = inboundUsersAttr;
})
(lib.mkIf (hmFishUsers != { }) {
environment.shells = lib.mkAfter (
lib.mapAttrsToList (
_: hmUser: lib.getExe hmUser.programs.fish.package
) hmFishUsers
);
users.users = lib.mapAttrs (
name: hmUser: {
shell = lib.mkForce (lib.getExe hmUser.programs.fish.package);
}
) hmFishUsers;
})
];
};
}
@@ -0,0 +1,26 @@
{ ... }: {
flake.homeManagerModules.wisdomAppsSpacedrive =
{ config, lib, pkgs, ... }:
let
root = config.chiasson.home;
cfg = config.chiasson.home.apps.spacedrive;
spacedrivePkg = pkgs.callPackage ./package { };
in
{
options.chiasson.home.apps.spacedrive = {
enable = lib.mkEnableOption ''
[Spacedrive](https://spacedrive.com/) v2 alpha upstream `.deb` repackaged for NixOS.
'';
package = lib.mkOption {
type = lib.types.package;
default = spacedrivePkg;
description = "Spacedrive package (defaults to upstream v2.0.0-alpha.2).";
};
};
config = lib.mkIf (root.enable && cfg.enable) {
home.packages = [ cfg.package ];
};
};
}
@@ -0,0 +1,112 @@
{
lib,
stdenv,
fetchurl,
dpkg,
makeWrapper,
autoPatchelfHook,
wrapGAppsHook3,
adwaita-icon-theme,
ffmpeg,
gdk-pixbuf,
glib,
glib-networking,
gst_all_1,
gtk3,
hicolor-icon-theme,
libsoup_3,
webkitgtk_4_1,
xdotool,
}:
let
version = "2.0.0-alpha.2";
srcInfo =
if stdenv.hostPlatform.system == "x86_64-linux" then
{
url = "https://github.com/spacedriveapp/spacedrive/releases/download/v${version}/Spacedrive-linux-x86_64.deb";
hash = "sha256-KzRPBtyX5x4ZLlZd6SgAS/cy/7irXt7v+b3Yuq9GETo=";
}
else if stdenv.hostPlatform.system == "aarch64-linux" then
{
url = "https://github.com/spacedriveapp/spacedrive/releases/download/v${version}/Spacedrive-linux-aarch64.deb";
hash = "sha256-Arq4seJxd69XdraIaYJSv1p9g+Bz/7rez/l9EP6dc9k=";
}
else
throw "spacedrive ${version}: unsupported platform: ${stdenv.hostPlatform.system}";
in
stdenv.mkDerivation {
pname = "spacedrive";
inherit version;
src = fetchurl srcInfo;
nativeBuildInputs = [
dpkg
makeWrapper
autoPatchelfHook
wrapGAppsHook3
];
buildInputs = [
adwaita-icon-theme
ffmpeg
gdk-pixbuf
glib
glib-networking
gtk3
hicolor-icon-theme
libsoup_3
webkitgtk_4_1
xdotool
gst_all_1.gst-plugins-ugly
gst_all_1.gst-plugins-bad
gst_all_1.gst-plugins-base
gst_all_1.gstreamer
];
# WebKitGTK + TLS + icons; ffmpeg/ffprobe on PATH (alpha Linux builds omit bundled ffmpeg).
preFixup = ''
gappsWrapperArgs+=(
"--prefix" "PATH" ":" "${lib.makeBinPath [ ffmpeg ]}"
"--set-default" "WEBKIT_DISABLE_DMABUF_RENDERER" "1"
)
'';
postFixup = ''
# Core daemon is not GTK-linked; wrapGAppsHook3 skips it still needs ffmpeg for media paths.
wrapProgram $out/bin/sd-daemon --prefix PATH : "${lib.makeBinPath [ ffmpeg ]}"
'';
unpackPhase = "dpkg-deb -x $src source";
installPhase = ''
runHook preInstall
mkdir -p $out/{bin,lib,share}
cp -r source/usr/bin/* $out/bin/
cp -r source/usr/lib/* $out/lib/
cp -r source/usr/share/* $out/share/
ln -sf Spacedrive $out/bin/spacedrive
substituteInPlace $out/share/applications/Spacedrive.desktop \
--replace-fail 'Exec=Spacedrive' 'Exec=spacedrive'
runHook postInstall
'';
meta = with lib; {
description = "Local-first file manager and virtual distributed filesystem (v2 alpha)";
homepage = "https://spacedrive.com";
changelog = "https://github.com/spacedriveapp/spacedrive/releases/tag/v${version}";
license = licenses.agpl3Plus;
platforms = [
"x86_64-linux"
"aarch64-linux"
];
mainProgram = "spacedrive";
sourceProvenance = with sourceTypes; [ binaryNativeCode ];
};
}
+1
View File
@@ -3,6 +3,7 @@
imports = [
./apps/discord.nix
./apps/localsend.nix
./apps/spacedrive
./apps/pokeclicker
./apps/spotify.nix
./browsers/orion.nix
+16 -1
View File
@@ -6,7 +6,17 @@
cfg = config.chiasson.home.shell.fish;
in
{
options.chiasson.home.shell.fish.enable = lib.mkEnableOption "Fish + grc, quiet greeting, rbw SSH socket defaults.";
options.chiasson.home.shell.fish = {
enable = lib.mkEnableOption "Fish + grc, quiet greeting, rbw SSH socket defaults.";
nixYourShell = {
enable = lib.mkEnableOption ''
Wrap `nix` / `nix-shell` so ephemeral shells use fish (and keep oh-my-posh) instead of bash.
'' // {
default = true;
};
};
};
config = lib.mkIf (root.enable && cfg.enable) {
# `fishPlugins.grc` only installs the plugin; the wrapper invokes the `grc` binary.
@@ -32,6 +42,11 @@
}
];
};
programs.nix-your-shell = lib.mkIf cfg.nixYourShell.enable {
enable = true;
enableFishIntegration = true;
};
};
};
}