Compare commits

..
6 Commits
Author SHA1 Message Date
ahmza 46271e24bb mount nas shares on demand 2026-08-16 17:54:19 +01:00
ahmza 63c1037c85 enable new desktop features on shadow 2026-08-16 17:53:55 +01:00
ahmza 64cbb91aac add seat-scoped via and qmk access 2026-08-16 17:53:31 +01:00
ahmza 3220ab4300 configure et-8550 printing and scanning 2026-08-16 17:53:05 +01:00
ahmza 97b5f89182 add nextcloud and prusaslicer clients 2026-08-16 17:52:43 +01:00
ahmza 61c36b6eef add screenshot tooling to hyprland 2026-08-16 17:52:18 +01:00
8 changed files with 170 additions and 2 deletions
+1 -1
View File
@@ -11,6 +11,7 @@
ghostty
waybar
quickshell
screenshot
];
in {
imports = modules;
@@ -148,7 +149,6 @@
udiskie
brightnessctl
# clipboard
wl-clipboard
cliphist
# theming
gsettings-desktop-schemas
+8
View File
@@ -0,0 +1,8 @@
{...}: {
# Nextcloud desktop sync client. Account and sync settings remain per-user.
flake.nixosModules.nextcloud = {pkgs, ...}: {
environment.systemPackages = with pkgs; [
nextcloud-client
];
};
}
+104
View File
@@ -0,0 +1,104 @@
{...}: {
# CUPS printing + eSCL scanning for the networked EPSON ET-8550.
#
# Two queues, deliberately:
# EPSON_ET_8550 driverless / IPP Everywhere. The default. PDF is
# passed straight through and the printer's own RIP
# does the work. 51 page sizes, 26 borderless, and the
# only queue that can print CD/DVDs (MediaType Disc).
# EPSON_ET_8550_Photo Epson ESC/P-R. Host rasterises to ESC/P-R at 360dpi.
# 34 sizes, 12 borderless, no disc support - but it is
# the only way to reach Epson's named media/quality
# presets ("Epson Ultra Glossy-Max Quality" etc) that
# IPP Everywhere cannot express. Kept for photo A/B.
#
# Note both PPDs are 360x360 HWResolution - escpr2 is not higher resolution.
#
# Both queues use the mDNS name, not 10.10.20.62, so a DHCP lease change
# doesn't break them. services.avahi.nssmdns4 is what resolves it.
# Port 9100 is closed on this printer, so socket:// is not an option.
#
# cups-browsed is off: it would auto-create a third duplicate queue for the
# same printer. avahi stays on for mDNS resolution and scanner discovery.
flake.nixosModules.printing = {
config,
lib,
pkgs,
...
}: {
programs.system-config-printer.enable = true;
services.avahi = {
enable = true;
nssmdns4 = true;
};
services.printing = {
enable = true;
browsed.enable = false;
drivers = with pkgs; [
epson-escpr2
];
};
hardware.printers = {
ensureDefaultPrinter = "EPSON_ET_8550";
ensurePrinters = [
{
name = "EPSON_ET_8550";
description = "EPSON ET-8550 (driverless)";
location = "Network";
deviceUri = "ipp://EPSONA70973.local:631/ipp/print";
model = "everywhere";
}
{
name = "EPSON_ET_8550_Photo";
description = "EPSON ET-8550 (ESC/P-R photo presets)";
location = "Network";
deviceUri = "ipp://EPSONA70973.local:631/ipp/print";
model = "epson-inkjet-printer-escpr2/Epson-ET-8550_Series-epson-escpr2-en.ppd";
}
];
};
# hardware/printers.nix orders ensure-printers only after cups.service, but
# our deviceUri is an mDNS name and the driverless queue queries the printer
# while it is created. Run the generated script asynchronously so an offline
# printer cannot fail boot or nixos-rebuild, then retry until it is reachable.
systemd.services.ensure-printers = lib.mkIf (config.hardware.printers.ensurePrinters != [] && config.services.printing.enable) {
after = [
"avahi-daemon.service"
"network-online.target"
"nss-lookup.target"
];
wants = [
"avahi-daemon.service"
"network-online.target"
];
serviceConfig = {
Type = lib.mkForce "simple";
Restart = "on-failure";
RestartSec = "1min";
};
};
# eSCL/AirScan. The printer advertises _uscan._tcp with rs=eSCL and
# mopria-certified-scan=1.3, so sane-airscan drives it with no vendor
# backend. No scanner/lp group needed - there's no local udev device.
#
# sane-backends ships its own `escl` backend which also claims eSCL
# devices. Left enabled it double-lists the scanner and, worse, GETs the
# printer's web root and dumps the HTML response onto scanimage's stdout.
# Disabling it leaves sane-airscan as the only eSCL backend, which reports
# a far better device string (airscan:e0:EPSON ET-8550 Series).
hardware.sane = {
enable = true;
extraBackends = [pkgs.sane-airscan];
disabledDefaultBackends = ["escl"];
};
environment.systemPackages = with pkgs; [
simple-scan
];
};
}
@@ -0,0 +1,8 @@
{...}: {
# PrusaSlicer package only; printer and filament profiles remain per-user.
flake.nixosModules.prusa-slicer = {pkgs, ...}: {
environment.systemPackages = with pkgs; [
prusa-slicer
];
};
}
+12
View File
@@ -0,0 +1,12 @@
{...}: {
# Screenshot capture, region selection, annotation, and clipboard support for
# the Hyprland screenshot keybinds managed in the dotfiles repo.
flake.nixosModules.screenshot = {pkgs, ...}: {
environment.systemPackages = with pkgs; [
grim
slurp
satty
wl-clipboard
];
};
}
+15
View File
@@ -0,0 +1,15 @@
{...}: {
# QMK/VIA keyboard tooling. QMK's uaccess rule lets the active local seat talk
# to HID devices; remote and non-seat sessions intentionally get no access.
flake.nixosModules.via = {pkgs, ...}: {
environment.systemPackages = with pkgs; [
via
qmk
vial
];
# Do not add pkgs.via or pkgs.vial to services.udev.packages: both make
# every hidraw device world-writable. QMK's rules use seat-scoped ACLs.
hardware.keyboard.qmk.enable = true;
};
}
+4 -1
View File
@@ -20,7 +20,10 @@
gaming
bottles
netops
prusa-slicer
printing
via
nextcloud
];
};
}
+18
View File
@@ -53,6 +53,22 @@
"x-systemd.device-timeout=10"
];
};
# Pin the NFS server until nas.hfx.ahmza.com points at 10.10.100.4.
# Automounting keeps an unavailable NAS out of the boot path.
nfsShare = export: {
device = "10.10.100.4:${export}";
fsType = "nfs";
options = [
"nfsvers=4.2"
"noauto"
"nofail"
"_netdev"
"x-systemd.automount"
"x-systemd.idle-timeout=600"
"x-systemd.mount-timeout=10"
];
};
in {
fileSystems = {
# Boot essentials, by UUID. UUIDs rather than labels here on purpose:
@@ -72,6 +88,8 @@
"/mnt/dump" = spinningDrive "DUMP";
"/mnt/bak" = spinningDrive "BAK";
"/mnt/games" = eagerDrive "GAMES";
"/mnt/nas" = nfsShare "/srv/nas";
"/mnt/media" = nfsShare "/srv/media";
};
# Swap exists for hibernation, not for memory pressure — 31GiB of RAM on a