1
0
forked from colin/nix-files

Compare commits

...

102 Commits

Author SHA1 Message Date
f645005b45 pinephone-pro: ship a binary helper to install (or update) u-boot on an existing (or new) device
moby is now updated to u-boot 2025.07
2025-09-01 22:25:48 +00:00
9979289be1 u-boot-pinephone-pro: refactor (build output is unchanged) 2025-09-01 20:21:07 +00:00
a1396fb273 move bootpart-systemd-boot installation into modules/image, so it reliably applies to hosts which need it 2025-09-01 20:20:43 +00:00
1c38797bad modules/image: fix extraGPTPadding; fix pinephone and pinephone-pro image installation 2025-09-01 20:19:46 +00:00
c66764fba5 hal/pine64-pinephone-pro: fix image build to not be truncated 2025-09-01 11:24:05 +00:00
7e7cac8ecd fix arm-trusted-firmware eval after apparent upstream refactoring to buildArmTrustedFirmware 2025-09-01 11:23:18 +00:00
e7a1ff8b3d rpi-400: note linux_rpi4 2025-09-01 09:51:59 +00:00
e43926eb25 nixpkgs: patches: remove commented-out, irrelevant rpm patch 2025-09-01 09:51:04 +00:00
4dbce1baae cross: update upstreaming status 2025-08-31 23:35:01 +00:00
55979b7e4e aarch64: enable vulkan-tools (it cross compiles) 2025-08-31 22:44:16 +00:00
fadcc1a842 hal/aarch64: only patch SUNXI_CCU=y on aarch64 PLUS preferBuiltin=false
maybe better to gate it on autoModules too?
2025-08-31 22:35:33 +00:00
5526bba05c nixpkgs-bootstrap: 2025-08-30 -> 2025-08-31 2025-08-31 22:07:43 +00:00
26412ee801 nixpkgs-wayland: 2025-08-30 -> 2025-08-31 2025-08-31 22:07:10 +00:00
3cdbd133f6 uassets: 2025-08-30 -> 2025-08-31 2025-08-31 22:06:44 +00:00
bd8c7c971a aarch64: kernel: remove forced BACKLIGHT_CLASS_DEVICE=y (fixed upstream)
fixed in nixpkgs 2024-12-27: <https://github.com/NixOS/nixpkgs/pull/367774>
2025-08-31 13:42:28 +00:00
4c4a24d08d bootpart-edk2-rpi: ship the rpi-400 dtb 2025-08-31 13:19:27 +00:00
86b037c835 modules/image: ship devicetree file, if configured 2025-08-31 12:57:15 +00:00
32ea5ad846 boot: re-enable nixpkgs default kernel modules
this doesn't fix cadey boot completely, but it gets it to fewer errors
2025-08-31 12:26:13 +00:00
3a1eec4308 edk2-rpi: swap raspberry logo with tianocore logo, to remove dependency on edk2-non-osi repo 2025-08-31 11:19:39 +00:00
e81a2498b7 bootpart-edk2-rpi: minimize custom config portions 2025-08-31 10:39:41 +00:00
5f8cfcb7e9 edk2-rpi: fix!
now it actually loads. havent tried booting the full systemd-boot enabled system though
2025-08-31 09:47:26 +00:00
13205492b4 bootpart-edk2-rpi: dont ship .dtb files 2025-08-31 09:04:18 +00:00
176ef307b2 rpi-400: try to boot via EDK2
however, my build of edk2 seems broken. drop the prebuilt RPI_EFI.fd into the resulting image, and it works ...
2025-08-31 08:58:43 +00:00
11293a4d0a bootpart-edk2-rpi: init
have not deployed this yet; untested
2025-08-31 08:20:17 +00:00
a34449faed nixpkgs-bootstrap: 2025-08-29 -> 2025-08-30 2025-08-30 21:12:42 +00:00
4f3b1dd361 nixpkgs-wayland: 2025-08-29 -> 2025-08-30 2025-08-30 21:10:15 +00:00
f7335634a1 euicc-manual: 2025-08-14 -> 2025-08-30 2025-08-30 21:10:01 +00:00
faa8a6968d uassets: 2025-08-29 -> 2025-08-30 2025-08-30 21:09:45 +00:00
fd54b70b36 edk2-rpi4: init 2025-08-30 05:16:36 +00:00
05b864143e todo.md: remove outdated comment about envelope/libadwaita 2025-08-30 01:32:18 +00:00
d9b82e8b1e moby: plumb deviceTree file through to systemd-boot
this fixes the lacking battery charge indication from the previous extlinux -> systemd-boot change
2025-08-30 01:22:52 +00:00
ad559acbd9 moby: switch extlinux -> systemd-boot
for the sake of consistency with my other platforms

u-boot boot order appears to be extlinux > script > efi_mgr > efi

note that after rebooting, battery shows 0%. unclear if systemd-boot somehow breaks charging, or just battery reporting, or if totally unrelated
2025-08-30 00:30:19 +00:00
4d4b28027c todo.md: remove outdated servo /boot size item 2025-08-29 20:56:19 +00:00
da52f21da2 remove commented-out generic-extlinux-compatible configs 2025-08-29 20:55:41 +00:00
fea85f438b servo: fix prosody
well, i know it works with the systemd hardening disabled. i'm assuming it'll work with that enabled too, but don't want to redeploy/restart the service right now
2025-08-29 19:46:42 +00:00
13db8bec76 nixpkgs: 2025-08-28 -> 2025-08-29 2025-08-29 16:17:17 +00:00
01e3ace398 nixpkgs-wayland: 2025-08-28 -> 2025-08-29 2025-08-29 16:17:03 +00:00
745ee33394 uassets: 2025-08-28 -> 2025-08-29 2025-08-29 16:16:49 +00:00
1c5c9b80eb nixpkgs: 2025-08-27 -> 2025-08-28; remove upstreamed newsflash cross code 2025-08-28 16:01:56 +00:00
94289c2253 nixpkgs-wayland: 2025-08-27 -> 2025-08-28 2025-08-28 16:00:27 +00:00
0c443fae25 uassets: 2025-08-26 -> 2025-08-28 2025-08-28 16:00:14 +00:00
a490a74390 cross: open PRs for all my rust cross patches 2025-08-28 01:57:17 +00:00
2e71e06c05 lemoa: inline the cross compilation fix 2025-08-27 18:43:49 +00:00
203832b5a8 envelope: 2024-09-13 -> 2025-05-17; inline the cross fixes 2025-08-27 18:37:55 +00:00
1204f4db69 cross: rewrite newsflash patch as a nixpkgs commit 2025-08-27 17:04:05 +00:00
a4b114fce2 nixpkgs: bump; rewrite snapshot patch as nixpkgs commit 2025-08-27 16:29:58 +00:00
7e17eb4056 nixpkgs-wayland: 2025-08-26 -> 2025-08-27 2025-08-27 15:52:50 +00:00
259d980a60 nixpkgs: 2025-08-26 0> 2025-08-27 2025-08-27 15:52:40 +00:00
5488486944 firefox: fix browserpass/native-messaging-hosts integration 2025-08-27 08:32:35 +00:00
969717b1fe firefox: disable safebrowsing and restrict app auto-updates even more aggressively
i don't think any auto-updating bit me, i'm just being pre-emptive
2025-08-27 07:55:45 +00:00
7391e34f77 cross: factor spot,video-trimmer build fixes into nixpkgs commits 2025-08-27 02:25:28 +00:00
7f45077485 cross: split delfin fix into nixpkgs patch 2025-08-27 01:12:25 +00:00
ceb7ccbc6d todo.md: task for migrating spot -> riff 2025-08-27 01:06:14 +00:00
9d63ec5dd2 hosts: remove references to lappy remote fs
this was causing mount timeouts on _every_ deploy
2025-08-27 00:00:21 +00:00
7ce93eae96 cross: fix papers via upstreamable patch 2025-08-26 23:52:58 +00:00
1277c73304 nixpkgs: update, drop upstreamed loupe/pwvucontrol cross patches 2025-08-26 18:14:55 +00:00
0550498cd1 nixpkgs/patches: remove redundant qemu patch, push coincurve upstream 2025-08-26 17:02:45 +00:00
023396a41e nixpkgs-bootstrap.staging: 2025-08-25 -> 2025-08-26 2025-08-26 15:44:27 +00:00
ebb335ef4c nixpkgs-wayland: 2025-08-25 -> 2025-08-26 2025-08-26 15:44:27 +00:00
fbb0046dda uvtools: 5.1.7 -> 5.2.0 2025-08-26 15:44:27 +00:00
59d4197bf5 uassets: 2025-08-25 -> 2025-08-26 2025-08-26 15:44:27 +00:00
90e4e20274 zimPackages.wikipedia_en_all_maxi: 2024-01 -> 2025-08 2025-08-26 15:44:27 +00:00
7ecd368e20 zimPackages.alpinelinux: 2025-07 -> 2025-08 2025-08-26 15:44:27 +00:00
79fc30da0e cross: push fractal/pwvucontrol/loupe patches upstream & update tracking statuses 2025-08-26 15:44:27 +00:00
23f3647cc5 nixpkgs-wayland: 2025-08-20 -> 2025-08-25 2025-08-26 15:44:27 +00:00
ad4910366d zimPackages.archlinux_en_all_maxi: 2025-07 -> 2025-08 2025-08-26 15:44:27 +00:00
609becadfe nixpkgs: 2025-08-18 -> 2025-08-26 2025-08-26 15:44:27 +00:00
3acabe60b6 uassets: 2025-08-20 -> 2025-08-25 2025-08-26 15:44:27 +00:00
87ec095b8a programs: typescript-language-server: link cache files into ephemeral storage 2025-08-26 15:44:27 +00:00
8831d8d1ac image: fix initrd path to be the /boot path instead of the /nix/store path 2025-08-22 02:58:09 +00:00
8b333a8887 doc/migrating-storage-device: show how to resize the fs 2025-08-22 02:58:09 +00:00
028d903e9c boot: package "mlabel", for changing FAT UUIDs 2025-08-22 02:20:05 +00:00
dfed5f070b servo: update fs UUIDs 2025-08-22 02:19:47 +00:00
b29ee5ac03 desko: gate ollama behind sane.maxBuildCost option 2025-08-21 02:43:35 +00:00
e700ff392f servo: gate costly services behind sane.maxBuildCost option 2025-08-21 02:42:58 +00:00
91578c0b78 snippets: add new links 2025-08-20 17:31:19 +00:00
b35656c9ae nixpkgs-wayland: 2025-08-19 -> 2025-08-20 2025-08-20 17:24:48 +00:00
726281a6dd uassets: 2025-08-19 -> 2025-08-20 2025-08-20 17:24:09 +00:00
f305027678 nvimpager: allow access to vimrc 2025-08-20 01:17:37 +00:00
2b69c07d12 nixpkgs-wayland: 2025-08-18 -> 2025-08-19 2025-08-19 08:35:30 +00:00
544b1e58e0 uassets: 2025-08-18 -> 2025-08-19 2025-08-19 08:35:18 +00:00
34c2d4f66f neovim: ship RC file as ~/.config/nvim/
this allows easier editing at runtime
2025-08-18 21:22:21 +00:00
4addf857b7 firefox: redirect "maps" search URL to Kagi by default 2025-08-18 19:39:31 +00:00
a3f6c148d3 nixpkgs: 2025-08-17 -> 2025-08-18 2025-08-18 15:25:24 +00:00
43a0abd68f nixpkgs-wayland: 2025-08-17 -> 2025-08-18 2025-08-18 15:25:15 +00:00
b3c4e96d6e syshud: 2025-07-26 -> 2025-08-18 2025-08-18 15:24:56 +00:00
ade5ce5339 uassets: 2025-08-17 -> 2025-08-18 2025-08-18 15:24:40 +00:00
e543034fcb overlays/cross: update upstreaming status 2025-08-17 21:25:15 +00:00
b5d96ed17b nixpkgs: 2026-08-16 -> 2025-08-17 2025-08-17 17:32:26 +00:00
003ce70cd7 nixpkgs-wayland: 2025-08-15 -> 2025-08-17 2025-08-17 17:32:16 +00:00
04f6964711 uassets: 2025-08-16 -> 2025-08-17 2025-08-17 17:31:59 +00:00
63cf19f839 nixpkgs: 2025-08-15 -> 2025-08-16 2025-08-16 21:05:35 +00:00
806a1aa294 nixpkgs-wayland: 2025-08-14 -> 2025-08-15 2025-08-16 20:13:28 +00:00
35a023f449 lpac: 2.2.1 -> 2.3.0 2025-08-16 17:06:56 +00:00
f0aec4416c uassets: 2025-08-15 -> 2025-08-16 2025-08-16 16:53:29 +00:00
e0bb1b7c62 servo: gitea: place only the most expensive repos behind Anubis 2025-08-16 08:15:47 +00:00
9847e0171c flowy: avoid invoking no-op efibootmgr operations 2025-08-16 08:05:55 +00:00
03a1638628 flowy: set nixos as default EFI boot entry, always 2025-08-16 07:55:35 +00:00
f7327bef3e servo: document the anubis openGraph setting 2025-08-16 07:04:56 +00:00
47fb8296db flowy: add bootloader entry to boot into Windows (but i still need to do more config to get Bitlocker to work w/o secure boot) 2025-08-16 07:02:37 +00:00
b409fbb5f7 systemd-boot: enable memtest and edk2 UEFI shell 2025-08-16 07:00:47 +00:00
84092395f4 Merge pull request 'patch-gitea-anubis-opengraph' (#6) from shelvacu/colins-nix-files:patch-gitea-anubis-opengraph into master
Reviewed-on: colin/nix-files#6
2025-08-16 07:00:22 +00:00
60 changed files with 1233 additions and 923 deletions

View File

@@ -57,7 +57,6 @@
## IMPROVEMENTS: ## IMPROVEMENTS:
- servo: expand /boot to 2 GiB like all other hosts
- moby: port to systemd-boot - moby: port to systemd-boot
- sane-deadlines: show day of the week for upcoming items - sane-deadlines: show day of the week for upcoming items
- and only show on "first" terminal opened; not on Ctrl+N terminals - and only show on "first" terminal opened; not on Ctrl+N terminals
@@ -74,7 +73,6 @@
- can't do that because lots of applications don't handle URIs - can't do that because lots of applications don't handle URIs
- could workaround using a wrapper that downloads the file and then passes it to the program - could workaround using a wrapper that downloads the file and then passes it to the program
- geary: replace with envelope - geary: replace with envelope
- likely requires updating envelope to a more recent version (for multi-accounting), and therefore updating libadwaita...
### security/resilience ### security/resilience
- /mnt/desko/home, etc, shouldn't include secrets (~/private) - /mnt/desko/home, etc, shouldn't include secrets (~/private)
@@ -135,6 +133,7 @@
- Trivia Quiz (https://linuxphoneapps.org/games/io.github.nokse22.trivia-quiz/) - Trivia Quiz (https://linuxphoneapps.org/games/io.github.nokse22.trivia-quiz/)
- sane-sync-music: remove empty dirs - sane-sync-music: remove empty dirs
- soulseek: install a CLI app usable over ssh - soulseek: install a CLI app usable over ssh
- moby: replace `spot` with its replacement, `riff` (<https://github.com/Diegovsky/riff>)
#### moby #### moby
- moby: port battery support to something upstreamable - moby: port battery support to something upstreamable

View File

@@ -1,18 +1,18 @@
## migrating a host to a new drive ## migrating a host to a new drive
1. copy persistent data off of the host: ### 1. copy persistent data off of the host:
```sh ```sh
$ mkdir -p mnt old/persist $ mkdir -p mnt old/persist
$ mount /dev/$old mnt $ mount /dev/$old mnt
$ rsync -arv mnt/persist/ old/persist/ $ rsync -arv mnt/persist/ old/persist/
``` ```
2. flash the new drive ### 2. flash the new drive
``` ```
$ nix-build -A hosts.moby.img $ nix-build -A hosts.moby.img
$ dd if=$(readlink ./result) of=/dev/$new bs=4M oflag=direct conv=sync status=progress $ dd if=$(readlink ./result) of=/dev/$new bs=4M oflag=direct conv=sync status=progress
``` ```
3. expand the partition and filesystem ### 3.1. expand the partition
```sh ```sh
$ cfdisk /dev/$new $ cfdisk /dev/$new
# scroll to the last partition # scroll to the last partition
@@ -21,24 +21,29 @@ $ cfdisk /dev/$new
> Write > Write
type "yes" type "yes"
> Quit > Quit
$ btrfs filesystem resize max /dev/$new ```
### 3.2. expand the filesystem
```
$ mkdir -p /mnt/$new
$ mount /dev/$new /mnt/$new
$ btrfs filesystem resize max /mnt/$new
``` ```
4. copy data onto the new host ### 4. copy data onto the new host
``` ```
$ mkdir new $ mkdir /mnt/$new
$ mount /dev/$new new $ mount /dev/$new /mnt/$new
# if you want to use btrfs snapshots (e.g. snapper), then create the data directory as a subvolume: # if you want to use btrfs snapshots (e.g. snapper), then create the data directory as a subvolume:
$ sudo btrfs subvolume create new/persist $ btrfs subvolume create /mnt/$new/persist
# restore the data # restore the data
$ rsync -arv old/persist/ new/persist/ $ rsync -arv old/persist/ /mnt/$new/persist/
``` ```
5. ensure/fix ownership ### 5. ensure/fix ownership
``` ```
$ chmod -R a+rX new/nix $ chmod -R a+rX /mnt/$new/nix
# or, let the nix daemon do it: # or, let the nix daemon do it:
$ nix copy --no-check-sigs --to new $(nix-build -A hosts.moby) $ nix copy --no-check-sigs --to /mnt/$new $(nix-build -A hosts.moby)
``` ```
```
6. insert the disk into the system, and boot! ### 6. insert the disk into the system, and boot!

View File

@@ -13,7 +13,4 @@
# TODO: port to `sane.programs` interface # TODO: port to `sane.programs` interface
services.xserver.desktopManager.kodi.enable = true; services.xserver.desktopManager.kodi.enable = true;
# /boot space is at a premium, especially with uncompressed kernels. default was 20.
# boot.loader.generic-extlinux-compatible.configurationLimit = 10;
} }

View File

@@ -1,4 +1,4 @@
{ ... }: { config, lib, ... }:
{ {
imports = [ imports = [
./fs.nix ./fs.nix
@@ -27,7 +27,7 @@
sane.roles.client = true; sane.roles.client = true;
sane.roles.pc = true; sane.roles.pc = true;
sane.roles.work = true; sane.roles.work = true;
sane.services.ollama.enable = true; sane.services.ollama.enable = lib.mkIf (config.sane.maxBuildCost >= 3) true;
sane.services.wg-home.enable = true; sane.services.wg-home.enable = true;
sane.ovpn.addrV4 = "172.26.55.21"; sane.ovpn.addrV4 = "172.26.55.21";
# sane.ovpn.addrV6 = "fd00:0000:1337:cafe:1111:1111:20c1:a73c"; # sane.ovpn.addrV6 = "fd00:0000:1337:cafe:1111:1111:20c1:a73c";

View File

@@ -1,4 +1,4 @@
{ ... }: { lib, pkgs, ... }:
{ {
imports = [ imports = [
./fs.nix ./fs.nix
@@ -22,4 +22,37 @@
sops.secrets.colin-passwd.neededForUsers = true; sops.secrets.colin-passwd.neededForUsers = true;
sane.services.rsync-net.enable = true; sane.services.rsync-net.enable = true;
# add an entry to boot into Windows, as if it had been launched directly from the BIOS.
boot.loader.systemd-boot.rebootForBitlocker = true;
boot.loader.systemd-boot.windows.primary.efiDeviceHandle = "HD0b";
system.activationScripts.makeDefaultBootEntry = {
text = let
makeDefaultBootEntry = pkgs.writeShellApplication {
name = "makeDefaultBootEntry";
runtimeInputs = with pkgs; [
efibootmgr
gnugrep
];
text = ''
# configure the EFI firmware to boot into NixOS by default.
# do this by querying the active boot entry, and just making that be the default.
# this is needed on flowy because enabling secure boot / booting into Windows
# resets the default boot order; manually reconfiguring that is tiresome.
efi=$(efibootmgr)
bootCurrent=$(echo "$efi" | grep '^BootCurrent: ')
bootCurrent=''${bootCurrent/BootCurrent: /}
bootOrder=$(echo "$efi" | grep '^BootOrder: ')
bootOrder=''${bootOrder/BootOrder: /}
if ! [[ "$bootOrder" =~ ^"$bootCurrent", ]]; then
# booted entry was not the default,
# so prepend it to the boot order:
newBootOrder="$bootCurrent,$bootOrder"
(set -x; efibootmgr -o "$newBootOrder")
fi
'';
};
in lib.getExe makeDefaultBootEntry;
};
} }

View File

@@ -58,10 +58,6 @@
sane.programs.mpv.config.defaultProfile = "fast"; sane.programs.mpv.config.defaultProfile = "fast";
# /boot space is at a premium, especially with uncompressed kernels. default was 20. # boot.loader.generic-extlinux-compatible.enable = true;
# boot.loader.generic-extlinux-compatible.configurationLimit = 10; # boot.loader.systemd-boot.enable = false;
# TODO: switch to systemd-boot
boot.loader.generic-extlinux-compatible.enable = true;
boot.loader.systemd-boot.enable = false;
} }

View File

@@ -16,7 +16,7 @@
fileSystems."/tmp".options = [ "size=32G" ]; fileSystems."/tmp".options = [ "size=32G" ];
fileSystems."/nix" = { fileSystems."/nix" = {
device = "/dev/disk/by-uuid/cc81cca0-3cc7-4d82-a00c-6243af3e7776"; device = "/dev/disk/by-uuid/55555555-eeee-ffff-bbbb-000020250820";
fsType = "btrfs"; fsType = "btrfs";
options = [ options = [
"compress=zstd" "compress=zstd"
@@ -25,7 +25,7 @@
}; };
fileSystems."/boot" = { fileSystems."/boot" = {
device = "/dev/disk/by-uuid/6EE3-4171"; device = "/dev/disk/by-uuid/2025-0820";
fsType = "vfat"; fsType = "vfat";
}; };

View File

@@ -124,6 +124,7 @@
services.anubis.instances."git.uninsane.org" = { services.anubis.instances."git.uninsane.org" = {
settings.TARGET = "http://127.0.0.1:3000"; settings.TARGET = "http://127.0.0.1:3000";
# allow IM clients/etc to show embeds/previews, else they just show "please verify you aren't a bot..."
botPolicy.openGraph.enabled = true; botPolicy.openGraph.enabled = true;
}; };
@@ -133,8 +134,13 @@
# XXX(2025-07-24): gitea's still being crawled, even with robots.txt. # XXX(2025-07-24): gitea's still being crawled, even with robots.txt.
# the load is less than when Anthropic first started, but it's still pretty high (like 600%). # the load is less than when Anthropic first started, but it's still pretty high (like 600%).
# place behind anubis to prevent AI crawlers from hogging my CPU (gitea is slow to render pages). # place behind anubis to prevent AI crawlers from hogging my CPU (gitea is slow to render pages).
proxyPass = "http://unix:${config.services.anubis.instances."git.uninsane.org".settings.BIND}"; proxyPassHeavy = "http://unix:${config.services.anubis.instances."git.uninsane.org".settings.BIND}";
# proxyPass = "http://127.0.0.1:3000"; # but anubis breaks embeds, so only protect the expensive repos.
proxyPassLight = "http://127.0.0.1:3000";
proxyTo = proxy: root: {
proxyPass = proxy;
recommendedProxySettings = true;
};
in { in {
forceSSL = true; # gitea complains if served over a different protocol than its config file says forceSSL = true; # gitea complains if served over a different protocol than its config file says
enableACME = true; enableACME = true;
@@ -144,9 +150,20 @@
''; '';
locations."/" = { locations."/" = {
inherit proxyPass; proxyPass = proxyPassLight;
recommendedProxySettings = true; recommendedProxySettings = true;
}; };
# selectively proxy the heavyweight items through anubis.
# a typical interaction is:
# nginx:/colin/linux -> anubis:/colin/linux -> browser is served a loading page
# -> nginx:.within.website/x/cmd/anubis/api/pass-challenge?response=... -> anubis:.within.website/x/cmd/anubis/api/pass-challenge?response=... -> browser is forwarded to /colin/linux
# -> nginx:/colin/linux -> anubis:/colin/linux -> gitea:/colin/linux -> browser is served the actual content
locations."/.within.website/" = proxyTo proxyPassHeavy;
locations."/colin/linux" = proxyTo proxyPassHeavy;
locations."/colin/nixpkgs" = proxyTo proxyPassHeavy;
locations."/colin/opencellid-mirror" = proxyTo proxyPassHeavy;
locations."/colin/podcastindex-db-mirror" = proxyTo proxyPassHeavy;
# fuck you @anthropic # fuck you @anthropic
# locations."= /robots.txt".extraConfig = '' # locations."= /robots.txt".extraConfig = ''
# return 200 "User-agent: *\nDisallow: /\n"; # return 200 "User-agent: *\nDisallow: /\n";
@@ -154,7 +171,7 @@
# gitea serves all `raw` files as content-type: plain, but i'd like to serve them as their actual content type. # gitea serves all `raw` files as content-type: plain, but i'd like to serve them as their actual content type.
# or at least, enough to make specific pages viewable (serving unoriginal content as arbitrary content type is dangerous). # or at least, enough to make specific pages viewable (serving unoriginal content as arbitrary content type is dangerous).
locations."~ ^/colin/phone-case-cq/raw/.*.html" = { locations."~ ^/colin/phone-case-cq/raw/.*.html" = {
inherit proxyPass; proxyPass = proxyPassLight;
recommendedProxySettings = true; recommendedProxySettings = true;
extraConfig = '' extraConfig = ''
proxy_hide_header Content-Type; proxy_hide_header Content-Type;
@@ -163,7 +180,7 @@
''; '';
}; };
locations."~ ^/colin/phone-case-cq/raw/.*.js" = { locations."~ ^/colin/phone-case-cq/raw/.*.js" = {
inherit proxyPass; proxyPass = proxyPassLight;
recommendedProxySettings = true; recommendedProxySettings = true;
extraConfig = '' extraConfig = ''
proxy_hide_header Content-Type; proxy_hide_header Content-Type;

View File

@@ -14,158 +14,160 @@
# #
# N.B.: default install DOES NOT SUPPORT DLNA out of the box. # N.B.: default install DOES NOT SUPPORT DLNA out of the box.
# one must install it as a "plugin", which can be done through the UI. # one must install it as a "plugin", which can be done through the UI.
{ ... }: { config, lib, ... }:
# lib.mkIf false #< XXX(2024-11-17): disabled because it hasn't been working for months; web UI hangs on load, TVs see no files # lib.mkIf false #< XXX(2024-11-17): disabled because it hasn't been working for months; web UI hangs on load, TVs see no files
{ {
# https://jellyfin.org/docs/general/networking/index.html config = lib.mkIf (config.sane.maxBuildCost >= 2) {
sane.ports.ports."1900" = { # https://jellyfin.org/docs/general/networking/index.html
protocol = [ "udp" ]; sane.ports.ports."1900" = {
visibleTo.lan = true; protocol = [ "udp" ];
description = "colin-upnp-for-jellyfin"; visibleTo.lan = true;
}; description = "colin-upnp-for-jellyfin";
sane.ports.ports."7359" = { };
protocol = [ "udp" ]; sane.ports.ports."7359" = {
visibleTo.lan = true; protocol = [ "udp" ];
description = "colin-jellyfin-specific-client-discovery"; visibleTo.lan = true;
# ^ not sure if this is necessary: copied this port from nixos jellyfin.openFirewall description = "colin-jellyfin-specific-client-discovery";
}; # ^ not sure if this is necessary: copied this port from nixos jellyfin.openFirewall
# not sure if 8096/8920 get used either: };
sane.ports.ports."8096" = { # not sure if 8096/8920 get used either:
protocol = [ "tcp" ]; sane.ports.ports."8096" = {
visibleTo.lan = true; protocol = [ "tcp" ];
description = "colin-jellyfin-http-lan"; visibleTo.lan = true;
}; description = "colin-jellyfin-http-lan";
sane.ports.ports."8920" = { };
protocol = [ "tcp" ]; sane.ports.ports."8920" = {
visibleTo.lan = true; protocol = [ "tcp" ];
description = "colin-jellyfin-https-lan"; visibleTo.lan = true;
}; description = "colin-jellyfin-https-lan";
sane.persist.sys.byStore.plaintext = [
{ user = "jellyfin"; group = "jellyfin"; mode = "0700"; path = "/var/lib/jellyfin/data"; method = "bind"; }
{ user = "jellyfin"; group = "jellyfin"; mode = "0700"; path = "/var/lib/jellyfin/metadata"; method = "bind"; }
# TODO: ship plugins statically, via nix. that'll be less fragile
{ user = "jellyfin"; group = "jellyfin"; mode = "0700"; path = "/var/lib/jellyfin/plugins/DLNA_5.0.0.0"; method = "bind"; }
{ user = "jellyfin"; group = "jellyfin"; mode = "0700"; path = "/var/lib/jellyfin/root"; method = "bind"; }
];
sane.persist.sys.byStore.ephemeral = [
{ user = "jellyfin"; group = "jellyfin"; mode = "0700"; path = "/var/lib/jellyfin/log"; method = "bind"; }
{ user = "jellyfin"; group = "jellyfin"; mode = "0700"; path = "/var/lib/jellyfin/transcodes"; method = "bind"; }
];
services.jellyfin.enable = true;
users.users.jellyfin.extraGroups = [ "media" ];
sane.fs."/var/lib/jellyfin".dir.acl = {
user = "jellyfin";
group = "jellyfin";
mode = "0700";
};
# `"Jellyfin.Plugin.Dlna": "Debug"` logging: <https://jellyfin.org/docs/general/networking/dlna>
# TODO: switch Dlna back to 'Information' once satisfied with stability
sane.fs."/var/lib/jellyfin/config/logging.json".symlink.text = ''
{
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning",
"Jellyfin.Plugin.Dlna": "Debug"
}
},
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss}] [{Level:u3}] [{ThreadId}] {SourceContext}: {Message:lj}{NewLine}{Exception}"
}
}
],
"Enrich": [ "FromLogContext", "WithThreadId" ]
}
}
'';
sane.fs."/var/lib/jellyfin/config/network.xml".file.text = ''
<?xml version="1.0" encoding="utf-8"?>
<NetworkConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<BaseUrl />
<EnableHttps>false</EnableHttps>
<RequireHttps>false</RequireHttps>
<InternalHttpPort>8096</InternalHttpPort>
<InternalHttpsPort>8920</InternalHttpsPort>
<PublicHttpPort>8096</PublicHttpPort>
<PublicHttpsPort>8920</PublicHttpsPort>
<AutoDiscovery>true</AutoDiscovery>
<EnableUPnP>false</EnableUPnP>
<EnableIPv4>true</EnableIPv4>
<EnableIPv6>false</EnableIPv6>
<EnableRemoteAccess>true</EnableRemoteAccess>
<LocalNetworkSubnets>
<string>10.78.76.0/22</string>
</LocalNetworkSubnets>
<KnownProxies>
<string>127.0.0.1</string>
<string>localhost</string>
<string>10.78.79.1</string>
</KnownProxies>
<IgnoreVirtualInterfaces>false</IgnoreVirtualInterfaces>
<VirtualInterfaceNames />
<EnablePublishedServerUriByRequest>false</EnablePublishedServerUriByRequest>
<PublishedServerUriBySubnet />
<RemoteIPFilter />
<IsRemoteIPFilterBlacklist>false</IsRemoteIPFilterBlacklist>
</NetworkConfiguration>
'';
# guest user id is `5ad194d60dca41de84b332950ffc4308`
sane.fs."/var/lib/jellyfin/plugins/configurations/Jellyfin.Plugin.Dlna.xml".file.text = ''
<?xml version="1.0" encoding="utf-8"?>
<DlnaPluginConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<EnablePlayTo>true</EnablePlayTo>
<ClientDiscoveryIntervalSeconds>60</ClientDiscoveryIntervalSeconds>
<BlastAliveMessages>true</BlastAliveMessages>
<AliveMessageIntervalSeconds>180</AliveMessageIntervalSeconds>
<SendOnlyMatchedHost>true</SendOnlyMatchedHost>
<DefaultUserId>5ad194d6-0dca-41de-84b3-32950ffc4308</DefaultUserId>
</DlnaPluginConfiguration>
'';
# fix LG TV to play more files.
# there are certain files for which it only supports Direct Play (not even "Direct Stream" -- but "Direct Play").
# this isn't a 100% fix: patching the profile allows e.g. Azumanga Daioh to play,
# but A Place Further Than the Universe still fails as before.
#
# profile is based on upstream: <https://github.com/jellyfin/jellyfin-plugin-dlna>
sane.fs."/var/lib/jellyfin/plugins/DLNA_5.0.0.0/profiles/LG Smart TV.xml".symlink.target = ./dlna/user/LG_Smart_TV.xml;
# XXX(2024-11-17): old method, but the file referenced seems not to be used and setting just it causes failures:
# > [DBG] Jellyfin.Plugin.Dlna.ContentDirectory.ContentDirectoryService: Not eligible for DirectPlay due to unsupported subtitles
# sane.fs."/var/lib/jellyfin/plugins/configurations/dlna/user/LG Smart TV.xml".symlink.target = ./dlna/user/LG_Smart_TV.xml;
systemd.services.jellyfin.unitConfig.RequiresMountsFor = [
"/var/media"
];
# Jellyfin multimedia server
# this is mostly taken from the official jellfin.org docs
services.nginx.virtualHosts."jelly.uninsane.org" = {
forceSSL = true;
enableACME = true;
# inherit kTLS;
locations."/" = {
proxyPass = "http://127.0.0.1:8096";
proxyWebsockets = true;
recommendedProxySettings = true;
# extraConfig = ''
# # Disable buffering when the nginx proxy gets very resource heavy upon streaming
# proxy_buffering off;
# '';
}; };
};
sane.dns.zones."uninsane.org".inet.CNAME."jelly" = "native"; sane.persist.sys.byStore.plaintext = [
{ user = "jellyfin"; group = "jellyfin"; mode = "0700"; path = "/var/lib/jellyfin/data"; method = "bind"; }
{ user = "jellyfin"; group = "jellyfin"; mode = "0700"; path = "/var/lib/jellyfin/metadata"; method = "bind"; }
# TODO: ship plugins statically, via nix. that'll be less fragile
{ user = "jellyfin"; group = "jellyfin"; mode = "0700"; path = "/var/lib/jellyfin/plugins/DLNA_5.0.0.0"; method = "bind"; }
{ user = "jellyfin"; group = "jellyfin"; mode = "0700"; path = "/var/lib/jellyfin/root"; method = "bind"; }
];
sane.persist.sys.byStore.ephemeral = [
{ user = "jellyfin"; group = "jellyfin"; mode = "0700"; path = "/var/lib/jellyfin/log"; method = "bind"; }
{ user = "jellyfin"; group = "jellyfin"; mode = "0700"; path = "/var/lib/jellyfin/transcodes"; method = "bind"; }
];
services.jellyfin.enable = true;
users.users.jellyfin.extraGroups = [ "media" ];
sane.fs."/var/lib/jellyfin".dir.acl = {
user = "jellyfin";
group = "jellyfin";
mode = "0700";
};
# `"Jellyfin.Plugin.Dlna": "Debug"` logging: <https://jellyfin.org/docs/general/networking/dlna>
# TODO: switch Dlna back to 'Information' once satisfied with stability
sane.fs."/var/lib/jellyfin/config/logging.json".symlink.text = ''
{
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning",
"Jellyfin.Plugin.Dlna": "Debug"
}
},
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss}] [{Level:u3}] [{ThreadId}] {SourceContext}: {Message:lj}{NewLine}{Exception}"
}
}
],
"Enrich": [ "FromLogContext", "WithThreadId" ]
}
}
'';
sane.fs."/var/lib/jellyfin/config/network.xml".file.text = ''
<?xml version="1.0" encoding="utf-8"?>
<NetworkConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<BaseUrl />
<EnableHttps>false</EnableHttps>
<RequireHttps>false</RequireHttps>
<InternalHttpPort>8096</InternalHttpPort>
<InternalHttpsPort>8920</InternalHttpsPort>
<PublicHttpPort>8096</PublicHttpPort>
<PublicHttpsPort>8920</PublicHttpsPort>
<AutoDiscovery>true</AutoDiscovery>
<EnableUPnP>false</EnableUPnP>
<EnableIPv4>true</EnableIPv4>
<EnableIPv6>false</EnableIPv6>
<EnableRemoteAccess>true</EnableRemoteAccess>
<LocalNetworkSubnets>
<string>10.78.76.0/22</string>
</LocalNetworkSubnets>
<KnownProxies>
<string>127.0.0.1</string>
<string>localhost</string>
<string>10.78.79.1</string>
</KnownProxies>
<IgnoreVirtualInterfaces>false</IgnoreVirtualInterfaces>
<VirtualInterfaceNames />
<EnablePublishedServerUriByRequest>false</EnablePublishedServerUriByRequest>
<PublishedServerUriBySubnet />
<RemoteIPFilter />
<IsRemoteIPFilterBlacklist>false</IsRemoteIPFilterBlacklist>
</NetworkConfiguration>
'';
# guest user id is `5ad194d60dca41de84b332950ffc4308`
sane.fs."/var/lib/jellyfin/plugins/configurations/Jellyfin.Plugin.Dlna.xml".file.text = ''
<?xml version="1.0" encoding="utf-8"?>
<DlnaPluginConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<EnablePlayTo>true</EnablePlayTo>
<ClientDiscoveryIntervalSeconds>60</ClientDiscoveryIntervalSeconds>
<BlastAliveMessages>true</BlastAliveMessages>
<AliveMessageIntervalSeconds>180</AliveMessageIntervalSeconds>
<SendOnlyMatchedHost>true</SendOnlyMatchedHost>
<DefaultUserId>5ad194d6-0dca-41de-84b3-32950ffc4308</DefaultUserId>
</DlnaPluginConfiguration>
'';
# fix LG TV to play more files.
# there are certain files for which it only supports Direct Play (not even "Direct Stream" -- but "Direct Play").
# this isn't a 100% fix: patching the profile allows e.g. Azumanga Daioh to play,
# but A Place Further Than the Universe still fails as before.
#
# profile is based on upstream: <https://github.com/jellyfin/jellyfin-plugin-dlna>
sane.fs."/var/lib/jellyfin/plugins/DLNA_5.0.0.0/profiles/LG Smart TV.xml".symlink.target = ./dlna/user/LG_Smart_TV.xml;
# XXX(2024-11-17): old method, but the file referenced seems not to be used and setting just it causes failures:
# > [DBG] Jellyfin.Plugin.Dlna.ContentDirectory.ContentDirectoryService: Not eligible for DirectPlay due to unsupported subtitles
# sane.fs."/var/lib/jellyfin/plugins/configurations/dlna/user/LG Smart TV.xml".symlink.target = ./dlna/user/LG_Smart_TV.xml;
systemd.services.jellyfin.unitConfig.RequiresMountsFor = [
"/var/media"
];
# Jellyfin multimedia server
# this is mostly taken from the official jellfin.org docs
services.nginx.virtualHosts."jelly.uninsane.org" = {
forceSSL = true;
enableACME = true;
# inherit kTLS;
locations."/" = {
proxyPass = "http://127.0.0.1:8096";
proxyWebsockets = true;
recommendedProxySettings = true;
# extraConfig = ''
# # Disable buffering when the nginx proxy gets very resource heavy upon streaming
# proxy_buffering off;
# '';
};
};
sane.dns.zones."uninsane.org".inet.CNAME."jelly" = "native";
};
} }

View File

@@ -1,40 +1,42 @@
{ pkgs, ... }: { config, lib, pkgs, ... }:
{ {
sane.services.kiwix-serve = { config = lib.mkIf (config.sane.maxBuildCost >= 3) {
enable = true; sane.services.kiwix-serve = {
port = 8013; enable = true;
zimPaths = with pkgs.zimPackages; [ port = 8013;
alpinelinux_en_all_maxi.zimPath zimPaths = with pkgs.zimPackages; [
archlinux_en_all_maxi.zimPath alpinelinux_en_all_maxi.zimPath
bitcoin_en_all_maxi.zimPath archlinux_en_all_maxi.zimPath
devdocs_en_nix.zimPath bitcoin_en_all_maxi.zimPath
gentoo_en_all_maxi.zimPath devdocs_en_nix.zimPath
# khanacademy_en_all.zimPath #< TODO: enable gentoo_en_all_maxi.zimPath
openstreetmap-wiki_en_all_maxi.zimPath # khanacademy_en_all.zimPath #< TODO: enable
psychonautwiki_en_all_maxi.zimPath openstreetmap-wiki_en_all_maxi.zimPath
rationalwiki_en_all_maxi.zimPath psychonautwiki_en_all_maxi.zimPath
# wikipedia_en_100.zimPath rationalwiki_en_all_maxi.zimPath
wikipedia_en_all_maxi.zimPath # wikipedia_en_100.zimPath
# wikipedia_en_all_mini.zimPath wikipedia_en_all_maxi.zimPath
zimgit-food-preparation_en.zimPath # wikipedia_en_all_mini.zimPath
zimgit-medicine_en.zimPath zimgit-food-preparation_en.zimPath
zimgit-post-disaster_en.zimPath zimgit-medicine_en.zimPath
zimgit-water_en.zimPath zimgit-post-disaster_en.zimPath
]; zimgit-water_en.zimPath
}; ];
services.nginx.virtualHosts."w.uninsane.org" = {
forceSSL = true;
enableACME = true;
# inherit kTLS;
locations."/" = {
proxyPass = "http://127.0.0.1:8013";
recommendedProxySettings = true;
}; };
locations."= /robots.txt".extraConfig = ''
return 200 "User-agent: *\nDisallow: /\n";
'';
};
sane.dns.zones."uninsane.org".inet.CNAME."w" = "native"; services.nginx.virtualHosts."w.uninsane.org" = {
forceSSL = true;
enableACME = true;
# inherit kTLS;
locations."/" = {
proxyPass = "http://127.0.0.1:8013";
recommendedProxySettings = true;
};
locations."= /robots.txt".extraConfig = ''
return 200 "User-agent: *\nDisallow: /\n";
'';
};
sane.dns.zones."uninsane.org".inet.CNAME."w" = "native";
};
} }

View File

@@ -3,7 +3,7 @@
# - <repo:LemmyNet/lemmy:docker/nginx.conf> # - <repo:LemmyNet/lemmy:docker/nginx.conf>
# - <repo:LemmyNet/lemmy-ansible:templates/nginx.conf> # - <repo:LemmyNet/lemmy-ansible:templates/nginx.conf>
{ lib, pkgs, ... }: { config, lib, pkgs, ... }:
let let
uiPort = 1234; # default ui port is 1234 uiPort = 1234; # default ui port is 1234
backendPort = 8536; # default backend port is 8536 backendPort = 8536; # default backend port is 8536
@@ -24,154 +24,156 @@ let
media.video.max_frame_count = 30 * 60 * 60; media.video.max_frame_count = 30 * 60 * 60;
}; };
in { in {
services.lemmy = { config = lib.mkIf (config.sane.maxBuildCost >= 2) {
enable = true; services.lemmy = {
settings.hostname = "lemmy.uninsane.org"; enable = true;
# federation.debug forces outbound federation queries to be run synchronously settings.hostname = "lemmy.uninsane.org";
# N.B.: this option might not be read for 0.17.0+? <https://github.com/LemmyNet/lemmy/blob/c32585b03429f0f76d1e4ff738786321a0a9df98/RELEASES.md#upgrade-instructions> # federation.debug forces outbound federation queries to be run synchronously
# settings.federation.debug = true; # N.B.: this option might not be read for 0.17.0+? <https://github.com/LemmyNet/lemmy/blob/c32585b03429f0f76d1e4ff738786321a0a9df98/RELEASES.md#upgrade-instructions>
settings.port = backendPort; # settings.federation.debug = true;
ui.port = uiPort; settings.port = backendPort;
database.createLocally = true; ui.port = uiPort;
nginx.enable = true; database.createLocally = true;
}; nginx.enable = true;
};
systemd.services.lemmy.environment = { systemd.services.lemmy.environment = {
RUST_BACKTRACE = "full"; RUST_BACKTRACE = "full";
RUST_LOG = "error"; RUST_LOG = "error";
# RUST_LOG = "warn"; # RUST_LOG = "warn";
# RUST_LOG = "debug"; # RUST_LOG = "debug";
# RUST_LOG = "trace"; # RUST_LOG = "trace";
# upstream defaults LEMMY_DATABASE_URL = "postgres:///lemmy?host=/run/postgresql"; # upstream defaults LEMMY_DATABASE_URL = "postgres:///lemmy?host=/run/postgresql";
# - Postgres complains that we didn't specify a user # - Postgres complains that we didn't specify a user
# lemmy formats the url as: # lemmy formats the url as:
# - postgres://{user}:{password}@{host}:{port}/{database} # - postgres://{user}:{password}@{host}:{port}/{database}
# SO suggests (https://stackoverflow.com/questions/3582552/what-is-the-format-for-the-postgresql-connection-string-url): # SO suggests (https://stackoverflow.com/questions/3582552/what-is-the-format-for-the-postgresql-connection-string-url):
# - postgresql://[user[:password]@][netloc][:port][/dbname][?param1=value1&...] # - postgresql://[user[:password]@][netloc][:port][/dbname][?param1=value1&...]
# LEMMY_DATABASE_URL = "postgres://lemmy@/run/postgresql"; # connection to server on socket "/run/postgresql/.s.PGSQL.5432" failed: FATAL: database "run/postgresql" does not exist # LEMMY_DATABASE_URL = "postgres://lemmy@/run/postgresql"; # connection to server on socket "/run/postgresql/.s.PGSQL.5432" failed: FATAL: database "run/postgresql" does not exist
# LEMMY_DATABASE_URL = "postgres://lemmy?host=/run/postgresql"; # no PostgreSQL user name specified in startup packet # LEMMY_DATABASE_URL = "postgres://lemmy?host=/run/postgresql"; # no PostgreSQL user name specified in startup packet
# LEMMY_DATABASE_URL = lib.mkForce "postgres://lemmy@?host=/run/postgresql"; # WORKS # LEMMY_DATABASE_URL = lib.mkForce "postgres://lemmy@?host=/run/postgresql"; # WORKS
LEMMY_DATABASE_URL = lib.mkForce "postgres://lemmy@/lemmy?host=/run/postgresql"; LEMMY_DATABASE_URL = lib.mkForce "postgres://lemmy@/lemmy?host=/run/postgresql";
}; };
users.groups.lemmy = {}; users.groups.lemmy = {};
users.users.lemmy = { users.users.lemmy = {
group = "lemmy"; group = "lemmy";
isSystemUser = true; isSystemUser = true;
}; };
services.nginx.virtualHosts."lemmy.uninsane.org" = { services.nginx.virtualHosts."lemmy.uninsane.org" = {
forceSSL = true; forceSSL = true;
enableACME = true; enableACME = true;
}; };
sane.dns.zones."uninsane.org".inet.CNAME."lemmy" = "native"; sane.dns.zones."uninsane.org".inet.CNAME."lemmy" = "native";
systemd.services.lemmy = { systemd.services.lemmy = {
# fix to use a normal user so we can configure perms correctly # fix to use a normal user so we can configure perms correctly
# XXX(2024-07-28): this hasn't been rigorously tested: # XXX(2024-07-28): this hasn't been rigorously tested:
# possible that i've set something too strict and won't notice right away # possible that i've set something too strict and won't notice right away
serviceConfig.DynamicUser = lib.mkForce false; serviceConfig.DynamicUser = lib.mkForce false;
serviceConfig.User = "lemmy"; serviceConfig.User = "lemmy";
serviceConfig.Group = "lemmy"; serviceConfig.Group = "lemmy";
# switch postgres from Requires -> Wants, so that postgres may restart without taking lemmy down with it. # switch postgres from Requires -> Wants, so that postgres may restart without taking lemmy down with it.
requires = lib.mkForce []; requires = lib.mkForce [];
wants = [ "postgresql.service" ]; wants = [ "postgresql.service" ];
# hardening (systemd-analyze security lemmy) # hardening (systemd-analyze security lemmy)
# a handful of these are specified in upstream nixpkgs, but mostly not # a handful of these are specified in upstream nixpkgs, but mostly not
serviceConfig.LockPersonality = true; serviceConfig.LockPersonality = true;
serviceConfig.NoNewPrivileges = true; serviceConfig.NoNewPrivileges = true;
serviceConfig.MemoryDenyWriteExecute = true; serviceConfig.MemoryDenyWriteExecute = true;
serviceConfig.PrivateDevices = true; serviceConfig.PrivateDevices = true;
serviceConfig.PrivateMounts = true; serviceConfig.PrivateMounts = true;
serviceConfig.PrivateTmp = true; serviceConfig.PrivateTmp = true;
serviceConfig.PrivateUsers = true; serviceConfig.PrivateUsers = true;
serviceConfig.ProcSubset = "pid"; serviceConfig.ProcSubset = "pid";
serviceConfig.ProtectClock = true; serviceConfig.ProtectClock = true;
serviceConfig.ProtectControlGroups = true; serviceConfig.ProtectControlGroups = true;
serviceConfig.ProtectHome = true; serviceConfig.ProtectHome = true;
serviceConfig.ProtectHostname = true; serviceConfig.ProtectHostname = true;
serviceConfig.ProtectKernelLogs = true; serviceConfig.ProtectKernelLogs = true;
serviceConfig.ProtectKernelModules = true; serviceConfig.ProtectKernelModules = true;
serviceConfig.ProtectKernelTunables = true; serviceConfig.ProtectKernelTunables = true;
serviceConfig.ProtectProc = "invisible"; serviceConfig.ProtectProc = "invisible";
serviceConfig.ProtectSystem = "strict"; serviceConfig.ProtectSystem = "strict";
serviceConfig.RemoveIPC = true; serviceConfig.RemoveIPC = true;
serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6"; serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
serviceConfig.RestrictNamespaces = true; serviceConfig.RestrictNamespaces = true;
serviceConfig.RestrictSUIDSGID = true; serviceConfig.RestrictSUIDSGID = true;
serviceConfig.SystemCallArchitectures = "native"; serviceConfig.SystemCallArchitectures = "native";
serviceConfig.SystemCallFilter = [ "@system-service" ]; serviceConfig.SystemCallFilter = [ "@system-service" ];
}; };
systemd.services.lemmy-ui = { systemd.services.lemmy-ui = {
# hardening (systemd-analyze security lemmy-ui) # hardening (systemd-analyze security lemmy-ui)
# TODO: upstream into nixpkgs # TODO: upstream into nixpkgs
serviceConfig.LockPersonality = true; serviceConfig.LockPersonality = true;
serviceConfig.NoNewPrivileges = true; serviceConfig.NoNewPrivileges = true;
# serviceConfig.MemoryDenyWriteExecute = true; #< it uses v8, JIT # serviceConfig.MemoryDenyWriteExecute = true; #< it uses v8, JIT
serviceConfig.PrivateDevices = true; serviceConfig.PrivateDevices = true;
serviceConfig.PrivateMounts = true; serviceConfig.PrivateMounts = true;
serviceConfig.PrivateTmp = true; serviceConfig.PrivateTmp = true;
serviceConfig.PrivateUsers = true; serviceConfig.PrivateUsers = true;
serviceConfig.ProcSubset = "pid"; serviceConfig.ProcSubset = "pid";
serviceConfig.ProtectClock = true; serviceConfig.ProtectClock = true;
serviceConfig.ProtectControlGroups = true; serviceConfig.ProtectControlGroups = true;
serviceConfig.ProtectHome = true; serviceConfig.ProtectHome = true;
serviceConfig.ProtectHostname = true; serviceConfig.ProtectHostname = true;
serviceConfig.ProtectKernelLogs = true; serviceConfig.ProtectKernelLogs = true;
serviceConfig.ProtectKernelModules = true; serviceConfig.ProtectKernelModules = true;
serviceConfig.ProtectKernelTunables = true; serviceConfig.ProtectKernelTunables = true;
serviceConfig.ProtectProc = "invisible"; serviceConfig.ProtectProc = "invisible";
serviceConfig.ProtectSystem = "strict"; serviceConfig.ProtectSystem = "strict";
serviceConfig.RemoveIPC = true; serviceConfig.RemoveIPC = true;
serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6"; serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
serviceConfig.RestrictNamespaces = true; serviceConfig.RestrictNamespaces = true;
serviceConfig.RestrictSUIDSGID = true; serviceConfig.RestrictSUIDSGID = true;
serviceConfig.SystemCallArchitectures = "native"; serviceConfig.SystemCallArchitectures = "native";
serviceConfig.SystemCallFilter = [ "@system-service" "@pkey" "@sandbox" ]; serviceConfig.SystemCallFilter = [ "@system-service" "@pkey" "@sandbox" ];
}; };
#v DO NOT REMOVE: defaults to 0.3, instead of latest, so always need to explicitly set this. #v DO NOT REMOVE: defaults to 0.3, instead of latest, so always need to explicitly set this.
services.pict-rs.package = pict-rs; services.pict-rs.package = pict-rs;
systemd.services.pict-rs = { systemd.services.pict-rs = {
serviceConfig.ExecStart = lib.mkForce (lib.concatStringsSep " " [ serviceConfig.ExecStart = lib.mkForce (lib.concatStringsSep " " [
(lib.getExe pict-rs) (lib.getExe pict-rs)
"--config-file" "--config-file"
tomlConfig tomlConfig
"run" "run"
]); ]);
# hardening (systemd-analyze security pict-rs) # hardening (systemd-analyze security pict-rs)
# TODO: upstream into nixpkgs # TODO: upstream into nixpkgs
serviceConfig.LockPersonality = true; serviceConfig.LockPersonality = true;
serviceConfig.NoNewPrivileges = true; serviceConfig.NoNewPrivileges = true;
serviceConfig.MemoryDenyWriteExecute = true; serviceConfig.MemoryDenyWriteExecute = true;
serviceConfig.PrivateDevices = true; serviceConfig.PrivateDevices = true;
serviceConfig.PrivateMounts = true; serviceConfig.PrivateMounts = true;
serviceConfig.PrivateTmp = true; serviceConfig.PrivateTmp = true;
serviceConfig.PrivateUsers = true; serviceConfig.PrivateUsers = true;
serviceConfig.ProcSubset = "pid"; serviceConfig.ProcSubset = "pid";
serviceConfig.ProtectClock = true; serviceConfig.ProtectClock = true;
serviceConfig.ProtectControlGroups = true; serviceConfig.ProtectControlGroups = true;
serviceConfig.ProtectHome = true; serviceConfig.ProtectHome = true;
serviceConfig.ProtectHostname = true; serviceConfig.ProtectHostname = true;
serviceConfig.ProtectKernelLogs = true; serviceConfig.ProtectKernelLogs = true;
serviceConfig.ProtectKernelModules = true; serviceConfig.ProtectKernelModules = true;
serviceConfig.ProtectKernelTunables = true; serviceConfig.ProtectKernelTunables = true;
serviceConfig.ProtectProc = "invisible"; serviceConfig.ProtectProc = "invisible";
serviceConfig.ProtectSystem = "strict"; serviceConfig.ProtectSystem = "strict";
serviceConfig.RemoveIPC = true; serviceConfig.RemoveIPC = true;
serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6"; serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
serviceConfig.RestrictNamespaces = true; serviceConfig.RestrictNamespaces = true;
serviceConfig.RestrictSUIDSGID = true; serviceConfig.RestrictSUIDSGID = true;
serviceConfig.SystemCallArchitectures = "native"; serviceConfig.SystemCallArchitectures = "native";
serviceConfig.SystemCallFilter = [ "@system-service" ]; serviceConfig.SystemCallFilter = [ "@system-service" ];
};
}; };
} }

View File

@@ -14,207 +14,209 @@ let
# logLevel = "debug"; # logLevel = "debug";
in in
{ {
sane.persist.sys.byStore.private = [ config = lib.mkIf (config.sane.maxBuildCost >= 2) {
# contains media i've uploaded to the server sane.persist.sys.byStore.private = [
{ user = "pleroma"; group = "pleroma"; path = "/var/lib/pleroma"; method = "bind"; } # contains media i've uploaded to the server
]; { user = "pleroma"; group = "pleroma"; path = "/var/lib/pleroma"; method = "bind"; }
services.pleroma.enable = true; ];
services.pleroma.secretConfigFile = config.sops.secrets.pleroma_secrets.path; services.pleroma.enable = true;
services.pleroma.configs = [ services.pleroma.secretConfigFile = config.sops.secrets.pleroma_secrets.path;
'' services.pleroma.configs = [
import Config ''
import Config
config :pleroma, Pleroma.Web.Endpoint, config :pleroma, Pleroma.Web.Endpoint,
url: [host: "fed.uninsane.org", scheme: "https", port: 443], url: [host: "fed.uninsane.org", scheme: "https", port: 443],
http: [ip: {127, 0, 0, 1}, port: 4040] http: [ip: {127, 0, 0, 1}, port: 4040]
# secret_key_base: "{secrets.pleroma.secret_key_base}", # secret_key_base: "{secrets.pleroma.secret_key_base}",
# signing_salt: "{secrets.pleroma.signing_salt}" # signing_salt: "{secrets.pleroma.signing_salt}"
config :pleroma, :instance, config :pleroma, :instance,
name: "Perfectly Sane", name: "Perfectly Sane",
description: "Single-user Pleroma instance", description: "Single-user Pleroma instance",
email: "admin.pleroma@uninsane.org", email: "admin.pleroma@uninsane.org",
notify_email: "notify.pleroma@uninsane.org", notify_email: "notify.pleroma@uninsane.org",
limit: 5000, limit: 5000,
registrations_open: true, registrations_open: true,
account_approval_required: true, account_approval_required: true,
max_pinned_statuses: 5, max_pinned_statuses: 5,
external_user_synchronization: true external_user_synchronization: true
# docs: https://hexdocs.pm/swoosh/Swoosh.Adapters.Sendmail.html # docs: https://hexdocs.pm/swoosh/Swoosh.Adapters.Sendmail.html
# test mail config with sudo -u pleroma ./bin/pleroma_ctl email test --to someone@somewhere.net # test mail config with sudo -u pleroma ./bin/pleroma_ctl email test --to someone@somewhere.net
config :pleroma, Pleroma.Emails.Mailer, config :pleroma, Pleroma.Emails.Mailer,
enabled: true, enabled: true,
adapter: Swoosh.Adapters.Sendmail, adapter: Swoosh.Adapters.Sendmail,
cmd_path: "${lib.getExe' pkgs.postfix "sendmail"}" cmd_path: "${lib.getExe' pkgs.postfix "sendmail"}"
config :pleroma, Pleroma.User, config :pleroma, Pleroma.User,
restricted_nicknames: [ "admin", "uninsane", "root" ] restricted_nicknames: [ "admin", "uninsane", "root" ]
config :pleroma, :media_proxy, config :pleroma, :media_proxy,
enabled: false, enabled: false,
redirect_on_failure: true redirect_on_failure: true
#base_url: "https://cache.pleroma.social" #base_url: "https://cache.pleroma.social"
# see for reference: # see for reference:
# - `force_custom_plan`: <https://docs.pleroma.social/backend/configuration/postgresql/#disable-generic-query-plans> # - `force_custom_plan`: <https://docs.pleroma.social/backend/configuration/postgresql/#disable-generic-query-plans>
config :pleroma, Pleroma.Repo, config :pleroma, Pleroma.Repo,
adapter: Ecto.Adapters.Postgres, adapter: Ecto.Adapters.Postgres,
username: "pleroma", username: "pleroma",
database: "pleroma", database: "pleroma",
hostname: "localhost", hostname: "localhost",
pool_size: 10, pool_size: 10,
prepare: :named, prepare: :named,
parameters: [ parameters: [
plan_cache_mode: "force_custom_plan" plan_cache_mode: "force_custom_plan"
] ]
# XXX: prepare: :named is needed only for PG <= 12 # XXX: prepare: :named is needed only for PG <= 12
# prepare: :named, # prepare: :named,
# password: "{secrets.pleroma.db_password}", # password: "{secrets.pleroma.db_password}",
# Configure web push notifications # Configure web push notifications
config :web_push_encryption, :vapid_details, config :web_push_encryption, :vapid_details,
subject: "mailto:notify.pleroma@uninsane.org" subject: "mailto:notify.pleroma@uninsane.org"
# public_key: "{secrets.pleroma.vapid_public_key}", # public_key: "{secrets.pleroma.vapid_public_key}",
# private_key: "{secrets.pleroma.vapid_private_key}" # private_key: "{secrets.pleroma.vapid_private_key}"
# config :joken, default_signer: "{secrets.pleroma.joken_default_signer}" # config :joken, default_signer: "{secrets.pleroma.joken_default_signer}"
config :pleroma, :database, rum_enabled: false config :pleroma, :database, rum_enabled: false
config :pleroma, :instance, static_dir: "/var/lib/pleroma/instance/static" config :pleroma, :instance, static_dir: "/var/lib/pleroma/instance/static"
config :pleroma, Pleroma.Uploaders.Local, uploads: "/var/lib/pleroma/uploads" config :pleroma, Pleroma.Uploaders.Local, uploads: "/var/lib/pleroma/uploads"
config :pleroma, configurable_from_database: false config :pleroma, configurable_from_database: false
# strip metadata from uploaded images # strip metadata from uploaded images
config :pleroma, Pleroma.Upload, filters: [Pleroma.Upload.Filter.Exiftool.StripLocation] config :pleroma, Pleroma.Upload, filters: [Pleroma.Upload.Filter.Exiftool.StripLocation]
# fix log spam: <https://git.pleroma.social/pleroma/pleroma/-/issues/1659> # fix log spam: <https://git.pleroma.social/pleroma/pleroma/-/issues/1659>
# specifically, remove LAN addresses from `reserved` # specifically, remove LAN addresses from `reserved`
config :pleroma, Pleroma.Web.Plugs.RemoteIp, config :pleroma, Pleroma.Web.Plugs.RemoteIp,
enabled: true, enabled: true,
reserved: ["127.0.0.0/8", "::1/128", "fc00::/7", "172.16.0.0/12"] reserved: ["127.0.0.0/8", "::1/128", "fc00::/7", "172.16.0.0/12"]
# TODO: GET /api/pleroma/captcha is broken # TODO: GET /api/pleroma/captcha is broken
# there was a nixpkgs PR to fix this around 2022/10 though. # there was a nixpkgs PR to fix this around 2022/10 though.
config :pleroma, Pleroma.Captcha, config :pleroma, Pleroma.Captcha,
enabled: false, enabled: false,
method: Pleroma.Captcha.Native method: Pleroma.Captcha.Native
# (enabled by colin) # (enabled by colin)
# Enable Strict-Transport-Security once SSL is working: # Enable Strict-Transport-Security once SSL is working:
config :pleroma, :http_security, config :pleroma, :http_security,
sts: true sts: true
# docs: https://docs.pleroma.social/backend/configuration/cheatsheet/#logger # docs: https://docs.pleroma.social/backend/configuration/cheatsheet/#logger
config :logger, config :logger,
backends: [{ExSyslogger, :ex_syslogger}] backends: [{ExSyslogger, :ex_syslogger}]
config :logger, :ex_syslogger, config :logger, :ex_syslogger,
level: :${logLevel} level: :${logLevel}
# policies => list of message rewriting facilities to be enabled # policies => list of message rewriting facilities to be enabled
# transparence => whether to publish these rules in node_info (and /about) # transparence => whether to publish these rules in node_info (and /about)
config :pleroma, :mrf, config :pleroma, :mrf,
policies: [Pleroma.Web.ActivityPub.MRF.SimplePolicy], policies: [Pleroma.Web.ActivityPub.MRF.SimplePolicy],
transparency: true transparency: true
# reject => { host, reason } # reject => { host, reason }
config :pleroma, :mrf_simple, config :pleroma, :mrf_simple,
reject: [ {"threads.net", "megacorp"}, {"*.threads.net", "megacorp"} ] reject: [ {"threads.net", "megacorp"}, {"*.threads.net", "megacorp"} ]
# reject: [ [host: "threads.net", reason: "megacorp"], [host: "*.threads.net", reason: "megacorp"] ] # reject: [ [host: "threads.net", reason: "megacorp"], [host: "*.threads.net", reason: "megacorp"] ]
# XXX colin: not sure if this actually _does_ anything # XXX colin: not sure if this actually _does_ anything
# better to steal emoji from other instances? # better to steal emoji from other instances?
# - <https://docs.pleroma.social/backend/configuration/cheatsheet/#mrf_steal_emoji> # - <https://docs.pleroma.social/backend/configuration/cheatsheet/#mrf_steal_emoji>
config :pleroma, :emoji, config :pleroma, :emoji,
shortcode_globs: ["/emoji/**/*.png"], shortcode_globs: ["/emoji/**/*.png"],
groups: [ groups: [
"Cirno": "/emoji/cirno/*.png", "Cirno": "/emoji/cirno/*.png",
"Kirby": "/emoji/kirby/*.png", "Kirby": "/emoji/kirby/*.png",
"Bun": "/emoji/bun/*.png", "Bun": "/emoji/bun/*.png",
"Yuru Camp": "/emoji/yuru_camp/*.png", "Yuru Camp": "/emoji/yuru_camp/*.png",
] ]
'' ''
]; ];
systemd.services.pleroma.path = [ systemd.services.pleroma.path = [
# something inside pleroma invokes `sh` w/o specifying it by path, so this is needed to allow pleroma to start # something inside pleroma invokes `sh` w/o specifying it by path, so this is needed to allow pleroma to start
pkgs.bash pkgs.bash
# used by Pleroma to strip geo tags from uploads # used by Pleroma to strip geo tags from uploads
pkgs.exiftool pkgs.exiftool
# config.sane.programs.exiftool.package #< XXX(2024-10-20): breaks image uploading # config.sane.programs.exiftool.package #< XXX(2024-10-20): breaks image uploading
# i saw some errors when pleroma was shutting down about it not being able to find `awk`. probably not critical # i saw some errors when pleroma was shutting down about it not being able to find `awk`. probably not critical
# config.sane.programs.gawk.package # config.sane.programs.gawk.package
# needed for email operations like password reset # needed for email operations like password reset
pkgs.postfix pkgs.postfix
]; ];
systemd.services.pleroma = { systemd.services.pleroma = {
# postgres can be slow to service early requests, preventing pleroma from starting on the first try # postgres can be slow to service early requests, preventing pleroma from starting on the first try
serviceConfig.Restart = "on-failure"; serviceConfig.Restart = "on-failure";
serviceConfig.RestartSec = "10s"; serviceConfig.RestartSec = "10s";
# hardening (systemd-analyze security pleroma) # hardening (systemd-analyze security pleroma)
# XXX(2024-07-28): this hasn't been rigorously tested: # XXX(2024-07-28): this hasn't been rigorously tested:
# possible that i've set something too strict and won't notice right away # possible that i've set something too strict and won't notice right away
# make sure to test: # make sure to test:
# - image/media uploading # - image/media uploading
serviceConfig.CapabilityBoundingSet = lib.mkForce [ "" "" ]; # nixos default is `~CAP_SYS_ADMIN` serviceConfig.CapabilityBoundingSet = lib.mkForce [ "" "" ]; # nixos default is `~CAP_SYS_ADMIN`
serviceConfig.LockPersonality = true; serviceConfig.LockPersonality = true;
serviceConfig.NoNewPrivileges = true; serviceConfig.NoNewPrivileges = true;
serviceConfig.MemoryDenyWriteExecute = true; serviceConfig.MemoryDenyWriteExecute = true;
serviceConfig.PrivateDevices = lib.mkForce true; #< dunno why nixpkgs has this set false; it seems to work as true serviceConfig.PrivateDevices = lib.mkForce true; #< dunno why nixpkgs has this set false; it seems to work as true
serviceConfig.PrivateMounts = true; serviceConfig.PrivateMounts = true;
serviceConfig.PrivateTmp = true; serviceConfig.PrivateTmp = true;
serviceConfig.PrivateUsers = true; serviceConfig.PrivateUsers = true;
serviceConfig.ProtectProc = "invisible"; serviceConfig.ProtectProc = "invisible";
serviceConfig.ProcSubset = "all"; #< needs /proc/sys/kernel/overflowuid for bwrap serviceConfig.ProcSubset = "all"; #< needs /proc/sys/kernel/overflowuid for bwrap
serviceConfig.ProtectClock = true; serviceConfig.ProtectClock = true;
serviceConfig.ProtectControlGroups = true; serviceConfig.ProtectControlGroups = true;
serviceConfig.ProtectHome = true; serviceConfig.ProtectHome = true;
serviceConfig.ProtectKernelModules = true; serviceConfig.ProtectKernelModules = true;
serviceConfig.ProtectSystem = lib.mkForce "strict"; serviceConfig.ProtectSystem = lib.mkForce "strict";
serviceConfig.RemoveIPC = true; serviceConfig.RemoveIPC = true;
serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_NETLINK"; serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_NETLINK";
serviceConfig.RestrictSUIDSGID = true; serviceConfig.RestrictSUIDSGID = true;
serviceConfig.SystemCallArchitectures = "native"; serviceConfig.SystemCallArchitectures = "native";
serviceConfig.SystemCallFilter = [ "@system-service" "@mount" "@sandbox" ]; #< "sandbox" might not actually be necessary serviceConfig.SystemCallFilter = [ "@system-service" "@mount" "@sandbox" ]; #< "sandbox" might not actually be necessary
serviceConfig.ProtectHostname = false; #< else brap can't mount /proc serviceConfig.ProtectHostname = false; #< else brap can't mount /proc
serviceConfig.ProtectKernelLogs = false; #< else breaks exiftool ("bwrap: Can't mount proc on /newroot/proc: Operation not permitted") serviceConfig.ProtectKernelLogs = false; #< else breaks exiftool ("bwrap: Can't mount proc on /newroot/proc: Operation not permitted")
serviceConfig.ProtectKernelTunables = false; #< else breaks exiftool serviceConfig.ProtectKernelTunables = false; #< else breaks exiftool
serviceConfig.RestrictNamespaces = false; # media uploads require bwrap serviceConfig.RestrictNamespaces = false; # media uploads require bwrap
}; };
# this is required to allow pleroma to send email. # this is required to allow pleroma to send email.
# raw `sendmail` works, but i think pleroma's passing it some funny flags or something, idk. # raw `sendmail` works, but i think pleroma's passing it some funny flags or something, idk.
# hack to fix that. # hack to fix that.
users.users.pleroma.extraGroups = [ "postdrop" ]; users.users.pleroma.extraGroups = [ "postdrop" ];
# Pleroma server and web interface # Pleroma server and web interface
# TODO: enable publog? # TODO: enable publog?
services.nginx.virtualHosts."fed.uninsane.org" = { services.nginx.virtualHosts."fed.uninsane.org" = {
forceSSL = true; # pleroma redirects to https anyway forceSSL = true; # pleroma redirects to https anyway
enableACME = true; enableACME = true;
# inherit kTLS; # inherit kTLS;
locations."/" = { locations."/" = {
proxyPass = "http://127.0.0.1:4040"; proxyPass = "http://127.0.0.1:4040";
recommendedProxySettings = true; recommendedProxySettings = true;
# documented: https://git.pleroma.social/pleroma/pleroma/-/blob/develop/installation/pleroma.nginx # documented: https://git.pleroma.social/pleroma/pleroma/-/blob/develop/installation/pleroma.nginx
extraConfig = '' extraConfig = ''
# client_max_body_size defines the maximum upload size # client_max_body_size defines the maximum upload size
client_max_body_size 16m; client_max_body_size 16m;
''; '';
};
};
sane.dns.zones."uninsane.org".inet.CNAME."fed" = "native";
sops.secrets."pleroma_secrets" = {
owner = config.users.users.pleroma.name;
}; };
}; };
sane.dns.zones."uninsane.org".inet.CNAME."fed" = "native";
sops.secrets."pleroma_secrets" = {
owner = config.users.users.pleroma.name;
};
} }

View File

@@ -41,6 +41,10 @@
# - maybe i need to setup stun/turn # - maybe i need to setup stun/turn
# #
# TODO: # TODO:
# - MIGRATE TO NIXOS MODULE OPTIONS:
# - `services.prosody.ssl.`...
# - `services.prosody.log`
# - this decreases likelihood of breakage during future upgrades
# - enable push notifications (mod_cloud_notify) # - enable push notifications (mod_cloud_notify)
# - optimize coturn (e.g. move off of the VPN!) # - optimize coturn (e.g. move off of the VPN!)
# - ensure muc is working # - ensure muc is working
@@ -245,11 +249,11 @@ in
extraConfig = '' extraConfig = ''
local function readAll(file) local function readAll(file)
local f = assert(io.open(file, "rb")) local f = Lua.assert(Lua.io.open(file, "rb"))
local content = f:read("*all") local content = f:read("*all")
f:close() f:close()
-- remove trailing newline -- remove trailing newline
return string.gsub(content, "%s+", "") return Lua.string.gsub(content, "%s+", "")
end end
-- logging docs: -- logging docs:
@@ -261,9 +265,11 @@ in
} }
-- see: <https://prosody.im/doc/certificates#automatic_location> -- see: <https://prosody.im/doc/certificates#automatic_location>
-- try to solve: "certmanager: Error indexing certificate directory /etc/prosody/certs: cannot open /etc/prosody/certs: No such file or directory" -- try to solve: "certmanager: Error indexing certificate directory /run/prosody/certs: cannot open /run/prosody/certs: No such file or directory"
-- only, this doesn't work because prosody doesn't like acme's naming scheme -- only, this doesn't work because prosody doesn't like acme's naming scheme
-- certificates = "/var/lib/acme" -- certificates = "/var/lib/acme/uninsane.org"
-- instead, point to /etc/prosody/certs and configure symlinks into this dir (see nix config)
certificates = "/etc/prosody/certs"
c2s_direct_tls_ports = { 5223 } c2s_direct_tls_ports = { 5223 }
s2s_direct_tls_ports = { 5270 } s2s_direct_tls_ports = { 5270 }

View File

@@ -1,14 +1,15 @@
{ lib, pkgs, ... }: { config, lib, pkgs, ... }:
{ {
boot.initrd.supportedFilesystems = [ "ext4" "btrfs" "ext2" "ext3" "vfat" ]; boot.initrd.supportedFilesystems = [ "ext4" "btrfs" "ext2" "ext3" "vfat" ];
# useful emergency utils # useful emergency utils
boot.initrd.extraUtilsCommands = '' boot.initrd.extraUtilsCommands = ''
copy_bin_and_libs ${lib.getExe' pkgs.btrfs-progs "btrfstune"} copy_bin_and_libs ${lib.getExe' pkgs.btrfs-progs "btrfstune"}
copy_bin_and_libs ${lib.getExe' pkgs.util-linux "{cfdisk,lsblk,lscpu}"}
copy_bin_and_libs ${lib.getExe' pkgs.gptfdisk "{cgdisk,gdisk}"}
copy_bin_and_libs ${lib.getExe' pkgs.smartmontools "smartctl"}
copy_bin_and_libs ${lib.getExe' pkgs.e2fsprogs "resize2fs"} copy_bin_and_libs ${lib.getExe' pkgs.e2fsprogs "resize2fs"}
copy_bin_and_libs ${lib.getExe' pkgs.gptfdisk "{cgdisk,gdisk}"}
copy_bin_and_libs ${lib.getExe' pkgs.mtools "mlabel"}
copy_bin_and_libs ${lib.getExe pkgs.nvme-cli} copy_bin_and_libs ${lib.getExe pkgs.nvme-cli}
copy_bin_and_libs ${lib.getExe' pkgs.smartmontools "smartctl"}
copy_bin_and_libs ${lib.getExe' pkgs.util-linux "{cfdisk,lsblk,lscpu}"}
''; '';
boot.kernelParams = [ boot.kernelParams = [
"boot.shell_on_fail" "boot.shell_on_fail"
@@ -37,8 +38,16 @@
boot.consoleLogLevel = 7; boot.consoleLogLevel = 7;
boot.loader.grub.enable = lib.mkDefault false; boot.loader.grub.enable = lib.mkDefault false;
# boot.loader.generic-extlinux-compatible.enable = lib.mkDefault true;
boot.loader.systemd-boot.enable = lib.mkDefault true; boot.loader.systemd-boot.enable = lib.mkDefault true;
boot.loader.systemd-boot.configurationLimit = lib.mkDefault 20;
boot.loader.systemd-boot.edk2-uefi-shell.enable = lib.mkDefault true;
boot.loader.systemd-boot.memtest86.enable = lib.mkDefault
(lib.meta.availableOn pkgs.stdenv.hostPlatform pkgs.memtest86plus);
warnings = lib.optionals (config.boot.loader.systemd-boot.enable && config.hardware.deviceTree.package != null && config.hardware.deviceTree.name == null) [
("systemd-boot enabled on a device-tree-enabled system but without configuring hardware.deviceTree.name: " +
"system will boot against the platform firmware's .dtb instead of the kernel's more up-to-date dtb")
];
hardware.enableAllFirmware = true; # firmware with licenses that don't allow for redistribution. fuck lawyers, fuck IP, give me the goddamn firmware. hardware.enableAllFirmware = true; # firmware with licenses that don't allow for redistribution. fuck lawyers, fuck IP, give me the goddamn firmware.
# hardware.enableRedistributableFirmware = true; # proprietary but free-to-distribute firmware (extraneous to `enableAllFirmware` option) # hardware.enableRedistributableFirmware = true; # proprietary but free-to-distribute firmware (extraneous to `enableAllFirmware` option)

View File

@@ -79,7 +79,7 @@ lib.mkMerge [
(ifSshAuthorized (remoteHome "crappy" {})) (ifSshAuthorized (remoteHome "crappy" {}))
(ifSshAuthorized (remoteHome "desko" {})) (ifSshAuthorized (remoteHome "desko" {}))
(ifSshAuthorized (remoteHome "flowy" {})) (ifSshAuthorized (remoteHome "flowy" {}))
(ifSshAuthorized (remoteHome "lappy" {})) # (ifSshAuthorized (remoteHome "lappy" {}))
(ifSshAuthorized (remoteHome "moby" { host = "moby-hn"; })) (ifSshAuthorized (remoteHome "moby" { host = "moby-hn"; }))
(ifSshAuthorized (remoteHome "servo" {})) (ifSshAuthorized (remoteHome "servo" {}))
] ]

View File

@@ -32,13 +32,13 @@
lan-ip = "10.78.79.56"; lan-ip = "10.78.79.56";
}; };
sane.hosts.by-name."lappy" = { # sane.hosts.by-name."lappy" = {
ssh.user_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDpmFdNSVPRol5hkbbCivRhyeENzb9HVyf9KutGLP2Zu"; # ssh.user_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDpmFdNSVPRol5hkbbCivRhyeENzb9HVyf9KutGLP2Zu";
ssh.host_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILSJnqmVl9/SYQ0btvGb0REwwWY8wkdkGXQZfn/1geEc"; # ssh.host_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILSJnqmVl9/SYQ0btvGb0REwwWY8wkdkGXQZfn/1geEc";
wg-home.pubkey = "FTUWGw2p4/cEcrrIE86PWVnqctbv8OYpw8Gt3+dC/lk="; # wg-home.pubkey = "FTUWGw2p4/cEcrrIE86PWVnqctbv8OYpw8Gt3+dC/lk=";
wg-home.ip = "10.0.10.20"; # wg-home.ip = "10.0.10.20";
lan-ip = "10.78.79.53"; # lan-ip = "10.78.79.53";
}; # };
sane.hosts.by-name."moby" = { sane.hosts.by-name."moby" = {
# ssh.authorized = lib.mkDefault false; # moby's too easy to hijack: don't let it ssh places # ssh.authorized = lib.mkDefault false; # moby's too easy to hijack: don't let it ssh places

View File

@@ -6,8 +6,9 @@ let
# nixpkgs' pam hardcodes unix_chkpwd path to the /run/wrappers one, # nixpkgs' pam hardcodes unix_chkpwd path to the /run/wrappers one,
# but i don't want the wrapper, so undo that. # but i don't want the wrapper, so undo that.
# ideally i would patch this via an overlay, but pam is in the bootstrap so that forces a full rebuild. # ideally i would patch this via an overlay, but pam is in the bootstrap so that forces a full rebuild.
# see: <repo:nixos/nixpkgs:pkgs/by-name/li/linux-pam/package.nix>
postPatch = (upstream.postPatch or "") + '' postPatch = (upstream.postPatch or "") + ''
substituteInPlace modules/pam_unix/Makefile.am --replace-fail \ substituteInPlace modules/module-meson.build --replace-fail \
"/run/wrappers/bin/unix_chkpwd" "$out/bin/unix_chkpwd" "/run/wrappers/bin/unix_chkpwd" "$out/bin/unix_chkpwd"
''; '';
}); });
@@ -215,8 +216,10 @@ in
# - USB keyboards: "uhci_hcd" "ehci_hcd" "ehci_pci" "ohci_hcd" "ohci_pci" "xhci_hcd" "xhci_pci" "usbhid" "hid_generic" "hid_lenovo" "hid_apple" "hid_roccat" "hid_logitech_hidpp" "hid_logitech_dj" "hid_microsoft" "hid_cherry" "hid_corsair" # - USB keyboards: "uhci_hcd" "ehci_hcd" "ehci_pci" "ohci_hcd" "ohci_pci" "xhci_hcd" "xhci_pci" "usbhid" "hid_generic" "hid_lenovo" "hid_apple" "hid_roccat" "hid_logitech_hidpp" "hid_logitech_dj" "hid_microsoft" "hid_cherry" "hid_corsair"
# - LVM: "dm_mod" # - LVM: "dm_mod"
# - on x86 only: more keyboard stuff: "pcips2" "atkbd" "i8042" # - on x86 only: more keyboard stuff: "pcips2" "atkbd" "i8042"
#
boot.initrd.includeDefaultModules = lib.mkDefault false; # however, including these modules seems relatively *harmless*,
# and it makes bringup of new systems a bit easier.
# boot.initrd.includeDefaultModules = lib.mkDefault false;
# see: <repo:nixos/nixpkgs:nixos/modules/virtualisation/nixos-containers.nix> # see: <repo:nixos/nixpkgs:nixos/modules/virtualisation/nixos-containers.nix>
boot.enableContainers = lib.mkDefault false; boot.enableContainers = lib.mkDefault false;

View File

@@ -1194,6 +1194,10 @@ in
typescript-language-server.buildCost = 2; typescript-language-server.buildCost = 2;
typescript-language-server.sandbox.whitelistPwd = true; typescript-language-server.sandbox.whitelistPwd = true;
typescript-language-server.persist.byStore.ephemeral = [
".cache/typescript"
".npm" # .npm/{_cacache,_logs}
];
tumiki-fighters.buildCost = 1; tumiki-fighters.buildCost = 1;
tumiki-fighters.sandbox.whitelistAudio = true; tumiki-fighters.sandbox.whitelistAudio = true;

View File

@@ -216,6 +216,7 @@
./tcpdump.nix ./tcpdump.nix
./tor-browser.nix ./tor-browser.nix
./tuba.nix ./tuba.nix
./u-boot-pinephone-pro
./unl0kr ./unl0kr
./uptime.nix ./uptime.nix
./v4l-utils.nix ./v4l-utils.nix

View File

@@ -16,6 +16,7 @@
<dt><a href="https://en.wikipedia.org/wiki/Special:Search?search=%s" shortcuturl="w">Search Wikipedia <dt><a href="https://en.wikipedia.org/wiki/Special:Search?search=%s" shortcuturl="w">Search Wikipedia
<dt><a href="https://github.com/nixos/nixpkgs/pulls?q=%s" shortcuturl="pr">Search nixpkgs PRs <dt><a href="https://github.com/nixos/nixpkgs/pulls?q=%s" shortcuturl="pr">Search nixpkgs PRs
<dt><a href="https://github.com/search?type=repositories&q=%s" shortcuturl="gh">Search GitHub <dt><a href="https://github.com/search?type=repositories&q=%s" shortcuturl="gh">Search GitHub
<dt><a href="https://kagi.com/maps/infobox?q=%s" shortcuturl="maps">Search Kagi Maps
<dt><a href="https://kagi.com/search?q=%s" shortcuturl="kagi">Search with Kagi <dt><a href="https://kagi.com/search?q=%s" shortcuturl="kagi">Search with Kagi
<dt><a href="https://lib.rs/search?q=%s" shortcuturl="librs">Search lib.rs (Rust) <dt><a href="https://lib.rs/search?q=%s" shortcuturl="librs">Search lib.rs (Rust)
<dt><a href="https://myanimelist.net/search/all?cat=all&q=%s" shortcuturl="mal">Search MyAnimeList <dt><a href="https://myanimelist.net/search/all?cat=all&q=%s" shortcuturl="mal">Search MyAnimeList
@@ -35,7 +36,7 @@
<dt><a href="https://www.ebay.com/sch/i.html?_sacat=0&_nkw=%s" shortcuturl="ebay">Search eBay <dt><a href="https://www.ebay.com/sch/i.html?_sacat=0&_nkw=%s" shortcuturl="ebay">Search eBay
<dt><a href="https://www.etsy.com/search?q=%s" shortcuturl="etsy">Search Etsy <dt><a href="https://www.etsy.com/search?q=%s" shortcuturl="etsy">Search Etsy
<dt><a href="https://www.etymonline.com/search?q=%s" shortcuturl="etym">Search Etymonline <dt><a href="https://www.etymonline.com/search?q=%s" shortcuturl="etym">Search Etymonline
<dt><a href="https://www.google.com/maps/search/%s" shortcuturl="maps">Search Google Maps <dt><a href="https://www.google.com/maps/search/%s" shortcuturl="gmaps">Search Google Maps
<dt><a href="https://www.google.com/search?q=%s" shortcuturl="g">Search Google <dt><a href="https://www.google.com/search?q=%s" shortcuturl="g">Search Google
<dt><a href="https://www.google.com/search?q=%s&" shortcuturl="google">Search Google <dt><a href="https://www.google.com/search?q=%s&" shortcuturl="google">Search Google
<dt><a href="https://www.google.com/search?tbm=shop&q=%s" shortcuturl="shopping">Search Google Shopping <dt><a href="https://www.google.com/search?tbm=shop&q=%s" shortcuturl="shopping">Search Google Shopping

View File

@@ -43,6 +43,10 @@ in
"knowledge/secrets/accounts" "knowledge/secrets/accounts"
]; ];
# firefox learns about this package by looking in ~/.mozilla/native-messaging-hosts
fs.".mozilla/native-messaging-hosts/com.github.browserpass.native.json".symlink.target
= "${browserpass}//lib/mozilla/native-messaging-hosts/com.github.browserpass.native.json";
# TODO: env.PASSWORD_STORE_DIR only needs to be present within the browser session. # TODO: env.PASSWORD_STORE_DIR only needs to be present within the browser session.
# alternative to PASSWORD_STORE_DIR: # alternative to PASSWORD_STORE_DIR:
# fs.".password-store".symlink.target = "knowledge/secrets/accounts"; # fs.".password-store".symlink.target = "knowledge/secrets/accounts";

View File

@@ -16,7 +16,9 @@ let
cfg.addons cfg.addons
); );
addonSuggestedPrograms = lib.map (n: config.sane.programs."${n}") addonSuggestedProgramNames; addonSuggestedPrograms = lib.map (n: config.sane.programs."${n}") addonSuggestedProgramNames;
addonHomePaths = lib.concatMap (p: p.sandbox.extraHomePaths) (addonSuggestedPrograms ++ nativeMessagingPrograms); addonHomePaths = lib.concatMap
(p: p.sandbox.extraHomePaths ++ builtins.attrNames p.fs)
(addonSuggestedPrograms ++ nativeMessagingPrograms);
packageUnwrapped = let packageUnwrapped = let
unwrapped = pkgs.firefox-unwrapped // { unwrapped = pkgs.firefox-unwrapped // {
@@ -29,7 +31,8 @@ let
# inherit the default librewolf.cfg # inherit the default librewolf.cfg
# it can be further customized via ~/.librewolf/librewolf.overrides.cfg # it can be further customized via ~/.librewolf/librewolf.overrides.cfg
libName = "firefox"; libName = "firefox";
inherit nativeMessagingHosts; # XXX(2025-08-26): nativeMessagingHosts wrapping is broken! put things in ~/.mozilla/native-messaging-hosts/ instead.
# inherit nativeMessagingHosts;
nixExtensions = lib.concatMap (ext: lib.optional ext.enable ext.package) (builtins.attrValues cfg.addons); nixExtensions = lib.concatMap (ext: lib.optional ext.enable ext.package) (builtins.attrValues cfg.addons);

View File

@@ -143,9 +143,20 @@ defaultPref("browser.shell.checkDefaultBrowser", false);
// disable extension updates // disable extension updates
defaultPref("extensions.update.autoUpdateDefault", false); defaultPref("extensions.update.autoUpdateDefault", false);
defaultPref("extensions.update.enabled", false); defaultPref("extensions.update.enabled", false);
defaultPref("extensions.systemAddon.update.enabled", false);
// wipe the URIs used to check for updates, as a precaution. // wipe the URIs used to check for updates, as a precaution.
defaultPref("extensions.update.url", ""); defaultPref("extensions.update.url", "");
defaultPref("extensions.update.background.url", ""); defaultPref("extensions.update.background.url", "");
defaultPref("extensions.systemAddon.update.url", "");
// also disable app-level auto-updates
defaultPref("app.update.auto", false);
// disable "safe browsing", in which my browser asks Google whether a site is malicious or not, for every site i visit (?)
defaultPref("browser.safebrowsing.blockedURIs.enabled", false);
defaultPref("browser.safebrowsing.downloads.enabled", false);
defaultPref("browser.safebrowsing.malware.enabled", false);
defaultPref("browser.safebrowsing.phishing.enabled", false);
// browser.engagement.sidebar-button.has-used // browser.engagement.sidebar-button.has-used
// browser.migration.version = 150 // browser.migration.version = 150

View File

@@ -36,7 +36,8 @@
sandbox.extraPaths = [ sandbox.extraPaths = [
"/boot" "/boot"
"/mnt/desko" "/mnt/desko"
"/mnt/lappy" "/mnt/flowy"
# "/mnt/lappy"
"/mnt/moby" "/mnt/moby"
"/mnt/servo" "/mnt/servo"
# "nix" # "nix"

View File

@@ -67,12 +67,12 @@ in
viAlias = true; viAlias = true;
vimAlias = true; vimAlias = true;
plugins = plugin-packages; plugins = plugin-packages;
customRC = '' # customRC = ''
${builtins.readFile ./vimrc} # ${builtins.readFile ./vimrc}
""""" PLUGIN CONFIG # """"" PLUGIN CONFIG
${plugin-configs} # ${plugin-configs}
''; # '';
}; };
neovim-unwrapped' = with pkgs; neovim-unwrapped.overrideAttrs (upstream: { neovim-unwrapped' = with pkgs; neovim-unwrapped.overrideAttrs (upstream: {
# fix cross compilation: # fix cross compilation:
@@ -122,9 +122,17 @@ in
# due to <https://github.com/NixOS/nixpkgs/pull/344541> # due to <https://github.com/NixOS/nixpkgs/pull/344541>
rubyEnv = null; rubyEnv = null;
withRuby = false; withRuby = false;
wrapRc = false; #< don't force VIMINIT env var
postBuild = lib.replaceStrings [ "if ! $out/bin/nvim-wrapper " ] [ "if false " ] base.postBuild; postBuild = lib.replaceStrings [ "if ! $out/bin/nvim-wrapper " ] [ "if false " ] base.postBuild;
}); });
fs.".config/nvim/init.vim".symlink.text = ''
${builtins.readFile ./vimrc}
""""" PLUGIN CONFIG
${plugin-configs}
'';
# private because there could be sensitive things in the swap # private because there could be sensitive things in the swap
persist.byStore.private = [ ".cache/vim-swap" ]; persist.byStore.private = [ ".cache/vim-swap" ];
env.EDITOR = "vim"; env.EDITOR = "vim";

View File

@@ -1,3 +1,6 @@
" ENV VARS
" VIMINIT=/path/to/init.vim to use a different vimrc
" let the terminal handle mouse events, that way i get OS-level ctrl+shift+c/etc " let the terminal handle mouse events, that way i get OS-level ctrl+shift+c/etc
" this used to be default, until <https://github.com/neovim/neovim/pull/19290> " this used to be default, until <https://github.com/neovim/neovim/pull/19290>
set mouse= set mouse=

View File

@@ -1,4 +1,7 @@
{ config, pkgs, ... }: { config, lib, pkgs, ... }:
let
cfg = config.sane.programs.nvimpager;
in
{ {
sane.programs.nvimpager = { sane.programs.nvimpager = {
packageUnwrapped = (pkgs.nvimpager.override { packageUnwrapped = (pkgs.nvimpager.override {
@@ -10,6 +13,9 @@
suggestedPrograms = [ "neovim" ]; suggestedPrograms = [ "neovim" ];
sandbox.extraHomePaths = [
".config/nvim"
];
sandbox.whitelistWayland = true; # for system clipboard integration sandbox.whitelistWayland = true; # for system clipboard integration
env.MANPAGER = "nvimpager"; env.MANPAGER = "nvimpager";
@@ -21,4 +27,8 @@
env.MANWIDTH = "999"; env.MANWIDTH = "999";
env.MANROFFOPT = "-c"; env.MANROFFOPT = "-c";
}; };
sane.programs.man-db.sandbox.extraHomePaths = lib.mkIf cfg.enabled [
".config/nvim"
];
} }

View File

@@ -11,6 +11,10 @@ let
type = lib.types.bool; type = lib.types.bool;
inherit default description; inherit default description;
}; };
i3ipc = pkgs.python3Packages.i3ipc.overridePythonAttrs {
# XXX(2025-08-25): tests are broken; remove once fixed
doCheck = false;
};
playerctl = pkgs.playerctl.overrideAttrs (upstream: { playerctl = pkgs.playerctl.overrideAttrs (upstream: {
patches = (upstream.patches or []) ++ [ patches = (upstream.patches or []) ++ [
(pkgs.fetchpatch { (pkgs.fetchpatch {
@@ -108,6 +112,9 @@ in
packageUnwrapped = (pkgs.nwg-panel.override { packageUnwrapped = (pkgs.nwg-panel.override {
inherit playerctl; inherit playerctl;
python3Packages = pkgs.python3Packages // {
inherit i3ipc;
};
}).overrideAttrs (base: { }).overrideAttrs (base: {
# patches = (base.patches or []) ++ lib.optionals (!cfg.config.mediaPrevNext) [ # patches = (base.patches or []) ++ lib.optionals (!cfg.config.mediaPrevNext) [
# ./playerctl-no-prev-next.diff # ./playerctl-no-prev-next.diff

View File

@@ -0,0 +1,21 @@
{ config, lib, pkgs, ... }:
let
cfg = config.sane.programs.u-boot-pinephone-pro;
in
{
sane.programs.u-boot-pinephone-pro = {
packageUnwrapped = pkgs.runCommandNoCC "u-boot-pinephone-pro-program" {
preferLocalBuild = true;
} ''
install -Dm644 ${pkgs.u-boot-pinephone-pro}/idbloader.img $out/share/boot/idbloader.img
install -Dm644 ${pkgs.u-boot-pinephone-pro}/u-boot.itb $out/share/boot/u-boot.itb
install -Dm755 ${./install-u-boot} $out/bin/install-u-boot
# ln -sv $out/bin/install-u-boot $out/share/boot/install-u-boot
'';
sandbox.autodetectCliPaths = "existingFile";
};
environment.pathsToLink = lib.mkIf cfg.enabled [
"/share/boot"
];
}

View File

@@ -0,0 +1,25 @@
#!/bin/sh
set -eu
drive=$1
if ! [[ -e "$drive" ]]; then
echo "usage: install-u-boot /dev/sdX"
exit 1
fi
bootfiles_dir=
for d in ${XDG_DATA_DIRS//:/ }; do
if [[ -e "$d/boot/idbloader.img" ]] && [[ -e "$d/boot/u-boot.itb" ]]; then
bootfiles_dir=$d/boot
fi
done
if [[ -z "$bootfiles_dir" ]]; then
echo "boot/{idbloader.img,u-boot.itb} not found on XDG_DATA_DIRS"
exit 1
fi
set -x
dd if="$bootfiles_dir/idbloader.img" of="$drive" bs=512 seek=64 conv=notrunc,sync oflag=direct status=progress
dd if="$bootfiles_dir/u-boot.itb" of="$drive" bs=512 seek=16384 conv=notrunc,sync oflag=direct status=progress

View File

@@ -65,7 +65,8 @@
sandbox.extraPaths = [ sandbox.extraPaths = [
"/boot" "/boot"
"/mnt/desko" "/mnt/desko"
"/mnt/lappy" "/mnt/flowy"
# "/mnt/lappy"
"/mnt/moby" "/mnt/moby"
"/mnt/servo" "/mnt/servo"
# "nix" # "nix"

View File

@@ -116,9 +116,9 @@ in
# see: `man logind.conf` # see: `man logind.conf`
# dont shutdown when power button is short-pressed (commonly done an accident, or by cats). # dont shutdown when power button is short-pressed (commonly done an accident, or by cats).
# but do on long-press: useful to gracefully power-off server. # but do on long-press: useful to gracefully power-off server.
services.logind.powerKey = "lock"; services.logind.settings.Login.HandlePowerKey = "lock";
services.logind.powerKeyLongPress = "poweroff"; services.logind.settings.Login.HandlePowerKeyLongPress = "poweroff";
services.logind.lidSwitch = "lock"; services.logind.settings.Login.HandleLidSwitch = "lock";
# under logind, 'uaccess' tag would grant the logged in user access to a device. # under logind, 'uaccess' tag would grant the logged in user access to a device.
# outside logind, map uaccess tag -> plugdev group to grant that access. # outside logind, map uaccess tag -> plugdev group to grant that access.
services.udev.extraRules = '' services.udev.extraRules = ''

View File

@@ -11,6 +11,7 @@ in
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
# disable the following non-essential programs which fail to cross compile # disable the following non-essential programs which fail to cross compile
sane.programs.bash-language-server.enableFor = { system = false; user.colin = false; }; # bash neovim LSP: doesn't cross compile (2025-01-05; blocked by ShellCheck) sane.programs.bash-language-server.enableFor = { system = false; user.colin = false; }; # bash neovim LSP: doesn't cross compile (2025-01-05; blocked by ShellCheck)
sane.programs.cargo.enableFor = { system = false; user.colin = false; }; #< does not cross compile (2025-08-25)
sane.programs.fcitx5.enableFor.user.colin = false; #< does not cross compile (2025-01-05; blocked by qtsvg) sane.programs.fcitx5.enableFor.user.colin = false; #< does not cross compile (2025-01-05; blocked by qtsvg)
sane.programs.firefox.config.addons.browserpass-extension.enable = false; #< does not cross compile sane.programs.firefox.config.addons.browserpass-extension.enable = false; #< does not cross compile
sane.programs.lua-language-server.enableFor = { system = false; user.colin = false; }; # lua neovim LSP: doesn't cross compile (2025-01-06) sane.programs.lua-language-server.enableFor = { system = false; user.colin = false; }; # lua neovim LSP: doesn't cross compile (2025-01-06)
@@ -19,23 +20,16 @@ in
sane.programs.nix-tree.enableFor = { system = false; user.colin = false; }; #< does not cross compile (2025-01-05; blocked by vty) sane.programs.nix-tree.enableFor = { system = false; user.colin = false; }; #< does not cross compile (2025-01-05; blocked by vty)
sane.programs.pyright.enableFor = { system = false; user.colin = false; }; #< python neovim LSP: doesn't cross compile (2025-01-05; unblocked) sane.programs.pyright.enableFor = { system = false; user.colin = false; }; #< python neovim LSP: doesn't cross compile (2025-01-05; unblocked)
sane.programs.typescript-language-server.enableFor = { system = false; user.colin = false; }; #< doesn't cross compile (2025-07-18; via `moreutils`) sane.programs.typescript-language-server.enableFor = { system = false; user.colin = false; }; #< doesn't cross compile (2025-07-18; via `moreutils`)
sane.programs.vulkan-tools.enableFor = { system = false; user.colin = false; }; #< does not cross compile (2025-02-08)
boot.kernelPatches = [ boot.kernelPatches = lib.optionals (!pkgs.stdenv.hostPlatform.linux-kernel.preferBuiltin) [
{ {
# TODO: upstream into nixpkgs. <repo:nixos/nixpkgs:pkgs/os-specific/linux/kernel/common-config.nix> # TODO: upstream into nixpkgs. <repo:nixos/nixpkgs:pkgs/os-specific/linux/kernel/common-config.nix>
name = "fix-module-builtin-mismatch"; name = "fix-module-builtin-mismatch";
patch = null; patch = null;
structuredExtraConfig = with lib.kernel; { structuredExtraConfig = with lib.kernel; {
# nixpkgs specifies `SUN8I_DE2_CCU = yes`, but that in turn requires `SUNXI_CCU = yes` and NOT `= module` # nixpkgs specifies `SUN8I_DE2_CCU = yes`, but that in turn requires `SUNXI_CCU = yes` and NOT `= module`
# symptom: config fails to eval # symptom: Kconfig build fails
SUNXI_CCU = yes; SUNXI_CCU = yes;
# nixpkgs specifies `DRM = yes`, which causes `DRM_PANEL=y`.
# in <repo:kernel.org/linux:include/drm/drm_panel.h> they branch based on if `CONFIG_BACKLIGHT_DEVICE` is a *builtin*,
# hence we need to build it as a builtin to actually have a backlight!
# same logic happens with nixpkgs `DRM_FBDEV_EMULATION = yes` => implies `CONFIG_DRM_KMS_HELPER=y`
# and <repo:kernel.org/linux:include/drm/display/drm_dp_helper.h>
BACKLIGHT_CLASS_DEVICE = yes;
}; };
} }
]; ];

View File

@@ -40,16 +40,31 @@ in
# boot.kernelPackages = pkgs.linuxPackagesFor myCustomKernel; # boot.kernelPackages = pkgs.linuxPackagesFor myCustomKernel;
# boot.initrd.extraFiles."/lib".source = "${config.system.modulesTree}/lib"; # boot.initrd.extraFiles."/lib".source = "${config.system.modulesTree}/lib";
# docs (pinephone specific; tow-boot instead of u-boot but close enough): <https://github.com/Tow-Boot/Tow-Boot/tree/development/boards/pine64-pinephoneA64> # Pinephone Pro bootloader locations: <https://wiki.pine64.org/wiki/RK3399_boot_sequence#U-Boot_boot_sequence>
# we need space in the GPT header to place u-boot. # we need space in the GPT header to place u-boot.
# only actually need 1 MB, but better to over-allocate than under-allocate # only actually need 1 MB, but better to over-allocate than under-allocate
sane.image.extraGPTPadding = 16 * 1024 * 1024; # N.B.: the original PP expected idbloader to be at block 16.
sane.image.firstPartGap = 0; # PPP expects idbloader to be at block 64.
# GPT header ends at block 34, which means PPP can use an ordinary partition table
# just with the first partition starting at e.g. 16 MiB instead of block 34.
# sane.image.extraGPTPadding = 16 * 1024 * 1024 - 34 * 512;
# sane.image.firstPartGap = 0;
sane.image.installBootloader = '' sane.image.installBootloader = ''
dd if=${pkgs.u-boot-pinephone-pro}/idbloader.img of=$out bs=512 seek=64 oflag=direct conv=sync uboot_itb_bytes=$(stat --printf="%s" ${pkgs.u-boot-pinephone-pro}/u-boot.itb)
dd if=${pkgs.u-boot-pinephone-pro}/u-boot.itb of=$out bs=512 seek=16384 oflag=direct conv=sync uboot_ends=$(( $uboot_itb_bytes + 16384 * 512))
gap_ends=${builtins.toString config.sane.image.firstPartGap}
if ! (( $uboot_ends <= $gap_ends )); then
echo 'firstPartGap is too small to fit all of u-boot!'
false
fi
dd if=${pkgs.u-boot-pinephone-pro}/idbloader.img of=$out bs=512 seek=64 conv=notrunc
dd if=${pkgs.u-boot-pinephone-pro}/u-boot.itb of=$out bs=512 seek=16384 conv=notrunc
''; '';
sane.programs.sysadminUtils.suggestedPrograms = [
"u-boot-pinephone-pro"
];
sane.programs.alsa-ucm-conf.suggestedPrograms = [ sane.programs.alsa-ucm-conf.suggestedPrograms = [
"pine64-alsa-ucm" # upstreaming: https://github.com/alsa-project/alsa-ucm-conf/pull/375 "pine64-alsa-ucm" # upstreaming: https://github.com/alsa-project/alsa-ucm-conf/pull/375
]; ];
@@ -88,6 +103,10 @@ in
} }
]; ];
#v N.B.: deviceTree.name is plumbed through /boot/loader/entries/.
#v if removed, systemd-boot will still (likely) boot, but DTB items known to the kernel
#v and not to the platform firmware (u-boot) will be missing (e.g. rk818/battery monitoring).
hardware.deviceTree.name = "rockchip/rk3399-pinephone-pro.dtb";
hardware.deviceTree.overlays = [ hardware.deviceTree.overlays = [
{ {
name = "rk3399-pinephone-pro-battery"; name = "rk3399-pinephone-pro-battery";
@@ -209,9 +228,12 @@ in
# from <repo:nixos/nixpkgs:nixos/modules/system/boot/kernel.nix> AKA pkgs.aggregateModules # from <repo:nixos/nixpkgs:nixos/modules/system/boot/kernel.nix> AKA pkgs.aggregateModules
# but configured to **ignore collisions** # but configured to **ignore collisions**
system.modulesTree = lib.mkForce [( system.modulesTree = lib.mkForce [(
(pkgs.aggregateModules (pkgs.aggregateModules (
( config.boot.extraModulePackages ++ [ config.boot.kernelPackages.kernel ]) config.boot.extraModulePackages ++ [
).overrideAttrs { (lib.getOutput "modules" config.boot.kernelPackages.kernel)
]
)).overrideAttrs {
name = "kernel-modules-merged-sane";
# earlier items override the contents of later items # earlier items override the contents of later items
ignoreCollisions = true; ignoreCollisions = true;
# checkCollisionContents = false; # checkCollisionContents = false;

View File

@@ -104,7 +104,7 @@ in
# docs (pinephone specific; tow-boot instead of u-boot but close enough): <https://github.com/Tow-Boot/Tow-Boot/tree/development/boards/pine64-pinephoneA64> # docs (pinephone specific; tow-boot instead of u-boot but close enough): <https://github.com/Tow-Boot/Tow-Boot/tree/development/boards/pine64-pinephoneA64>
# we need space in the GPT header to place u-boot. # we need space in the GPT header to place u-boot.
# only actually need 1 MB, but better to over-allocate than under-allocate # only actually need 1 MB, but better to over-allocate than under-allocate
sane.image.extraGPTPadding = 16 * 1024 * 1024; sane.image.extraGPTPadding = 16 * 1024 * 1024 - 34 * 512;
sane.image.firstPartGap = 0; sane.image.firstPartGap = 0;
sane.image.installBootloader = '' sane.image.installBootloader = ''
dd if=${pkgs.u-boot-pinephone}/u-boot-sunxi-with-spl.bin of=$out bs=1024 seek=8 conv=notrunc dd if=${pkgs.u-boot-pinephone}/u-boot-sunxi-with-spl.bin of=$out bs=1024 seek=8 conv=notrunc

View File

@@ -7,6 +7,18 @@ in
sane.hal.rpi-400.enable = lib.mkEnableOption "Raspberry Pi 400 hardware support"; sane.hal.rpi-400.enable = lib.mkEnableOption "Raspberry Pi 400 hardware support";
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
sane.image.extraBootFiles = [ pkgs.bootpart-u-boot-rpi-aarch64 ]; sane.image.extraBootFiles = [
# rpi bootrom -> edk2 -> systemd-boot
# edk2 exists here to provide the base UEFI environment which systemd-boot expects
pkgs.bootpart-edk2-rpi
];
#v used by systemd-boot
hardware.deviceTree.name = "broadcom/bcm2711-rpi-400.dtb";
# XXX(2025-08-31): stock kernel boots to initrd, but appears (?) to fail to mount root:
# mmc0: invalid bus width
# mmc0: error -22 whilst initialising SD card
# linux_rpi4 seems to do the same...
# boot.kernelPackages = pkgs.linuxKernel.packages.linux_rpi4;
}; };
} }

View File

@@ -9,26 +9,26 @@ in
}; };
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
boot.initrd.availableKernelModules = [ # boot.initrd.availableKernelModules = [
"xhci_pci" "ahci" "sd_mod" "sdhci_pci" # nixos-generate-config defaults # "xhci_pci" "ahci" "sd_mod" "sdhci_pci" # nixos-generate-config defaults
"usb_storage" # rpi needed this to boot from usb storage, i think. # "usb_storage" # rpi needed this to boot from usb storage, i think.
"nvme" # to boot from nvme devices # "nvme" # to boot from nvme devices
# efi_pstore evivars # # efi_pstore evivars
# added (speculatively) 2024/05/21; these were implicitly being added by nixos/modules/system/boot/kernel.nix # # added (speculatively) 2024/05/21; these were implicitly being added by nixos/modules/system/boot/kernel.nix
# i've copied not all of them, but most # # i've copied not all of them, but most
"mmc_block" # "mmc_block"
"dm_mod" # "dm_mod"
# USB keyboards # # USB keyboards
"uhci_hcd" "ehci_hcd" "ehci_pci" "ohci_hcd" "ohci_pci" "xhci_hcd" "xhci_pci" "usbhid" "hid_generic" "hid_lenovo" "hid_apple" "hid_roccat" "hid_logitech_hidpp" "hid_logitech_dj" "hid_microsoft" "hid_cherry" "hid_corsair" # "uhci_hcd" "ehci_hcd" "ehci_pci" "ohci_hcd" "ohci_pci" "xhci_hcd" "xhci_pci" "usbhid" "hid_generic" "hid_lenovo" "hid_apple" "hid_roccat" "hid_logitech_hidpp" "hid_logitech_dj" "hid_microsoft" "hid_cherry" "hid_corsair"
# x86 keyboard stuff # # x86 keyboard stuff
"pcips2" "atkbd" "i8042" # "pcips2" "atkbd" "i8042"
# stage-2 init needs rtc? # # stage-2 init needs rtc?
"rtc_cmos" # "rtc_cmos"
]; # ];
hardware.cpu.amd.updateMicrocode = true; # desko hardware.cpu.amd.updateMicrocode = true; # desko
hardware.cpu.intel.updateMicrocode = true; # lappy hardware.cpu.intel.updateMicrocode = true; # flowy, lappy
boot.extraModprobeConfig = '' boot.extraModprobeConfig = ''
# allow nested virtualization. XXX(2025-06-24): required for my work (?) # allow nested virtualization. XXX(2025-06-24): required for my work (?)
@@ -37,7 +37,5 @@ in
options kvm_amd nested=1 options kvm_amd nested=1
options kvm_intel nested=1 options kvm_intel nested=1
''; '';
sane.image.extraBootFiles = [ pkgs.bootpart-systemd-boot ];
}; };
} }

View File

@@ -280,8 +280,11 @@ in
bootFsImg bootFsImg
nixFsImg nixFsImg
]; ];
firstPartGap = cfg.firstPartGap; inherit (cfg)
sectorSize = cfg.sectorSize; firstPartGap
sectorSize
extraGPTPadding
;
passthru = { passthru = {
inherit bootFsImg nixFsImg; inherit bootFsImg nixFsImg;
}; };
@@ -307,8 +310,9 @@ in
mkdir -p $out mkdir -p $out
# 34 is the base GPT header size, as added to -p by cgpt. # 34 is the base GPT header size, as added to -p by cgpt.
# more precisely: PMBR (1 block) + Primary GPT header (1 block) + Primary GPT Table (32 blocks)
gptSize=$((34*512)) gptSize=$((34*512))
part0Start=$(( $gptSize + $firstPartGap )) part0Start=$(( $extraGPTPadding + $gptSize + $firstPartGap ))
( (
# solve for the size of the disk image # solve for the size of the disk image
@@ -326,11 +330,11 @@ in
truncate -s $totalSize $out/disk.img truncate -s $totalSize $out/disk.img
# Zeroes the GPT # Zeroes the GPT
cgpt create -z $out/disk.img ( set -x ; cgpt create -z $out/disk.img )
# Create the GPT with space if desired # Create the GPT, optionally with some extra padding between the primary GPT header and the primary GPT table
cgpt create -p 0 $out/disk.img ( set -x ; cgpt create -p $(( $extraGPTPadding / $sectorSize )) $out/disk.img )
# Add the PMBR # Add the PMBR
cgpt boot -p $out/disk.img ( set -x ; cgpt boot -p $out/disk.img )
) )
( (
@@ -376,9 +380,10 @@ in
'' else '' '' else ''
cp ${img}/disk.img $out cp ${img}/disk.img $out
chmod +w $out chmod +w $out
set -x (
${cfg.installBootloader} set -x
set +x ${cfg.installBootloader}
)
chmod -w $out chmod -w $out
'' ''
); );
@@ -390,13 +395,15 @@ in
'') '')
] ]
++ ++
lib.optionals config.boot.loader.systemd-boot.enable [ lib.optionals config.boot.loader.systemd-boot.enable ([
pkgs.bootpart-systemd-boot
# it'd be cool to use `config.system.build.installBootLoader` to install both the bootloader config AND the bootloader itself, # it'd be cool to use `config.system.build.installBootLoader` to install both the bootloader config AND the bootloader itself,
# but the combination of custom nixpkgs logic + systemd's sanity checking makes it near impossible to use # but the combination of custom nixpkgs logic + systemd's sanity checking makes it near impossible to use
# outside a live system. # outside a live system.
# so manually generate a bootloader entry: # so manually generate a bootloader entry:
(pkgs.runCommandLocal "populate-systemd-boot" {} '' (pkgs.runCommandLocal "populate-systemd-boot" {} ''
toplevel=${config.system.build.toplevel} toplevel=${config.system.build.toplevel}
dtbpath=${if config.hardware.deviceTree.name != null then config.hardware.deviceTree.name else ""}
kernel_params=$(cat "$toplevel/kernel-params") kernel_params=$(cat "$toplevel/kernel-params")
kernel=$(readlink "$toplevel/kernel") kernel=$(readlink "$toplevel/kernel")
@@ -411,14 +418,25 @@ in
efi_initrd="/EFI/nixos/$initrd_name.efi" efi_initrd="/EFI/nixos/$initrd_name.efi"
install -Dm644 "$initrd" "$out/$efi_initrd" install -Dm644 "$initrd" "$out/$efi_initrd"
efi_dtb=
if [ -n "$dtbpath" ]; then
dtbs=$(readlink "$toplevel/dtbs")
dtbs_name="''${dtbs/\/nix\/store\//}"
dtbs_name="''${dtbs_name/\//-}"
# nixos-generated devicetree path is relative to /boot instead of being fully qualified, for some reason.
efi_dtb="EFI/nixos/$dtbs_name-$(basename $dtbpath).efi"
install -Dm644 "$dtbs/$dtbpath" "$out/$efi_dtb"
fi
mkdir -p $out/loader/entries mkdir -p $out/loader/entries
cat > $out/loader/entries/nixos-generation-0.conf <<EOF cat > $out/loader/entries/nixos-generation-0.conf <<EOF
title NixOS title NixOS
sort-key nixos sort-key nixos
version Generation 0 NixOS version Generation 0 NixOS
linux $efi_kernel linux $efi_kernel
initrd $initrd initrd $efi_initrd
options init=$toplevel/init $kernel_params options init=$toplevel/init $kernel_params
''${efi_dtb:+devicetree $efi_dtb}
EOF EOF
cat > $out/loader/loader.conf <<EOF cat > $out/loader/loader.conf <<EOF
timeout 5 timeout 5
@@ -426,7 +444,7 @@ in
console-mode keep console-mode keep
EOF EOF
'') '')
] ])
; ;
}; };
} }

View File

@@ -1,39 +1,6 @@
# outstanding cross-compilation PRs/issues: # tracking:
# - all: <https://github.com/NixOS/nixpkgs/labels/6.topic%3A%20cross-compilation> # - all cross compilation PRs: <https://github.com/NixOS/nixpkgs/labels/6.topic%3A%20cross-compilation>
# - qtsvg mixed deps: <https://github.com/NixOS/nixpkgs/issues/269756> # - potential idiom to fix cross cargo-inside-meson: <https://github.com/NixOS/nixpkgs/pull/434878>
# - big Qt fix: <https://github.com/NixOS/nixpkgs/pull/267311>
#
# outstanding issues:
# - 2023/10/10: build python3 is pulled in by many things
# - nix why-depends --all /nix/store/8g3kd2jxifq10726p6317kh8srkdalf5-nixos-system-moby-23.11.20231011.dirty /nix/store/pzf6dnxg8gf04xazzjdwarm7s03cbrgz-python3-3.10.12/bin/python3.10
# - gstreamer-vaapi -> gstreamer-dev -> glib-dev
# - portfolio -> {glib,cairo,pygobject}-dev
# - komikku -> python3.10-brotlicffi -> python3.10-cffi
# - many others. python3.10-cffi seems to be the offender which infects 70% of consumers though
# - 2023/10/11: build ruby is pulled in by `neovim`:
# - nix why-depends --all /nix/store/rhli8vhscv93ikb43639c2ysy3a6dmzp-nixos-system-moby-23.11.20231011.30c7fd8 /nix/store/5xbwwbyjmc1xvjzhghk6r89rn4ylidv8-ruby-3.1.4
# - 2023/12/19: rustPlatform.cargoSetupHook outside of `buildRustPackage` or python packages is a mess
# - it doesn't populate `.cargo/config` with valid cross-compilation config
# - something to do with the way it's spliced: `nativeBuildInputs = [ rustPlatform.cargoSetupHook.__spliced.hostHost ]` (or hostTarget) WORKS
# - see <https://github.com/NixOS/nixpkgs/pull/260068> -- it's probably wrong.
# - WIP fix in `pr-cross-cargo`/`pr-cross-cargo2` nixpkgs branch.
# - sanity check by building `pkgsCross.aarch64-multiplatform.rav1e`, and the `fd` program mentioned in PR 260068
# - `pkgsCross.musl64.fd`
# - `pkgsStatic.fd`
# - this is way too tricky to enable cross compilation without breaking the musl stuff.
# - i lost a whole day trying to get it to work: don't do it!
#
# partially fixed:
# - 2023/10/11: build coreutils pulled in by rpm 4.18.1, but NOT by 4.19.0
# - nix why-depends --all /nix/store/gjwd2x507x7gjycl5q0nydd39d3nkwc5-dtrx-8.5.3-aarch64-unknown-linux-gnu /nix/store/y9gr7abwxvzcpg5g73vhnx1fpssr5frr-coreutils-9.3
#
# outstanding issues for software i don't have deployed:
# - gdk-pixbuf doesn't generate `gdk-pixbuf-thumbnailer` on cross
# - been this way since 2018: <https://gitlab.gnome.org/GNOME/gdk-pixbuf/-/merge_requests/20>
# - as authored upstream, thumbnailer depends on loader.cache, and neither are built during cross compilation.
# - nixos manually builds loader.cache in postInstall (via emulator).
# - even though we have loader.cache, ordering means that thumbnailer still can't be built.
# - solution is probably to integrate meson's cross_file stuff, and pushing all this emulation upstream.
final: prev: final: prev:
let let
@@ -85,63 +52,63 @@ let
typelibPath = pkgs: lib.concatStringsSep ":" (builtins.map (p: "${lib.getLib p}/lib/girepository-1.0") pkgs); typelibPath = pkgs: lib.concatStringsSep ":" (builtins.map (p: "${lib.getLib p}/lib/girepository-1.0") pkgs);
# `cargo` which adds the correct env vars and `--target` flag when invoked from meson build scripts # `cargo` which adds the correct env vars and `--target` flag when invoked from meson build scripts
crossCargo = let # crossCargo = let
inherit (final.pkgsBuildHost) cargo; # inherit (final.pkgsBuildHost) cargo;
inherit (final.rust.envVars) setEnv rustHostPlatformSpec; # inherit (final.rust.envVars) setEnv rustHostPlatformSpec;
in (final.pkgsBuildBuild.writeShellScriptBin "cargo" '' # in (final.pkgsBuildBuild.writeShellScriptBin "cargo" ''
targetDir=target # targetDir=target
isFlavored= # isFlavored=
outDir= # outDir=
profile= # profile=
cargoArgs=("$@") # cargoArgs=("$@")
nextIsOutDir= # nextIsOutDir=
nextIsProfile= # nextIsProfile=
nextIsTargetDir= # nextIsTargetDir=
for arg in "''${cargoArgs[@]}"; do # for arg in "''${cargoArgs[@]}"; do
if [[ -n "$nextIsOutDir" ]]; then # if [[ -n "$nextIsOutDir" ]]; then
nextIsOutDir= # nextIsOutDir=
outDir="$arg" # outDir="$arg"
elif [[ -n "$nextIsProfile" ]]; then # elif [[ -n "$nextIsProfile" ]]; then
nextIsProfile= # nextIsProfile=
profile="$arg" # profile="$arg"
elif [[ -n "$nextIsTargetDir" ]]; then # elif [[ -n "$nextIsTargetDir" ]]; then
nextIsTargetDir= # nextIsTargetDir=
targetDir="$arg" # targetDir="$arg"
elif [[ "$arg" = "build" ]]; then # elif [[ "$arg" = "build" ]]; then
isFlavored=1 # isFlavored=1
elif [[ "$arg" = "--out-dir" ]]; then # elif [[ "$arg" = "--out-dir" ]]; then
nextIsOutDir=1 # nextIsOutDir=1
elif [[ "$arg" = "--profile" ]]; then # elif [[ "$arg" = "--profile" ]]; then
nextIsProfile=1 # nextIsProfile=1
elif [[ "$arg" = "--release" ]]; then # elif [[ "$arg" = "--release" ]]; then
profile=release # profile=release
elif [[ "$arg" = "--target-dir" ]]; then # elif [[ "$arg" = "--target-dir" ]]; then
nextIsTargetDir=1 # nextIsTargetDir=1
fi # fi
done # done
extraFlags=() # extraFlags=()
# not all subcommands support flavored arguments like `--target` # # not all subcommands support flavored arguments like `--target`
if [ -n "$isFlavored" ]; then # if [ -n "$isFlavored" ]; then
# pass the target triple to cargo so it will cross compile # # pass the target triple to cargo so it will cross compile
# and fix so it places outputs in the same directory as non-cross, see: <https://doc.rust-lang.org/cargo/guide/build-cache.html> # # and fix so it places outputs in the same directory as non-cross, see: <https://doc.rust-lang.org/cargo/guide/build-cache.html>
extraFlags+=( # extraFlags+=(
--target "${rustHostPlatformSpec}" # --target "${rustHostPlatformSpec}"
-Z unstable-options # -Z unstable-options
) # )
if [ -z "$outDir" ]; then # if [ -z "$outDir" ]; then
extraFlags+=( # extraFlags+=(
--out-dir "$targetDir"/''${profile:-debug} # --out-dir "$targetDir"/''${profile:-debug}
) # )
fi # fi
fi # fi
exec ${setEnv} "${lib.getExe cargo}" "$@" "''${extraFlags[@]}" # exec ${setEnv} "${lib.getExe cargo}" "$@" "''${extraFlags[@]}"
'').overrideAttrs { # '').overrideAttrs {
inherit (cargo) meta; # inherit (cargo) meta;
}; # };
in with final; { in with final; {
# binutils = prev.binutils.override { # binutils = prev.binutils.override {
# # fix that resulting binary files would specify build #!sh as their interpreter. # # fix that resulting binary files would specify build #!sh as their interpreter.
@@ -153,7 +120,7 @@ in with final; {
# }; # };
# 2025/07/27: upstreaming is unblocked, but a cleaner solution than this doesn't seem to exist yet # 2025/08/31: upstreaming is unblocked, but a cleaner solution than this doesn't seem to exist yet
confy = prev.confy.overrideAttrs (upstream: { confy = prev.confy.overrideAttrs (upstream: {
# meson's `python.find_installation` method somehow just doesn't support cross compilation. # meson's `python.find_installation` method somehow just doesn't support cross compilation.
# - <https://mesonbuild.com/Python-module.html#find_installation> # - <https://mesonbuild.com/Python-module.html#find_installation>
@@ -171,10 +138,10 @@ in with final; {
''; '';
}); });
# 2025/07/27: upstreaming is unblocked # 2025/08/26: upstreaming is unblocked, on desko branch `pr-delfin-cross`
delfin = prev.delfin.override { # delfin = prev.delfin.override {
cargo = crossCargo; # cargo = crossCargo;
}; # };
# 2025/07/27: upstreaming is unblocked # 2025/07/27: upstreaming is unblocked
# dtrx = prev.dtrx.override { # dtrx = prev.dtrx.override {
@@ -185,18 +152,18 @@ in with final; {
# binutils = binutils-unwrapped; # binutils = binutils-unwrapped;
# }; # };
# 2025/07/27: upstreaming is unblocked # envelope = prev.envelope.override {
# cargo = crossCargo;
# };
# 2025/08/31: upstreaming is blocked on mailutils -> gss -> shishi
# emacs = prev.emacs.override { # emacs = prev.emacs.override {
# nativeComp = false; # will be renamed to `withNativeCompilation` in future # nativeComp = false; # will be renamed to `withNativeCompilation` in future
# # future: we can specify 'action-if-cross-compiling' to actually invoke the test programs: # # future: we can specify 'action-if-cross-compiling' to actually invoke the test programs:
# # <https://www.gnu.org/software/autoconf/manual/autoconf-2.63/html_node/Runtime.html> # # <https://www.gnu.org/software/autoconf/manual/autoconf-2.63/html_node/Runtime.html>
# }; # };
envelope = prev.envelope.override { # 2025/08/31: upstreaming is unblocked
cargo = crossCargo; #< fixes openssl not being able to find its library
};
# 2025/07/27: upstreaming is unblocked
# firejail = prev.firejail.overrideAttrs (upstream: { # firejail = prev.firejail.overrideAttrs (upstream: {
# # firejail executes its build outputs to produce the default filter list. # # firejail executes its build outputs to produce the default filter list.
# # i think we *could* copy the default filters from pkgsBuildBuild, but that doesn't seem future proof # # i think we *could* copy the default filters from pkgsBuildBuild, but that doesn't seem future proof
@@ -210,7 +177,7 @@ in with final; {
# ''); # '');
# }); # });
# 2025/07/27: upstreaming is unblocked # 2025/08/31: upstreaming is unblocked
# flare-signal = prev.flare-signal.overrideAttrs (upstream: { # flare-signal = prev.flare-signal.overrideAttrs (upstream: {
# env = let # env = let
# inherit buildPackages stdenv rust; # inherit buildPackages stdenv rust;
@@ -232,21 +199,16 @@ in with final; {
# }; # };
# }); # });
# 2025/07/27: upstreaming is blocked by glycin-loaders # 2025/08/26: upstreaming is unblocked, out for PR: <https://github.com/NixOS/nixpkgs/pull/437038>
fractal = prev.fractal.override { # fractal = prev.fractal.override {
cargo = crossCargo; # cargo = crossCargo;
}; # };
# 2025/07/27: upstreaming is unblocked
glycin-loaders = prev.glycin-loaders.override {
cargo = crossCargo;
};
# 2025/07/27: upstreaming is blocked on gnome-shell # 2025/07/27: upstreaming is blocked on gnome-shell
# fixes: "gdbus-codegen not found or executable" # fixes: "gdbus-codegen not found or executable"
# gnome-session = mvToNativeInputs [ glib ] super.gnome-session; # gnome-session = mvToNativeInputs [ glib ] super.gnome-session;
# 2025/07/27: upstreaming is blocked on ibus, evolution-data-server -> gnome-online-accounts -> gvfs -> ... # 2025/08/31: upstreaming is blocked on evolution-data-server -> gnome-online-accounts -> gvfs -> ... -> ruby
# gnome-shell = super.gnome-shell.overrideAttrs (orig: { # gnome-shell = super.gnome-shell.overrideAttrs (orig: {
# # fixes "meson.build:128:0: ERROR: Program 'gjs' not found or not executable" # # fixes "meson.build:128:0: ERROR: Program 'gjs' not found or not executable"
# # does not fix "_giscanner.cpython-310-x86_64-linux-gnu.so: cannot open shared object file: No such file or directory" (python import failure) # # does not fix "_giscanner.cpython-310-x86_64-linux-gnu.so: cannot open shared object file: No such file or directory" (python import failure)
@@ -271,11 +233,6 @@ in with final; {
# ]; # ];
# }); # });
# 2025/07/27: upstreaming is unblocked
gnome-user-share = prev.gnome-user-share.override {
cargo = crossCargo;
};
# 2025/07/27: upstreaming is unblocked # 2025/07/27: upstreaming is unblocked
# # gnustep is going to need a *lot* of work/domain-specific knowledge to truly cross-compile, # # gnustep is going to need a *lot* of work/domain-specific knowledge to truly cross-compile,
# gnustep-base = prev.gnustep-base.overrideAttrs (upstream: { # gnustep-base = prev.gnustep-base.overrideAttrs (upstream: {
@@ -331,14 +288,7 @@ in with final; {
# nativeBuildInputs = lib.remove [ qt6.wrapQtAppsHook ] upstream.nativeBuildInputs; # nativeBuildInputs = lib.remove [ qt6.wrapQtAppsHook ] upstream.nativeBuildInputs;
# }); # });
# 2025/07/27: upstreaming is unblocked -- but is this necessary? # lemoa = prev.lemoa.override { cargo = crossCargo; };
# koreader = prev.koreader.overrideAttrs (upstream: {
# nativeBuildInputs = upstream.nativeBuildInputs ++ [
# autoPatchelfHook
# ];
# });
lemoa = prev.lemoa.override { cargo = crossCargo; };
# libsForQt5 = prev.libsForQt5.overrideScope (self: super: { # libsForQt5 = prev.libsForQt5.overrideScope (self: super: {
# # 2025/07/27: upstreaming is blocked on qtsvg # # 2025/07/27: upstreaming is blocked on qtsvg
@@ -354,11 +304,6 @@ in with final; {
# callPackage = self.newScope { inherit (self) qtCompatVersion qtModule srcs; inherit stdenv; }; # callPackage = self.newScope { inherit (self) qtCompatVersion qtModule srcs; inherit stdenv; };
# }); # });
# 2025/07/27: upstreaming blocked on glycin-loaders
loupe = prev.loupe.override {
cargo = crossCargo;
};
# 2024/11/19: upstreaming is unblocked # 2024/11/19: upstreaming is unblocked
mepo = (prev.mepo.override { mepo = (prev.mepo.override {
# nixpkgs mepo correctly puts `zig_0_13.hook` in nativeBuildInputs, # nixpkgs mepo correctly puts `zig_0_13.hook` in nativeBuildInputs,
@@ -397,46 +342,6 @@ in with final; {
# 2025/07/27: upstreaming is unblocked by deps; but turns out to not be this simple # 2025/07/27: upstreaming is unblocked by deps; but turns out to not be this simple
# ncftp = addNativeInputs [ bintools ] prev.ncftp; # ncftp = addNativeInputs [ bintools ] prev.ncftp;
# 2025/07/27: upstreaming is unblocked
newsflash = (prev.newsflash.override {
cargo = crossCargo;
}).overrideAttrs (upstream: {
postPatch = (upstream.postPatch or "") + ''
rm build.rs
export OUT_DIR=$(pwd)
# from build.rs:
glib-compile-resources --sourcedir=data/resources --target=icons.gresource data/resources/icons.gresource.xml
glib-compile-resources --sourcedir=data/resources --target=styles.gresource data/resources/styles.gresource.xml
substitute data/io.gitlab.news_flash.NewsFlash.appdata.xml.in.in \
data/resources/io.gitlab.news_flash.NewsFlash.appdata.xml \
--replace-fail '@appid@' 'io.gitlab.news_flash.NewsFlash'
glib-compile-resources --sourcedir=data/resources --target=appdata.gresource data/resources/appdata.gresource.xml
'';
env = let
ccForBuild = "${buildPackages.stdenv.cc}/bin/${buildPackages.stdenv.cc.targetPrefix}cc";
cxxForBuild = "${buildPackages.stdenv.cc}/bin/${buildPackages.stdenv.cc.targetPrefix}c++";
ccForHost = "${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc";
cxxForHost = "${stdenv.cc}/bin/${stdenv.cc.targetPrefix}c++";
rustBuildPlatform = stdenv.buildPlatform.rust.rustcTarget;
rustTargetPlatform = stdenv.hostPlatform.rust.rustcTarget;
in (upstream.env or {}) // {
# taken from <pkgs/build-support/rust/hooks/default.nix>
# fixes "cargo:warning=aarch64-unknown-linux-gnu-gcc: error: unrecognized command-line option -m64"
# XXX: these aren't necessarily valid environment variables: the referenced nix file is more clever to get them to work.
"CC_${rustBuildPlatform}" = "${ccForBuild}";
"CXX_${rustBuildPlatform}" = "${cxxForBuild}";
"CC_${rustTargetPlatform}" = "${ccForHost}";
"CXX_${rustTargetPlatform}" = "${cxxForHost}";
# fails to fix "Failed to find OpenSSL development headers."
# OPENSSL_NO_VENDOR = 1;
# OPENSSL_LIB_DIR = "${lib.getLib openssl}/lib";
# OPENSSL_DIR = "${lib.getDev openssl}";
};
});
# fixes "properties/gresource.xml: Permission denied" # fixes "properties/gresource.xml: Permission denied"
# - by providing glib-compile-resources # - by providing glib-compile-resources
# 2025/07/27: upstreaming is blocked on gst-plugins-good, qtkeychain, qtmultimedia, qtquick3d, qt-jdenticon # 2025/07/27: upstreaming is blocked on gst-plugins-good, qtkeychain, qtmultimedia, qtquick3d, qt-jdenticon
@@ -506,7 +411,7 @@ in with final; {
# # buildInputs = lib.remove gnupg upstream.buildInputs; # # buildInputs = lib.remove gnupg upstream.buildInputs;
# }); # });
# 2025/07/27: upstreaming is unblocked, but most of this belongs in _oils_ repo # 2025/08/31: upstreaming is unblocked, but most of this belongs in _oils_ repo
oils-for-unix = prev.oils-for-unix.overrideAttrs (upstream: { oils-for-unix = prev.oils-for-unix.overrideAttrs (upstream: {
postPatch = (upstream.postPatch or "") + '' postPatch = (upstream.postPatch or "") + ''
substituteInPlace _build/oils.sh \ substituteInPlace _build/oils.sh \
@@ -530,10 +435,10 @@ in with final; {
]; ];
}); });
# 2025/07/27: upstreaming is blocked on gnome-user-share, nautilus # 2025/08/31: upstreaming is unblocked; out for review: <https://github.com/NixOS/nixpkgs/pull/437704>
papers = prev.papers.override { # papers = prev.papers.override {
cargo = crossCargo; # cargo = crossCargo;
}; # };
# 2025/07/27: upstreaming is blocked on gnome-session (itself blocked on gnome-shell) # 2025/07/27: upstreaming is blocked on gnome-session (itself blocked on gnome-shell)
# phosh = prev.phosh.overrideAttrs (upstream: { # phosh = prev.phosh.overrideAttrs (upstream: {
@@ -561,11 +466,6 @@ in with final; {
# ]; # ];
# } prev.phosh-mobile-settings; # } prev.phosh-mobile-settings;
# 2025/07/27: upstreaming is unblocked
pwvucontrol = prev.pwvucontrol.override {
cargo = crossCargo;
};
# pythonPackagesExtensions = prev.pythonPackagesExtensions ++ [ # pythonPackagesExtensions = prev.pythonPackagesExtensions ++ [
# (pyself: pysuper: { # (pyself: pysuper: {
# # 2025/07/23: upstreaming is unblocked, but solution is untested. # # 2025/07/23: upstreaming is unblocked, but solution is untested.
@@ -728,16 +628,16 @@ in with final; {
# # ''; # # '';
# }); # });
# 2025/07/27: upstreaming is blocked on glycin-loaders # 2025/08/26: upstreaming is unblocked; implemented on desko `pr-snapshot-cross` branch
snapshot = prev.snapshot.override { # snapshot = prev.snapshot.override {
# fixes "error: linker `cc` not found" # # fixes "error: linker `cc` not found"
cargo = crossCargo; # cargo = crossCargo;
}; # };
# 2025/07/27: upstreaming is unblocked # 2025/08/26: upstreaming is unblocked; patched on desko branch `pr-spot-cross`
spot = prev.spot.override { # spot = prev.spot.override {
cargo = crossCargo; # cargo = crossCargo;
}; # };
# 2025/07/27: upstreaming is unblocked # 2025/07/27: upstreaming is unblocked
# squeekboard = prev.squeekboard.overrideAttrs (upstream: { # squeekboard = prev.squeekboard.overrideAttrs (upstream: {
@@ -783,7 +683,7 @@ in with final; {
# ]; # ];
# }); # });
# 2025/07/27: upstreaming blocked on gvfs -> udisks -> libblockdev -> {thin-provisioning-tools,libndctl -> ... -> ruby} # 2025/08/31: upstreaming blocked on gvfs -> udisks -> libblockdev -> {thin-provisioning-tools,libndctl -> ... -> ruby}
swaynotificationcenter = mvToNativeInputs [ buildPackages.wayland-scanner ] prev.swaynotificationcenter; swaynotificationcenter = mvToNativeInputs [ buildPackages.wayland-scanner ] prev.swaynotificationcenter;
# 2025/07/27: upstreaming is unblocked # 2025/07/27: upstreaming is unblocked
@@ -834,10 +734,10 @@ in with final; {
# }); # });
# }; # };
# 2025/05/01: upstreaming is unblocked # 2025/08/26: upstreaming is unblocked; implemented on desko branch `pr-video-trimmer-cross`
video-trimmer = prev.video-trimmer.override { # video-trimmer = prev.video-trimmer.override {
cargo = crossCargo; # cargo = crossCargo;
}; # };
# 2025/01/13: upstreaming is blocked on arrow-cpp, python-pyarrow, python-contourpy, python-matplotlib, python-h5py, python-pandas, google-cloud-cpp # 2025/01/13: upstreaming is blocked on arrow-cpp, python-pyarrow, python-contourpy, python-matplotlib, python-h5py, python-pandas, google-cloud-cpp
# visidata = prev.visidata.override { # visidata = prev.visidata.override {

View File

@@ -23,7 +23,7 @@ in
# DISABLE HDCP BLOB in pinephone pro. # DISABLE HDCP BLOB in pinephone pro.
# this is used by u-boot; requires redeploying the bootloader (the SPL, specifically). # this is used by u-boot; requires redeploying the bootloader (the SPL, specifically).
# i can see that nixpkgs does process this option, but the hash of bl31.elf doesn't actually change # i can see that nixpkgs does process this option, but the hash of bl31.elf doesn't actually change
arm-trusted-firmware = super.arm-trusted-firmware.override { buildArmTrustedFirmware = super.buildArmTrustedFirmware.override {
unfreeIncludeHDCPBlob = false; unfreeIncludeHDCPBlob = false;
}; };

View File

@@ -0,0 +1,14 @@
# sourced, with modifications, from <https://github.com/pftf/RPi4/blob/master/config.txt>
arm_64bit=1
# arm_boost=1
# N.B.: `enable_uart=1` is required for systemd-boot's `timeout` (i.e. auto-boot default entry) feature
enable_uart=1
# uart_2ndstage=1
enable_gic=1
armstub=RPI_EFI.fd
# disable_commandline_tags=1
# disable_overscan=1
# device_tree_address=0x3e0000
# device_tree_end=0x400000
# dtoverlay=miniuart-bt
# dtoverlay=upstream-pi4

View File

@@ -0,0 +1,30 @@
{
edk2-rpi4,
raspberrypifw,
runCommandLocal,
}:
runCommandLocal "bootpart-edk2-rpi" {
meta = {
description = ''
unmanaged files to place in /boot on a Raspberry Pi 400 system.
these files are not enough on their own to boot a kernel,
but only to boot an EFI application.
best paired with systemd-boot (via `bootpart-systemd-boot`), or perhaps u-boot (untested).
'';
platforms = [
"aarch64-linux"
];
};
} ''
install -Dm644 ${edk2-rpi4}/RPI_EFI.fd $out/RPI_EFI.fd
install -Dm644 ${./config.txt} $out/config.txt
install -Dm644 ${raspberrypifw}/share/raspberrypi/boot/fixup4.dat $out/fixup4.dat
install -Dm644 ${raspberrypifw}/share/raspberrypi/boot/start4.elf $out/start4.elf
# N.B.: there are weird incompatibilities between raspberrypifw (start4.elf) and edk2.
# it seems that if the two binaries are on different versions, then the dtb resolves some discrepencies:
# - allows systemd-boot to autoboot after 5s (else, it lacks its countdown ... uart problems?)
# but generally, omitting this .dtb probably won't totally break the boot.
install -Dm644 ${raspberrypifw}/share/raspberrypi/boot/bcm2711-rpi-400.dtb $out/bcm2711-rpi-400.dtb
# install -Dm644 ${raspberrypifw}/share/raspberrypi/boot/bcm2711-rpi-4-b.dtb $out/bcm2711-rpi-4-b.dtb
# install -Dm644 ${raspberrypifw}/share/raspberrypi/boot/bcm2711-rpi-cm4.dtb $out/bcm2711-rpi-cm4.dtb
''

View File

@@ -0,0 +1,133 @@
# WHEN UPDATING:
# - check the tag in <repo:nixos/nixpkgs:pkgs/by-name/ed/edk2/package.nix>
# e.g. edk2-stable202505
# - figure the date, via `cd edk2 && git show edk2-stable202505`
# - pin the other repos to the closest commit
# consider updating to the known-good commits from <https://github.com/pftf/RPi4>
{
acpica-tools,
buildArmTrustedFirmware,
edk2,
fetchFromGitHub,
lib,
}:
let
armTrustedFirmwareRpi4 = buildArmTrustedFirmware rec {
# see: <repo:tianocore/edk2-non-osi:Platform/RaspberryPi/RPi4/TrustedFirmware/Readme.md>
# says they build it with:
# > make PLAT=rpi4 RPI3_PRELOADED_DTB_BASE=0x1F0000 PRELOADED_BL33_BASE=0x20000 SUPPORT_VFP=1 SMC_PCI_SUPPORT=1 DEBUG=0 all
# see also <repo:ARM-software/arm-trusted-firmware:plat/rpi/rpi4/platform.mk>
platform = "rpi4";
extraMeta.platforms = [ "aarch64-linux" ];
filesToInstall = [ "build/${platform}/release/bl31.bin" ];
# platformCanUseHDCPBlob = true;
extraMakeFlags = [
# these are the flags which tianocore, pftf build with.
# RPI3_PRELOADED_DTB_BASE: "Auxiliary build option needed when using `RPI3_DIRECT_LINUX_BOOT=1`. This option allows to specify the location of a DTB in memory."
# "RPI3_PRELOADED_DTB_BASE=0x1F0000"
# PRELOADED_BL33_BASE: "Used to specify the fixed address of a BL33 binary that has been preloaded by earlier boot stages (VPU). Useful for bundling BL31 and BL33 in the same `armstub` image (e.g. TF-A + EDK2)."
# IOW: ATF and EDK2 need to agree on the value of PRELOADED_BL33_BASE!
"PRELOADED_BL33_BASE=0x20000"
# SUPPORT_VFP: "allow Vector Floating Point operations in EL3".
# where EL3 is the part of TFA which stays resident in the CPU;
# ATF lowers to EL2 before passing control to the next boot stage;
# i'd guess this is an (optional) optimization of some sort?
# "SUPPORT_VFP=1"
# SMC_PCI_SUPPORT: ATF rpi4/platform.mk defaults this to 0 and says "SMCCC PCI support (should be enabled for ACPI builds)".
# "SMC_PCI_SUPPORT=1"
];
};
edk2-platforms = fetchFromGitHub {
owner = "tianocore";
repo = "edk2-platforms";
name = "edk2-platforms";
rev = "6153891ee3b4e80e0340236f0eec0228746bacc0"; # 2025-05-25
hash = "sha256-EuM6MXc39IJB8QAkW/DFagz2wLI1EYftvayP45oHz0I=";
};
# edk2-src = fetchFromGitHub {
# owner = "tianocore";
# repo = "edk2";
# name = "edk2";
# # fetchSubmodules = true;
# rev = "060bb0e5a75946729defa4824fa899cf4cc0528b";
# # hash = "sha256-gafZ+iyJ0IpGpe3ucPw/Ap/3ZrY3gCNSJEpAqgBAzRY=";
# };
# edk2-non-osi = fetchFromGitHub {
# owner = "tianocore";
# repo = "edk2-non-osi";
# name = "edk2-non-osi";
# rev = "0544808c623bb73252310b1e5ef887caaf08c34b"; # 2024-03-14
# hash = "sha256-09D1p7xHT6rLxgdw7flT3gEWNKqxOhM2Q643t0nw9ww=";
# # rev = "3415f616e08a0d9c7bd264cab674929a7b0f5e33"; # 2025-08-04
# };
in edk2.mkDerivation "Platform/RaspberryPi/RPi4/RPi4.dsc" {
pname = "edk2-rpi4";
inherit (edk2) version;
nativeBuildInputs = [
acpica-tools
];
srcs = [
edk2.src
edk2-platforms
];
sourceRoot = edk2.src.name;
postPatch = ''
# patch out the raspberry pi logo from the boot process, so as to remove dependency
# on separate edk2-non-osi repo (which i would otherwise have to keep in sync)...
# to instead build WITH the raspberry logo, remove these patches and set
# PACKAGES_PATH=$edk2:$edk2-platforms:$edk2-non-osi
#
# N.B.: can either comment out the `LogoDxe.inf` lines, to build with no logo,
# or point them to a different in-tree Logo (e.g. AMD, Intel, or tianocore (i.e. MdeModulePkg)).
substituteInPlace ../edk2-platforms/Platform/RaspberryPi/RPi4/RPi4.fdf \
--replace-fail \
'INF Platform/RaspberryPi/Drivers/LogoDxe/LogoDxe.inf' \
'INF MdeModulePkg/Logo/LogoDxe.inf'
substituteInPlace ../edk2-platforms/Platform/RaspberryPi/RPi4/RPi4.dsc \
--replace-fail \
'Platform/RaspberryPi/Drivers/LogoDxe/LogoDxe.inf' \
'MdeModulePkg/Logo/LogoDxe.inf'
export PACKAGES_PATH=$(pwd):$(pwd)/../edk2-platforms
'';
installPhase = ''
runHook preInstall
install -Dm644 Build/RPi4/RELEASE*/FV/RPI_EFI.fd $out/RPI_EFI.fd
runHook postInstall
'';
buildFlags = [
"-DTFA_BUILD_ARTIFACTS=${armTrustedFirmwareRpi4}" #< or, place bl31.bin at Platform/RaspberryPi/RPi4/TrustedFirmware
# flags taken from <https://github.com/pftf/RPi4/blob/master/.github/workflows/linux_edk2.yml#L63>
# in practice, none seem to be required
# "-DSECURE_BOOT_ENABLE=TRUE"
# "-DINCLUDE_TFTP_COMMAND=TRUE"
# "-DNETWORK_ISCSI_ENABLE=TRUE"
# "-DSMC_PCI_SUPPORT=1"
# "-DNETWORK_TLS_ENABLE=FALSE"
# "-DNETWORK_ALLOW_HTTP_CONNECTIONS=TRUE"
];
# fixes `error: -Wformat-security ignored without -Wformat`
env.NIX_CFLAGS_COMPILE = "-Wformat";
passthru = {
inherit
# edk2-non-osi
edk2-platforms
# edk2-src
armTrustedFirmwareRpi4
;
};
meta = {
maintainers = with lib.maintainers; [
colinsane
];
platforms = [ "aarch64-linux" ];
};
}

View File

@@ -9,9 +9,11 @@
libsoup_3, libsoup_3,
meson, meson,
ninja, ninja,
nix-update-script,
openssl, openssl,
pkg-config, pkg-config,
python3, python3,
rust,
rustPlatform, rustPlatform,
rustc, rustc,
stdenv, stdenv,
@@ -19,20 +21,21 @@
wrapGAppsHook4, wrapGAppsHook4,
}: }:
stdenv.mkDerivation { stdenv.mkDerivation (finalAttrs: {
pname = "envelope"; pname = "envelope";
version = "0.1.0-unstable-2024-09-13"; version = "0.1.0-unstable-2025-05-17";
src = fetchFromGitLab { src = fetchFromGitLab {
domain = "gitlab.gnome.org"; domain = "gitlab.gnome.org";
owner = "felinira"; owner = "felinira";
repo = "envelope"; repo = "envelope";
rev = "11ce86da13793787a25e48ca23322b33fcf8bf34"; # last commit before libadwaita 1.6 rev = "e2a8a56aa9b68d82486b99790b86322715d2a6db";
hash = "sha256-EX309RhisBx27TscMsibEvqCSCUSukTgf4Xs1Vws4YY="; hash = "sha256-osVShCaKKoGhxWCjaYcMkOji8e0oETgDaDpCAfHauwQ=";
}; };
cargoDeps = rustPlatform.importCargoLock { cargoDeps = rustPlatform.fetchCargoVendor {
lockFile = ./Cargo.lock; inherit (finalAttrs) pname version src;
hash = "sha256-8pK8cw9nYJmmybYRL+PUCK8FvUUPbyFp7oYYF461KPc=";
}; };
nativeBuildInputs = [ nativeBuildInputs = [
@@ -58,10 +61,21 @@ stdenv.mkDerivation {
postPatch = '' postPatch = ''
patchShebangs --build build-aux/meson-cargo-manifest.py patchShebangs --build build-aux/meson-cargo-manifest.py
# versions prior to c3f5ed4f (2024-10-13) didn't embed Cargo.lock
cp ${./Cargo.lock} Cargo.lock substituteInPlace src/meson.build \
--replace-fail \
"'src' / rust_target / meson.project_name()" \
"'src' / '${stdenv.hostPlatform.rust.cargoShortTarget}' / rust_target / meson.project_name()"
''; '';
env."CC_${stdenv.buildPlatform.rust.rustcTarget}" = rust.envVars.ccForBuild; #< fixes cross build of sql-macros proc-macro
env.CARGO_BUILD_TARGET = stdenv.hostPlatform.rust.rustcTargetSpec;
env.OPENSSL_NO_VENDOR = true; #< speculative, to use the nixos openssl
env.RUSTC_BOOTSTRAP = 1; #< fixes 'error[E0554]: `#![feature]` may not be used on the stable release channel'
# env.LIBSQLITE3_SYS_USE_PKG_CONFIG = 1; #< TODO: use nixos libsqlite instead of pre-packaged one
passthru.updateScript = nix-update-script { };
meta = with lib; { meta = with lib; {
description = "a mobile-first email client for the GNOME ecosystem"; description = "a mobile-first email client for the GNOME ecosystem";
homepage = "https://gitlab.gnome.org/felinira/envelope/"; homepage = "https://gitlab.gnome.org/felinira/envelope/";
@@ -70,4 +84,4 @@ stdenv.mkDerivation {
platforms = platforms.linux; platforms = platforms.linux;
mainProgram = "envelope"; mainProgram = "envelope";
}; };
} })

View File

@@ -11,13 +11,13 @@
}: }:
stdenvNoCC.mkDerivation (finalAttrs: { stdenvNoCC.mkDerivation (finalAttrs: {
pname = "euicc-manual"; pname = "euicc-manual";
version = "0-unstable-2025-08-14"; version = "0-unstable-2025-08-30";
# XXX: their gitea downloads are broken, so use fetchgit # XXX: their gitea downloads are broken, so use fetchgit
src = fetchgit { src = fetchgit {
url = "https://gitea.osmocom.org/sim-card/euicc-manual"; url = "https://gitea.osmocom.org/sim-card/euicc-manual";
rev = "b9ca1371f6849ec5724f5374a11bb380b7a762a6"; rev = "af14e4ca642048367a655994ac31341756429f5d";
hash = "sha256-4Bveo+4rpwRjmUrneN7ObJekQ3W2woai8Pe8JWlp9QM="; hash = "sha256-CXu4yWnCDu8X8gSWe6QsVD9w2zI0SZMOoKkVRi0/eDM=";
}; };
nativeBuildInputs = [ nativeBuildInputs = [

View File

@@ -33,6 +33,12 @@ stdenv.mkDerivation rec {
hash = "sha256-ALoxT+RLL4omJ7quWDJVdXgevaO8i8q/29FFFudIRV4="; hash = "sha256-ALoxT+RLL4omJ7quWDJVdXgevaO8i8q/29FFFudIRV4=";
}; };
postPatch = ''
substituteInPlace src/meson.build --replace-fail \
"'target' / rust_target / meson.project_name()" \
"'target' / '${stdenv.hostPlatform.rust.cargoShortTarget}' / rust_target / meson.project_name()"
'';
nativeBuildInputs = [ nativeBuildInputs = [
cargo cargo
desktop-file-utils desktop-file-utils
@@ -49,6 +55,8 @@ stdenv.mkDerivation rec {
openssl openssl
]; ];
env.CARGO_BUILD_TARGET = stdenv.hostPlatform.rust.rustcTargetSpec;
passthru.updateScript = gitUpdater { passthru.updateScript = gitUpdater {
rev-prefix = "v"; rev-prefix = "v";
}; };

View File

@@ -14,12 +14,12 @@
stdenv.mkDerivation (finalAttrs: { stdenv.mkDerivation (finalAttrs: {
pname = "lpac"; pname = "lpac";
version = "2.2.1"; version = "2.3.0";
src = fetchFromGitHub { src = fetchFromGitHub {
owner = "estkme-group"; owner = "estkme-group";
repo = "lpac"; repo = "lpac";
rev = "v${finalAttrs.version}"; rev = "v${finalAttrs.version}";
hash = "sha256-dxoYuX3dNj4piXQBqU4w1ICeyOGid35c+6ZITQiN6wA="; hash = "sha256-ALne5sHB6ff7cHAWe0rFwpP/Yz4EhZBiOrgdM2B8+OE=";
}; };
# options: # options:

View File

@@ -14,8 +14,8 @@
mkNixpkgs ? import ./mkNixpkgs.nix {}, mkNixpkgs ? import ./mkNixpkgs.nix {},
}: }:
mkNixpkgs { mkNixpkgs {
rev = "6207745fb2fb83330b7193fed31337050b075f40"; rev = "70ec3948a7f996d279bd77c66420027268b98aeb";
sha256 = "sha256-NfKklCRVBW979loK3FIXjYYMO2oGfFx/ozfg37oWRcc="; sha256 = "sha256-gwYhaTGhEeYlEYTR7Bhewam6wRKrMu3SODZE4f/cg0Y=";
version = "unstable-2025-08-15"; version = "unstable-2025-08-31";
branch = "master"; branch = "master";
} }

View File

@@ -45,51 +45,52 @@ in
# TODO: enable, once i can tolerate a mass rebuild # TODO: enable, once i can tolerate a mass rebuild
# (fetchpatch' { # (fetchpatch' {
# # 2025-08-06: merged into staging
# name = "v4l-utils: fix cross-compilation";
# prUrl = "https://github.com/NixOS/nixpkgs/pull/429900";
# hash = "sha256-oH9jTG38mWpjwf/LH3MTCrBm2NC4WTRPki2mUhCc5WQ=";
# })
# (fetchpatch' {
# name = "libpcap: enable dbus, rdma, bluetooth features"; # name = "libpcap: enable dbus, rdma, bluetooth features";
# prUrl = "https://github.com/NixOS/nixpkgs/pull/429225"; # prUrl = "https://github.com/NixOS/nixpkgs/pull/429225";
# hash = "sha256-cALgj+7eXd3H4WAmW6CIcxWRC3D4PoY2PWNsDxK+G9g="; # hash = "sha256-cALgj+7eXd3H4WAmW6CIcxWRC3D4PoY2PWNsDxK+G9g=";
# }) # })
# (fetchpatch' {
# # 2025-07-15: merged into staging
# name = "treewide: populate arch and platform for more node packages";
# prUrl = "https://github.com/NixOS/nixpkgs/pull/422938";
# hash = "sha256-lN99K0k9dCUBFXc99XB97cZSVDu5A74pHL40vw9cobY=";
# })
# XXX(2025-07-25): master & staging have diverged that the above patch doesn't apply correctly;
# manually recreate the patches against master:
(fetchpatch' {
name = "nodejs: split destCPU into stdenv.$platform.node";
saneCommit = "1fd1d40033deb51bc74ecf11b401cf2ffde5aae3";
hash = "sha256-LGp9HzUINI5iTQ3UtggUNWS4zaYhakUI3OqM6rPiYr0=";
})
(fetchpatch' {
name = "treewide: replace node platform mapping with stdenv.hostPlatform.node.{arch,platform}";
saneCommit = "57bac5daa19c55a547f60271a7b48c59337ec12f";
hash = "sha256-DBenl7O4KuQ1I6jmB66upufYSUdYHRkqRdqRT9stbys=";
})
(fetchpatch' {
name = "buildNpmPackage: push npm_config_* options into npmHooks.npmConfigHook";
saneCommit = "f84ef10710b6634f5bcc4c7bc4764ecfd6e8dec5";
hash = "sha256-BHwtNvSGaqBRzUj0mP3JqAfygxjiKoX3lh4z9+B4UWk=";
})
(fetchpatch' {
name = "pnpm.configHook: set npm_config_{arch,platform}";
saneCommit = "38d2a3d80502ad63686ca886f4438d2942fbddb6";
hash = "sha256-0grq9Os9XD+voupAQuB48WBptH5oM/qYX5iEdmuVqMQ=";
})
(fetchpatch' { (fetchpatch' {
name = "signal-desktop: fix cross compilation"; name = "signal-desktop: fix cross compilation";
prUrl = "https://github.com/NixOS/nixpkgs/pull/423089"; prUrl = "https://github.com/NixOS/nixpkgs/pull/423089";
# hash = "sha256-609snDT1Ru69ZTWfzu4PnhY0pj3xghPr8w880j7JZ5k="; hash = "sha256-4VEKjZsI7XW+/gbq3fn3bjjciPKtd2IU8SH4CsqqJ6Y=";
hash = "sha256-bVMOanUcYNPf2JbaWS9ga+0jAwuZQSfMKlwtNRp9tYU="; })
(fetchpatch' {
name = "fractal: fix cross compilation";
prUrl = "https://github.com/NixOS/nixpkgs/pull/437038";
hash = "sha256-B7s2aNVony+G7FW2PaR7FVO7zzWa7SiLONWRGrsXA3A=";
})
(fetchpatch' {
name = "gmobile: set strictDeps, fix cross compilation";
prUrl = "https://github.com/NixOS/nixpkgs/pull/437700";
# saneCommit = "223b327fcc0775212bcc30a0bfb57c90ce5e3251";
hash = "sha256-3zxCtRlliCpaDbJBV4hioQG7ehFvA9Co1JQdGStY1Js=";
})
(fetchpatch' {
# desko nixpkgs branch: `pr-papers-cross`
name = "papers: fix cross compilation";
prUrl = "https://github.com/NixOS/nixpkgs/pull/437704";
# saneCommit = "eaed8b1530ce9eb9f674677003866d2d793b90fa";
hash = "sha256-G+2I7FMVN7WJio1ufwRZ0F13X/LViNdH1zfR4qqN46Y=";
})
(fetchpatch' {
# desko nixpkgs branch: `pr-delfin-cross`
name = "delfin: fix cross compilation";
prUrl = "https://github.com/NixOS/nixpkgs/pull/437748";
# saneCommit = "b19145967431b49849d7dc5e0657322134297a24";
hash = "sha256-R5hAfUmNsLnNpx26ZFZWqA0dLiYR/4pBMwfJrOBC+l0=";
})
(fetchpatch' {
# desko nixpkgs branch: `pr-snapshot-cross`
name = "snapshot: fix cross compilation";
prUrl = "https://github.com/NixOS/nixpkgs/pull/437708";
# saneCommit = "9bf01eef452d46c2990cdc872017f1015892ea7d";
hash = "sha256-nzqbRP9wHyDnwKyaATZ5mSyn68qgRvs4pEtAkhauiMM=";
}) })
# (fetchpatch' { # (fetchpatch' {
@@ -135,12 +136,6 @@ in
# hash = "sha256-UyZaNNp84zKShuo6zu0nfZ2FygHGcmV63Ww4Y4CtCF0="; # hash = "sha256-UyZaNNp84zKShuo6zu0nfZ2FygHGcmV63Ww4Y4CtCF0=";
# }) # })
# (fetchpatch' {
# name = "rpm: 4.18.1 -> 4.19.0";
# prUrl = "https://github.com/NixOS/nixpkgs/pull/260558";
# hash = "sha256-kwod+6SbUZechzbmu1D4Hlh6pYiPD18wcqetk0OIOrA=";
# })
# (fetchpatch' { # (fetchpatch' {
# # XXX: doesn't cleanly apply; fetch `firefox-pmos-mobile` branch from my git instead # # XXX: doesn't cleanly apply; fetch `firefox-pmos-mobile` branch from my git instead
# name = "firefox-pmos-mobile: init at -pmos-2.2.0"; # name = "firefox-pmos-mobile: init at -pmos-2.2.0";

View File

@@ -2,8 +2,8 @@
mkNixpkgs ? import ./mkNixpkgs.nix {}, mkNixpkgs ? import ./mkNixpkgs.nix {},
}: }:
mkNixpkgs { mkNixpkgs {
rev = "c0e9e1afcfdb5fcd0ae7466a20a9c1ced45ce8a1"; rev = "b6e3a2d6af4a1b9c25104fcf7a24fa7d702a626d";
sha256 = "sha256-njAuNOzJKhK4lAuabibqWqsziLZVCMQJmDZRm5MYbbQ="; sha256 = "sha256-Y2NtoHYeYJydIvBBhAxvuLqP0tB5KsGprLrlgBAHaCI=";
version = "unstable-2025-08-15"; version = "unstable-2025-08-31";
branch = "staging-next"; branch = "staging-next";
} }

View File

@@ -2,8 +2,8 @@
mkNixpkgs ? import ./mkNixpkgs.nix {}, mkNixpkgs ? import ./mkNixpkgs.nix {},
}: }:
mkNixpkgs { mkNixpkgs {
rev = "664c1d7072fbafa4c806ac6b22f9a6eee221cfcf"; rev = "8ba2cb563c7bd53a8a6e37d3f9530aa1f3757a38";
sha256 = "sha256-Y7DnNNQLKLdQwIwAEyGQPPcqDDLiCZcuJnQ9f/mWigM="; sha256 = "sha256-MXmCtJpYNURZSxeU3SEvecw9ln8sv3GZXHM4gskwVz0=";
version = "unstable-2025-08-15"; version = "unstable-2025-08-31";
branch = "staging"; branch = "staging";
} }

View File

@@ -7,8 +7,8 @@ let
src = fetchFromGitHub { src = fetchFromGitHub {
owner = "nix-community"; owner = "nix-community";
repo = "nixpkgs-wayland"; repo = "nixpkgs-wayland";
rev = "9c452b9ea8e584d5085629e2b76703c94df64b6f"; rev = "60f64e8511aeca7cdd967ef42746845c89321ef7";
hash = "sha256-THPRayZls0/4rZSw4R5B7evCbGVr5AN3SQQZSgYpIiA="; hash = "sha256-ghByh4Imm2FCMGhTkdyy74DBJIqRgZTDqB77YcnQFSs=";
}; };
flake = import "${src}/flake.nix"; flake = import "${src}/flake.nix";
evaluated = flake.outputs { evaluated = flake.outputs {
@@ -25,7 +25,7 @@ let
in src.overrideAttrs (base: { in src.overrideAttrs (base: {
# attributes required by update scripts # attributes required by update scripts
pname = "nixpkgs-wayland"; pname = "nixpkgs-wayland";
version = "0-unstable-2025-08-14"; version = "0-unstable-2025-08-31";
src = src; src = src;
# passthru only nixpkgs-wayland's own packages -- not the whole nixpkgs-with-nixpkgs-wayland-as-overlay: # passthru only nixpkgs-wayland's own packages -- not the whole nixpkgs-with-nixpkgs-wayland-as-overlay:

View File

@@ -14,13 +14,13 @@
stdenv.mkDerivation (finalAttrs: { stdenv.mkDerivation (finalAttrs: {
pname = "syshud"; pname = "syshud";
version = "0-unstable-2025-07-26"; version = "0-unstable-2025-08-18";
src = fetchFromGitHub { src = fetchFromGitHub {
owner = "System64fumo"; owner = "System64fumo";
repo = "syshud"; repo = "syshud";
rev = "d954c124280b71f80930046a11e390a814c1b229"; rev = "6dbf17bb953342c844517d1b4eb672cbae7a1566";
hash = "sha256-FUPnIUl9x0eZmhls4CmPGg4kZb1MNmKU5BKecFDQdHM="; hash = "sha256-T9tWmgDIcmmRXAeWR7Pfjalkl6xogtuz1qfsSAuQmkg=";
}; };
postPatch = '' postPatch = ''

View File

@@ -6,8 +6,7 @@
armTrustedFirmwareRK3399, armTrustedFirmwareRK3399,
buildUBoot, buildUBoot,
}: }:
buildUBoot {
(buildUBoot {
defconfig = "pinephone-pro-rk3399_defconfig"; defconfig = "pinephone-pro-rk3399_defconfig";
filesToInstall = [ filesToInstall = [
"idbloader.img" #< entry point: place it at sector 64 & it'll load whatever's at sector 16384 into RAM and jump to it "idbloader.img" #< entry point: place it at sector 64 & it'll load whatever's at sector 16384 into RAM and jump to it
@@ -24,7 +23,7 @@
"u-boot-nodtb.bin" "u-boot-nodtb.bin"
"u-boot.sym" "u-boot.sym"
]; ];
}).overrideAttrs (upstream: {
# default baud rate is 1500000, which is too fast for some USB <-> serial adapters to do # default baud rate is 1500000, which is too fast for some USB <-> serial adapters to do
# CONFIG_DM_RNG is needed to seed the kernel, and avoid "KASLR disabled due to lack of seed" # CONFIG_DM_RNG is needed to seed the kernel, and avoid "KASLR disabled due to lack of seed"
extraConfig = '' extraConfig = ''
@@ -32,30 +31,30 @@
CONFIG_DM_RNG=y CONFIG_DM_RNG=y
''; '';
# default layout is: # XXX: RK3399 ships a blob for HDCP (media copy protection) in the trusted firmware.
# scriptaddr = 0x00500000 # that can be removed with:
# script_offset_f = 0xffe000 # `(arm-trusted-firmware.override { unfreeIncludeHDCPBlob = false; }).armTrustedFirmwareRK3399`, if so desired.
# script_size_f = 0x2000 BL31 = "${armTrustedFirmwareRK3399}/bl31.elf";
# pxefile_addr_r = 0x00600000 }
# fdt_addr_r = 0x01e00000 # ).overrideAttrs (upstream: {
# fdtoverlay_addr_r = 0x01f00000
# kernel_addr_r = 0x02080000
# ramdisk_addr_r = 0x06000000
# kernel_comp_addr_r = 0x08000000
# kernel_comp_size = 0x2000000
#
# this offers 63.5 MiB for the kernel.
# unfortunately, my bloated kernels can be larger than that, so push the addresses back and hope it works:
# postPatch = (upstream.postPatch or "") + ''
# substituteInPlace include/configs/rk3399_common.h \
# --replace-fail ramdisk_addr_r=0x06000000 ramdisk_addr_r=0x0a000000 \
# --replace-fail kernel_comp_addr_r=0x08000000 kernel_comp_addr_r=0x0c000000
# '';
env = (upstream.env or {}) // { # default layout is:
# XXX: RK3399 ships a blob for HDCP (media copy protection) in the trusted firmware. # scriptaddr = 0x00500000
# that can be removed with: # script_offset_f = 0xffe000
# `(arm-trusted-firmware.override { unfreeIncludeHDCPBlob = false; }).armTrustedFirmwareRK3399`, if so desired. # script_size_f = 0x2000
BL31 = "${armTrustedFirmwareRK3399}/bl31.elf"; # pxefile_addr_r = 0x00600000
}; # fdt_addr_r = 0x01e00000
}) # fdtoverlay_addr_r = 0x01f00000
# kernel_addr_r = 0x02080000
# ramdisk_addr_r = 0x06000000
# kernel_comp_addr_r = 0x08000000
# kernel_comp_size = 0x2000000
#
# this offers 63.5 MiB for the kernel.
# unfortunately, my bloated kernels can be larger than that, so push the addresses back and hope it works:
# postPatch = (upstream.postPatch or "") + ''
# substituteInPlace include/configs/rk3399_common.h \
# --replace-fail ramdisk_addr_r=0x06000000 ramdisk_addr_r=0x0a000000 \
# --replace-fail kernel_comp_addr_r=0x08000000 kernel_comp_addr_r=0x0c000000
# '';
# })

View File

@@ -6,12 +6,12 @@
}: }:
stdenvNoCC.mkDerivation { stdenvNoCC.mkDerivation {
pname = "uassets"; pname = "uassets";
version = "0-unstable-2025-08-15"; version = "0-unstable-2025-08-31";
src = fetchFromGitHub { src = fetchFromGitHub {
owner = "uBlockOrigin"; owner = "uBlockOrigin";
repo = "uAssets"; repo = "uAssets";
rev = "e1dd6d5aa73d9dc6d7a123ef585ba5d082bb6fa8"; rev = "f46c97622c978dbe59a942fc649f0eddb3deeb39";
hash = "sha256-rGZWU2OXWjyweyWjST8CgpriEUB1Sa2wd3/FJ1cVMlw="; hash = "sha256-dDtN7WUBbJGbWCSFpVE2NkcFpZXO9RJKJy15Pa18xXE=";
}; };
dontBuild = true; dontBuild = true;

View File

@@ -7,12 +7,12 @@
}: }:
buildDotnetModule rec { buildDotnetModule rec {
pname = "UVtools"; pname = "UVtools";
version = "5.1.7"; version = "5.2.0";
src = fetchFromGitHub { src = fetchFromGitHub {
owner = "sn4k3"; owner = "sn4k3";
repo = "UVtools"; repo = "UVtools";
rev = "v${version}"; rev = "v${version}";
hash = "sha256-+3E8Ts+rv72Jq4jLcmyU3KUP7U0k6Ruo5+Dn0hdj+Yg="; hash = "sha256-4o+F56E80GElRb4DfmOv6mqwQ8+23E0aj/RjGr7Pg8U=";
}; };
nugetDeps = ./deps.json; nugetDeps = ./deps.json;

View File

@@ -1,6 +1,6 @@
{ mkVersionedHttpZim }: mkVersionedHttpZim { { mkVersionedHttpZim }: mkVersionedHttpZim {
owner = "other"; owner = "other";
pname = "alpinelinux_en_all_maxi"; pname = "alpinelinux_en_all_maxi";
version = "2025-07"; version = "2025-08";
hash = "sha256-B99/UhqhKsVqphXRuRFDTD4eIY6/MqkO0pfNKGadbsg="; hash = "sha256-/MW3BAvEnsWfIZawkRq8qKhaLzPivAByWE9qIEPP4wo=";
} }

View File

@@ -1,6 +1,6 @@
{ mkVersionedHttpZim }: mkVersionedHttpZim { { mkVersionedHttpZim }: mkVersionedHttpZim {
owner = "other"; owner = "other";
pname = "archlinux_en_all_maxi"; pname = "archlinux_en_all_maxi";
version = "2025-07"; version = "2025-08";
hash = "sha256-Hz2KpptYh0j5f88AyIpy0JaT+qhAegZHOCdaIz22NHo="; hash = "sha256-++r0i57yLDEwVFj0fQm96zSW4kRgbtUkyq86c+Lz2FQ=";
} }

View File

@@ -1,6 +1,6 @@
{ mkVersionedHttpZim }: mkVersionedHttpZim { { mkVersionedHttpZim }: mkVersionedHttpZim {
owner = "wikipedia"; owner = "wikipedia";
pname = "wikipedia_en_all_maxi"; pname = "wikipedia_en_all_maxi";
version = "2024-01"; version = "2025-08";
hash = "sha256-GrRFV3TSFhm9fCFxhFOSD3EQnzBAPZJh96NPefh6p4Q="; hash = "sha256-OqVTmcWvputcJHcZTg0CLAUnYWQIvGRMIiTtMo2mLfs=";
} }

View File

@@ -1,5 +1,5 @@
{ {
"data": "ENC[AES256_GCM,data:cAS8NgkT6wpTvwdL0EydbEpW4M+r0PTz2/rsRda2ZyeG3jSPKXe9ls+g6S0akOi0HWP870zd3geuMOP6UdfShFaC609GeoUkYIbTLTp66xwlERl8BkBHl/nopli1x7f9bQg3HomovTWBshloYnDT/+IPqU3R8PJk8KEmEs2ClhcjtUMu3AUejIXM1asxO7kTdOGyZ/ykOcr1sMaY50qjle1RtfZTLMipdgxUFuziEM1CisyN4ch1se6kJBxH3HydwOoZb3UxoTly99XlH+qUwfuEjOtBUdXrQAClMv5EiR9znvGwahdEagW4Y2gbOhyFpENgf8nMwK+ocAKCI66zook5RkYkMmQvPh0e2q42GmWnGArmRvO6LEMgYtqPmqDNwJz3GtZjlELbHpSxJ9DtDx06h1gLsV7A3wtkJ24fIgQDKPr1DOtr5TiZ5DnjhXdRakL7+3CWLJcBTKHdZ6bxAwgvwuEXWJmedG3nOgmwitpixjLrGEx0pxNjI6BQuLqthRBc8Bww8kUKwMAEbD9NzvKgmzW4nOy8GSdJ3uPG6dQCXQ1iCvV0E2VZ9Nx9MoCxq5/hMYRS7VMLDlN2xEOR1TRDiaIrGG2LOzJOhsjVtRi+5EUzXYVGL52MnAi+UTF9HRsC8E+M5G5ZAZbnw3J0vRCt+gaBUQ0j6DY9Wl5+Jp/3qVi6Avc9WMR8psTi/pVsIQKOxa4cfsQJ/X14Rb8D+I2OjeE88xBl43sztNYzK3u9oJLZsJ+ZiNQWpnpBSZtjkPcg/zgZPKWZjafCMY+fxT3o0H7h9hO4rnJHZg6TzVayjrCDps5fQAuapzvRPUs5Q80gO1/m3pyg9AnZrIZudhhCGVsrPh8rKjsSiNV1GZkciLmzMUiqLrjBMkaW1N72cua9vm6UqnriMyK5rGgPDw5SWisAXNab0ZRS1nsgSxNSiHsZe+nbwIu89ubgVaz/B2yeOQ1AnBedUZbRxzzaUnjt0xAxByBJunAELyLwMr2zRBwM3VVn4VcPx506Dg/T4V/GgYVAcQdA/OeF0cZidmDdV2XdZgZjH+9Jv5crlh2sRwc+1zskE45Nh/2WW0wA2MZ8RKeUOMGAa6rXbFoxx4YKUJxWgwGzg4hyhdNHdwcImG4/ocpdgcJ2b1aIv5CXCL4kBkMIegfTqKzVmEwu0BqAhiBJ4Z9LD/62mUUcQE7kfD5AmV1Xb4RxJEayXIbeUclasJ8Hg45Aqpz5jlbYebYLo+0bSFPO/fHQdLaEijElq7yET19EkRa3qkI8MIaZQr7BNViQL+wcCgOaGFAprZPXsOz7J4T9RVdhuuXPKpGUXK8nkCY7eUM0k+arEoxO/vAssKHByVmCIL+QxBqYDTvH35zR4/zkSMPkWGL0+Dw13/aUdAkHMLPqp4gSfcwH75ryzq4qLousbIbUnvL46KRZvAFQGjMKX3wb2z8jmQrq//hU/TUU8juX5ZewEkfZ4iQ/QsoR4ZEevEnJDu/r8bfZxkzHPG25joCv5SoGoP38a8jNmfxFX1zTCMRbHG+V6FNGlfZeF1B0o9Fg26Pmt3LQtkAujRUFJ7VjgsQhkPhwO6JiKghuwMnf61NmSK3ZXjV93StPcgVZFu3ug8jweFfkW99JPcvVWtGhoX+E/QGbrcSj6/AOhDI=,iv:a8KXOScK1IMw7eZzvDPoVCk2sqFMuLbsoMvTg5S8wYA=,tag:MccSEjjn2kVWxL9hhPOGSA==,type:str]", "data": "ENC[AES256_GCM,data:5pzAWnh/9NKq2G++E9knqRXMDzrdtqi0N//uJsAzfcm/yid+Cb/3XykosHZzNS9whVloOxNXrSuiVsc9RH0lAWVuKbr4LP/s0TjX1r0sn/NCFtrpsyQ6BN4LzAVnw35Hx4T+zFSQyx+Iu4tjm+o3iyXo8FBV2NIG/TiQ8rt6ErBlJSLS+qifUF616hDW9rPHMyrZI7KNV5juOFLVZy7mRQ3hvq9JeYocKohWFROluDORTryn5z+BO3IMmBSwE2/a8d48d/zdFz7pf+l2xjJFvWdi9yXW6hw2V7FtS3DdTVQUew2oMRdU27sHrqhrJf84P5jclDGLggTQvpxV79kJDNfxNggRNwIa/RUSI8ayrnn3MbRSEudnbXGocigCdS10CgbHnrVxhscGEur5qgMDilOxFFlOoXIc8tUC3Au/44bzHyGCqsKvu3eggPMxhuLdE3mFzr24LMhGQ6nDd95VcvwVvWVRzMnYpGXezoin/WcIVKWWYpyCsyOF6XLa5ueTkZ22C2A6aKNGIdtApAkKJ01bxJc38SAcnRkh5MQObD3Ty3u7cXmN3QPRASPvysJ9Cc0w1l5s6tHpjyk+DOqAT0kN65Cq22PqncwQzt1wxp3UcQ7tqavzW0GSIKVtG/H4OjNL6MkF7NFelvo9AaaDh7RNAAq8VT18rzD3MOVlSwRAWmoz5HJTgqk6SyaltkuOsgsbP7Zbih60u5ww5SOuC+JCNVnyel6qWd4QlJO+ycnqjaVJM+1kdbd6RNuqUXLE7N8shcEJ0F7/FqSbOLUQyZ4KmIib/8UL1mcY83xSqn9LnmCoQfSxuehzgHtRmF9BCWq+2zjrWOKslQAIC5ECCQGIEf/2ooyFj0lh3djbe60nDP6PeXq0ffyw4m5XGhRQe0nyf9AQy8VpVAvmbq29DzcC+5dPEBKr326dLajHFfXMIURxpu4yx4B69HXMAX837MXrHXUCYNe8X5UObmRwGFkJ6e6VysFbJe/DzBfEKZMPysj49juPuviWDpvj8ZquHhF5mBjMjfUJLQYY/gdlV1MzJSmMAYrraKh669r1J1yoe/V+CM8vJFKjQMlh3eU/sb08JBhGIiW9uQYxQoCrtQK2qIZcK3U/QAzkMm+mp45D8T4w6w03jbHqjyoYHdufppxI2kDbPOM/k/8/amvr5ZTgwXOQU9CTVOG3cE7jQ3pTErwcOK8/MYbmP45U+2kgLRRSFmKxuUv0bVA94I3TL4ErtQKwpa+7QhVepPVz0n5NcYN59jnm7FQpuv8lVDuVL8ToNriC8MLg4+uM8WxYZHTjXqF6DP+Arrua4SYxsSt0YA1cCiwt5BVMP2jjS20yRe7/WeVWQOg6mCZex47e6u4B7yro30Cfx/BofRt2JK0998mJUhORl2RyWL4UUoDxQn6ryaupcxnwZMnSyEihUHKMNommzYnZvVqE0pmoPdx7gKwTAaFr+oCeAAX0spKgTJyeEGqQyElh/JwJLgY6QAHOR+HrSroyIsI3DHoSLBAZ74CiD8xEInwR0Y5R4Hr0B2+kerqBV3MxEsUoBjRwLmtpTZUKlRjYWIoindfS9YC45m+l/2QUxb7+BnlcYYNuGdru6pl2DEMpFRQHCHwV5udgz8CEC4NGgozUcMKwUNTLlPe0TMVJC3HAPa5CEx7DmYqkGoBR8lrZarxdch7pZhXvCTqnAWSKCOBkCUK5dy0ecfyarmIAiKof+VkMlcwUu1G+X6pp9Ug8bYB6,iv:xjXwI1aZB6RJL+BYkIGhSG9kiiWZQqcxQuz9qEQGMFA=,tag:8+PSWNXVHjleuEle5/qFMQ==,type:str]",
"sops": { "sops": {
"age": [ "age": [
{ {
@@ -47,8 +47,8 @@
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA0VWdCWG9DdUliajJLdjZ1\nWW03QmNpb1hoUHRjK0s1UWdrdmFLcGQ4aUZvCmIxWEZxVGV3OGhIOEVxMGE0Q3lh\nY0F6dE9aWkJwR3lYaFBJYkhOeVQxYWcKLS0tIHlrZGZqTjh4dSswcWd5Y2J6WFpi\nVVdDNWUzWDRzcGtHdTZiS3RuYjFsemsKy1LW/DgYHGyBxl4ejrZBuN/g794cuMld\nr5W8k3IWBIk0HT1km9fMiW4zV+KgcrF312k/p6poo/pdGJ8e8kYsGw==\n-----END AGE ENCRYPTED FILE-----\n" "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA0VWdCWG9DdUliajJLdjZ1\nWW03QmNpb1hoUHRjK0s1UWdrdmFLcGQ4aUZvCmIxWEZxVGV3OGhIOEVxMGE0Q3lh\nY0F6dE9aWkJwR3lYaFBJYkhOeVQxYWcKLS0tIHlrZGZqTjh4dSswcWd5Y2J6WFpi\nVVdDNWUzWDRzcGtHdTZiS3RuYjFsemsKy1LW/DgYHGyBxl4ejrZBuN/g794cuMld\nr5W8k3IWBIk0HT1km9fMiW4zV+KgcrF312k/p6poo/pdGJ8e8kYsGw==\n-----END AGE ENCRYPTED FILE-----\n"
} }
], ],
"lastmodified": "2025-08-09T16:48:48Z", "lastmodified": "2025-08-20T17:31:03Z",
"mac": "ENC[AES256_GCM,data:lctLfwra+yCkgVyke4l3L5fqDQu6VTMspG48l54lOLYYEQGGYw/V+HDI6GdKVywvGfnthzf8C9LSTRJrD3gKv/Q9a4piaTCTabZ43s0rk5jRCRuUgW7dJqH2nYqZ4AZB2C3DqQn4tCUoRW0PQsZTv+jIwu+jethbn/mb81j2kGc=,iv:WgflsIi5zPGl6bn6A7W2Dvi3XMzck/LNsz/nKV1mLAk=,tag:+sn6kLAiiuXD9wk52VS0KQ==,type:str]", "mac": "ENC[AES256_GCM,data:U86dC8cNZWILAGf/0WA/JOCq+pCIoKSzsUKgW89hNQJe0sUDgRPo23uvwWa6C/2YuSlP5Jv5ofp0hO6a39dJ83iQibyOIrf0VArRRy8whu1kn/bwIhWxWL7mF6WhKgKmPLy8BX2h0zAp6EL+ct9JdYPb2gdoXrfl0f0R0BDUnL8=,iv:80e1zdyRaPPeDSvfejFd/LjusL6aoKb9F/VTp46l0Kc=,tag:jMHHxG3Ycy5fr74BQnaBEg==,type:str]",
"unencrypted_suffix": "_unencrypted", "unencrypted_suffix": "_unencrypted",
"version": "3.10.2" "version": "3.10.2"
} }