forked from colin/nix-files
Compare commits
64 Commits
patch-gite
...
master
Author | SHA1 | Date | |
---|---|---|---|
1c5c9b80eb | |||
94289c2253 | |||
0c443fae25 | |||
a490a74390 | |||
2e71e06c05 | |||
203832b5a8 | |||
1204f4db69 | |||
a4b114fce2 | |||
7e17eb4056 | |||
259d980a60 | |||
5488486944 | |||
969717b1fe | |||
7391e34f77 | |||
7f45077485 | |||
ceb7ccbc6d | |||
9d63ec5dd2 | |||
7ce93eae96 | |||
1277c73304 | |||
0550498cd1 | |||
023396a41e | |||
ebb335ef4c | |||
fbb0046dda | |||
59d4197bf5 | |||
90e4e20274 | |||
7ecd368e20 | |||
79fc30da0e | |||
23f3647cc5 | |||
ad4910366d | |||
609becadfe | |||
3acabe60b6 | |||
87ec095b8a | |||
8831d8d1ac | |||
8b333a8887 | |||
028d903e9c | |||
dfed5f070b | |||
b29ee5ac03 | |||
e700ff392f | |||
91578c0b78 | |||
b35656c9ae | |||
726281a6dd | |||
f305027678 | |||
2b69c07d12 | |||
544b1e58e0 | |||
34c2d4f66f | |||
4addf857b7 | |||
a3f6c148d3 | |||
43a0abd68f | |||
b3c4e96d6e | |||
ade5ce5339 | |||
e543034fcb | |||
b5d96ed17b | |||
003ce70cd7 | |||
04f6964711 | |||
63cf19f839 | |||
806a1aa294 | |||
35a023f449 | |||
f0aec4416c | |||
e0bb1b7c62 | |||
9847e0171c | |||
03a1638628 | |||
f7327bef3e | |||
47fb8296db | |||
b409fbb5f7 | |||
84092395f4 |
1
TODO.md
1
TODO.md
@@ -135,6 +135,7 @@
|
||||
- Trivia Quiz (https://linuxphoneapps.org/games/io.github.nokse22.trivia-quiz/)
|
||||
- sane-sync-music: remove empty dirs
|
||||
- soulseek: install a CLI app usable over ssh
|
||||
- moby: replace `spot` with its replacement, `riff` (<https://github.com/Diegovsky/riff>)
|
||||
|
||||
#### moby
|
||||
- moby: port battery support to something upstreamable
|
||||
|
@@ -1,18 +1,18 @@
|
||||
## migrating a host to a new drive
|
||||
1. copy persistent data off of the host:
|
||||
### 1. copy persistent data off of the host:
|
||||
```sh
|
||||
$ mkdir -p mnt old/persist
|
||||
$ mount /dev/$old mnt
|
||||
$ rsync -arv mnt/persist/ old/persist/
|
||||
```
|
||||
|
||||
2. flash the new drive
|
||||
### 2. flash the new drive
|
||||
```
|
||||
$ nix-build -A hosts.moby.img
|
||||
$ 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
|
||||
$ cfdisk /dev/$new
|
||||
# scroll to the last partition
|
||||
@@ -21,24 +21,29 @@ $ cfdisk /dev/$new
|
||||
> Write
|
||||
type "yes"
|
||||
> 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
|
||||
$ mount /dev/$new new
|
||||
$ mkdir /mnt/$new
|
||||
$ mount /dev/$new /mnt/$new
|
||||
# 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
|
||||
$ 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:
|
||||
$ 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!
|
||||
|
@@ -1,4 +1,4 @@
|
||||
{ ... }:
|
||||
{ config, lib, ... }:
|
||||
{
|
||||
imports = [
|
||||
./fs.nix
|
||||
@@ -27,7 +27,7 @@
|
||||
sane.roles.client = true;
|
||||
sane.roles.pc = 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.ovpn.addrV4 = "172.26.55.21";
|
||||
# sane.ovpn.addrV6 = "fd00:0000:1337:cafe:1111:1111:20c1:a73c";
|
||||
|
@@ -1,4 +1,4 @@
|
||||
{ ... }:
|
||||
{ lib, pkgs, ... }:
|
||||
{
|
||||
imports = [
|
||||
./fs.nix
|
||||
@@ -22,4 +22,37 @@
|
||||
sops.secrets.colin-passwd.neededForUsers = 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;
|
||||
};
|
||||
}
|
||||
|
@@ -16,7 +16,7 @@
|
||||
fileSystems."/tmp".options = [ "size=32G" ];
|
||||
|
||||
fileSystems."/nix" = {
|
||||
device = "/dev/disk/by-uuid/cc81cca0-3cc7-4d82-a00c-6243af3e7776";
|
||||
device = "/dev/disk/by-uuid/55555555-eeee-ffff-bbbb-000020250820";
|
||||
fsType = "btrfs";
|
||||
options = [
|
||||
"compress=zstd"
|
||||
@@ -25,7 +25,7 @@
|
||||
};
|
||||
|
||||
fileSystems."/boot" = {
|
||||
device = "/dev/disk/by-uuid/6EE3-4171";
|
||||
device = "/dev/disk/by-uuid/2025-0820";
|
||||
fsType = "vfat";
|
||||
};
|
||||
|
||||
|
@@ -124,6 +124,7 @@
|
||||
|
||||
services.anubis.instances."git.uninsane.org" = {
|
||||
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;
|
||||
};
|
||||
|
||||
@@ -133,8 +134,13 @@
|
||||
# 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%).
|
||||
# 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}";
|
||||
# proxyPass = "http://127.0.0.1:3000";
|
||||
proxyPassHeavy = "http://unix:${config.services.anubis.instances."git.uninsane.org".settings.BIND}";
|
||||
# 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 {
|
||||
forceSSL = true; # gitea complains if served over a different protocol than its config file says
|
||||
enableACME = true;
|
||||
@@ -144,9 +150,20 @@
|
||||
'';
|
||||
|
||||
locations."/" = {
|
||||
inherit proxyPass;
|
||||
proxyPass = proxyPassLight;
|
||||
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
|
||||
# locations."= /robots.txt".extraConfig = ''
|
||||
# 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.
|
||||
# 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" = {
|
||||
inherit proxyPass;
|
||||
proxyPass = proxyPassLight;
|
||||
recommendedProxySettings = true;
|
||||
extraConfig = ''
|
||||
proxy_hide_header Content-Type;
|
||||
@@ -163,7 +180,7 @@
|
||||
'';
|
||||
};
|
||||
locations."~ ^/colin/phone-case-cq/raw/.*.js" = {
|
||||
inherit proxyPass;
|
||||
proxyPass = proxyPassLight;
|
||||
recommendedProxySettings = true;
|
||||
extraConfig = ''
|
||||
proxy_hide_header Content-Type;
|
||||
|
@@ -14,158 +14,160 @@
|
||||
#
|
||||
# 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.
|
||||
{ ... }:
|
||||
{ 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
|
||||
{
|
||||
# https://jellyfin.org/docs/general/networking/index.html
|
||||
sane.ports.ports."1900" = {
|
||||
protocol = [ "udp" ];
|
||||
visibleTo.lan = true;
|
||||
description = "colin-upnp-for-jellyfin";
|
||||
};
|
||||
sane.ports.ports."7359" = {
|
||||
protocol = [ "udp" ];
|
||||
visibleTo.lan = true;
|
||||
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" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
description = "colin-jellyfin-http-lan";
|
||||
};
|
||||
sane.ports.ports."8920" = {
|
||||
protocol = [ "tcp" ];
|
||||
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;
|
||||
# '';
|
||||
config = lib.mkIf (config.sane.maxBuildCost >= 2) {
|
||||
# https://jellyfin.org/docs/general/networking/index.html
|
||||
sane.ports.ports."1900" = {
|
||||
protocol = [ "udp" ];
|
||||
visibleTo.lan = true;
|
||||
description = "colin-upnp-for-jellyfin";
|
||||
};
|
||||
sane.ports.ports."7359" = {
|
||||
protocol = [ "udp" ];
|
||||
visibleTo.lan = true;
|
||||
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" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
description = "colin-jellyfin-http-lan";
|
||||
};
|
||||
sane.ports.ports."8920" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
description = "colin-jellyfin-https-lan";
|
||||
};
|
||||
};
|
||||
|
||||
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";
|
||||
};
|
||||
}
|
||||
|
@@ -1,40 +1,42 @@
|
||||
{ pkgs, ... }:
|
||||
{ config, lib, pkgs, ... }:
|
||||
{
|
||||
sane.services.kiwix-serve = {
|
||||
enable = true;
|
||||
port = 8013;
|
||||
zimPaths = with pkgs.zimPackages; [
|
||||
alpinelinux_en_all_maxi.zimPath
|
||||
archlinux_en_all_maxi.zimPath
|
||||
bitcoin_en_all_maxi.zimPath
|
||||
devdocs_en_nix.zimPath
|
||||
gentoo_en_all_maxi.zimPath
|
||||
# khanacademy_en_all.zimPath #< TODO: enable
|
||||
openstreetmap-wiki_en_all_maxi.zimPath
|
||||
psychonautwiki_en_all_maxi.zimPath
|
||||
rationalwiki_en_all_maxi.zimPath
|
||||
# wikipedia_en_100.zimPath
|
||||
wikipedia_en_all_maxi.zimPath
|
||||
# wikipedia_en_all_mini.zimPath
|
||||
zimgit-food-preparation_en.zimPath
|
||||
zimgit-medicine_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;
|
||||
config = lib.mkIf (config.sane.maxBuildCost >= 3) {
|
||||
sane.services.kiwix-serve = {
|
||||
enable = true;
|
||||
port = 8013;
|
||||
zimPaths = with pkgs.zimPackages; [
|
||||
alpinelinux_en_all_maxi.zimPath
|
||||
archlinux_en_all_maxi.zimPath
|
||||
bitcoin_en_all_maxi.zimPath
|
||||
devdocs_en_nix.zimPath
|
||||
gentoo_en_all_maxi.zimPath
|
||||
# khanacademy_en_all.zimPath #< TODO: enable
|
||||
openstreetmap-wiki_en_all_maxi.zimPath
|
||||
psychonautwiki_en_all_maxi.zimPath
|
||||
rationalwiki_en_all_maxi.zimPath
|
||||
# wikipedia_en_100.zimPath
|
||||
wikipedia_en_all_maxi.zimPath
|
||||
# wikipedia_en_all_mini.zimPath
|
||||
zimgit-food-preparation_en.zimPath
|
||||
zimgit-medicine_en.zimPath
|
||||
zimgit-post-disaster_en.zimPath
|
||||
zimgit-water_en.zimPath
|
||||
];
|
||||
};
|
||||
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";
|
||||
};
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
# - <repo:LemmyNet/lemmy:docker/nginx.conf>
|
||||
# - <repo:LemmyNet/lemmy-ansible:templates/nginx.conf>
|
||||
|
||||
{ lib, pkgs, ... }:
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
uiPort = 1234; # default ui port is 1234
|
||||
backendPort = 8536; # default backend port is 8536
|
||||
@@ -24,154 +24,156 @@ let
|
||||
media.video.max_frame_count = 30 * 60 * 60;
|
||||
};
|
||||
in {
|
||||
services.lemmy = {
|
||||
enable = true;
|
||||
settings.hostname = "lemmy.uninsane.org";
|
||||
# federation.debug forces outbound federation queries to be run synchronously
|
||||
# N.B.: this option might not be read for 0.17.0+? <https://github.com/LemmyNet/lemmy/blob/c32585b03429f0f76d1e4ff738786321a0a9df98/RELEASES.md#upgrade-instructions>
|
||||
# settings.federation.debug = true;
|
||||
settings.port = backendPort;
|
||||
ui.port = uiPort;
|
||||
database.createLocally = true;
|
||||
nginx.enable = true;
|
||||
};
|
||||
config = lib.mkIf (config.sane.maxBuildCost >= 2) {
|
||||
services.lemmy = {
|
||||
enable = true;
|
||||
settings.hostname = "lemmy.uninsane.org";
|
||||
# federation.debug forces outbound federation queries to be run synchronously
|
||||
# N.B.: this option might not be read for 0.17.0+? <https://github.com/LemmyNet/lemmy/blob/c32585b03429f0f76d1e4ff738786321a0a9df98/RELEASES.md#upgrade-instructions>
|
||||
# settings.federation.debug = true;
|
||||
settings.port = backendPort;
|
||||
ui.port = uiPort;
|
||||
database.createLocally = true;
|
||||
nginx.enable = true;
|
||||
};
|
||||
|
||||
systemd.services.lemmy.environment = {
|
||||
RUST_BACKTRACE = "full";
|
||||
RUST_LOG = "error";
|
||||
# RUST_LOG = "warn";
|
||||
# RUST_LOG = "debug";
|
||||
# RUST_LOG = "trace";
|
||||
# upstream defaults LEMMY_DATABASE_URL = "postgres:///lemmy?host=/run/postgresql";
|
||||
# - Postgres complains that we didn't specify a user
|
||||
# lemmy formats the url as:
|
||||
# - postgres://{user}:{password}@{host}:{port}/{database}
|
||||
# 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&...]
|
||||
# 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 = lib.mkForce "postgres://lemmy@?host=/run/postgresql"; # WORKS
|
||||
LEMMY_DATABASE_URL = lib.mkForce "postgres://lemmy@/lemmy?host=/run/postgresql";
|
||||
};
|
||||
users.groups.lemmy = {};
|
||||
users.users.lemmy = {
|
||||
group = "lemmy";
|
||||
isSystemUser = true;
|
||||
};
|
||||
systemd.services.lemmy.environment = {
|
||||
RUST_BACKTRACE = "full";
|
||||
RUST_LOG = "error";
|
||||
# RUST_LOG = "warn";
|
||||
# RUST_LOG = "debug";
|
||||
# RUST_LOG = "trace";
|
||||
# upstream defaults LEMMY_DATABASE_URL = "postgres:///lemmy?host=/run/postgresql";
|
||||
# - Postgres complains that we didn't specify a user
|
||||
# lemmy formats the url as:
|
||||
# - postgres://{user}:{password}@{host}:{port}/{database}
|
||||
# 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&...]
|
||||
# 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 = lib.mkForce "postgres://lemmy@?host=/run/postgresql"; # WORKS
|
||||
LEMMY_DATABASE_URL = lib.mkForce "postgres://lemmy@/lemmy?host=/run/postgresql";
|
||||
};
|
||||
users.groups.lemmy = {};
|
||||
users.users.lemmy = {
|
||||
group = "lemmy";
|
||||
isSystemUser = true;
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."lemmy.uninsane.org" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
};
|
||||
services.nginx.virtualHosts."lemmy.uninsane.org" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
};
|
||||
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."lemmy" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."lemmy" = "native";
|
||||
|
||||
systemd.services.lemmy = {
|
||||
# fix to use a normal user so we can configure perms correctly
|
||||
# XXX(2024-07-28): this hasn't been rigorously tested:
|
||||
# possible that i've set something too strict and won't notice right away
|
||||
serviceConfig.DynamicUser = lib.mkForce false;
|
||||
serviceConfig.User = "lemmy";
|
||||
serviceConfig.Group = "lemmy";
|
||||
systemd.services.lemmy = {
|
||||
# fix to use a normal user so we can configure perms correctly
|
||||
# XXX(2024-07-28): this hasn't been rigorously tested:
|
||||
# possible that i've set something too strict and won't notice right away
|
||||
serviceConfig.DynamicUser = lib.mkForce false;
|
||||
serviceConfig.User = "lemmy";
|
||||
serviceConfig.Group = "lemmy";
|
||||
|
||||
# switch postgres from Requires -> Wants, so that postgres may restart without taking lemmy down with it.
|
||||
requires = lib.mkForce [];
|
||||
wants = [ "postgresql.service" ];
|
||||
# switch postgres from Requires -> Wants, so that postgres may restart without taking lemmy down with it.
|
||||
requires = lib.mkForce [];
|
||||
wants = [ "postgresql.service" ];
|
||||
|
||||
# hardening (systemd-analyze security lemmy)
|
||||
# a handful of these are specified in upstream nixpkgs, but mostly not
|
||||
serviceConfig.LockPersonality = true;
|
||||
serviceConfig.NoNewPrivileges = true;
|
||||
serviceConfig.MemoryDenyWriteExecute = true;
|
||||
serviceConfig.PrivateDevices = true;
|
||||
serviceConfig.PrivateMounts = true;
|
||||
serviceConfig.PrivateTmp = true;
|
||||
serviceConfig.PrivateUsers = true;
|
||||
serviceConfig.ProcSubset = "pid";
|
||||
# hardening (systemd-analyze security lemmy)
|
||||
# a handful of these are specified in upstream nixpkgs, but mostly not
|
||||
serviceConfig.LockPersonality = true;
|
||||
serviceConfig.NoNewPrivileges = true;
|
||||
serviceConfig.MemoryDenyWriteExecute = true;
|
||||
serviceConfig.PrivateDevices = true;
|
||||
serviceConfig.PrivateMounts = true;
|
||||
serviceConfig.PrivateTmp = true;
|
||||
serviceConfig.PrivateUsers = true;
|
||||
serviceConfig.ProcSubset = "pid";
|
||||
|
||||
serviceConfig.ProtectClock = true;
|
||||
serviceConfig.ProtectControlGroups = true;
|
||||
serviceConfig.ProtectHome = true;
|
||||
serviceConfig.ProtectHostname = true;
|
||||
serviceConfig.ProtectKernelLogs = true;
|
||||
serviceConfig.ProtectKernelModules = true;
|
||||
serviceConfig.ProtectKernelTunables = true;
|
||||
serviceConfig.ProtectProc = "invisible";
|
||||
serviceConfig.ProtectSystem = "strict";
|
||||
serviceConfig.RemoveIPC = true;
|
||||
serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
|
||||
serviceConfig.ProtectClock = true;
|
||||
serviceConfig.ProtectControlGroups = true;
|
||||
serviceConfig.ProtectHome = true;
|
||||
serviceConfig.ProtectHostname = true;
|
||||
serviceConfig.ProtectKernelLogs = true;
|
||||
serviceConfig.ProtectKernelModules = true;
|
||||
serviceConfig.ProtectKernelTunables = true;
|
||||
serviceConfig.ProtectProc = "invisible";
|
||||
serviceConfig.ProtectSystem = "strict";
|
||||
serviceConfig.RemoveIPC = true;
|
||||
serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
|
||||
|
||||
serviceConfig.RestrictNamespaces = true;
|
||||
serviceConfig.RestrictSUIDSGID = true;
|
||||
serviceConfig.SystemCallArchitectures = "native";
|
||||
serviceConfig.SystemCallFilter = [ "@system-service" ];
|
||||
};
|
||||
serviceConfig.RestrictNamespaces = true;
|
||||
serviceConfig.RestrictSUIDSGID = true;
|
||||
serviceConfig.SystemCallArchitectures = "native";
|
||||
serviceConfig.SystemCallFilter = [ "@system-service" ];
|
||||
};
|
||||
|
||||
systemd.services.lemmy-ui = {
|
||||
# hardening (systemd-analyze security lemmy-ui)
|
||||
# TODO: upstream into nixpkgs
|
||||
serviceConfig.LockPersonality = true;
|
||||
serviceConfig.NoNewPrivileges = true;
|
||||
# serviceConfig.MemoryDenyWriteExecute = true; #< it uses v8, JIT
|
||||
serviceConfig.PrivateDevices = true;
|
||||
serviceConfig.PrivateMounts = true;
|
||||
serviceConfig.PrivateTmp = true;
|
||||
serviceConfig.PrivateUsers = true;
|
||||
serviceConfig.ProcSubset = "pid";
|
||||
systemd.services.lemmy-ui = {
|
||||
# hardening (systemd-analyze security lemmy-ui)
|
||||
# TODO: upstream into nixpkgs
|
||||
serviceConfig.LockPersonality = true;
|
||||
serviceConfig.NoNewPrivileges = true;
|
||||
# serviceConfig.MemoryDenyWriteExecute = true; #< it uses v8, JIT
|
||||
serviceConfig.PrivateDevices = true;
|
||||
serviceConfig.PrivateMounts = true;
|
||||
serviceConfig.PrivateTmp = true;
|
||||
serviceConfig.PrivateUsers = true;
|
||||
serviceConfig.ProcSubset = "pid";
|
||||
|
||||
serviceConfig.ProtectClock = true;
|
||||
serviceConfig.ProtectControlGroups = true;
|
||||
serviceConfig.ProtectHome = true;
|
||||
serviceConfig.ProtectHostname = true;
|
||||
serviceConfig.ProtectKernelLogs = true;
|
||||
serviceConfig.ProtectKernelModules = true;
|
||||
serviceConfig.ProtectKernelTunables = true;
|
||||
serviceConfig.ProtectProc = "invisible";
|
||||
serviceConfig.ProtectSystem = "strict";
|
||||
serviceConfig.RemoveIPC = true;
|
||||
serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
|
||||
serviceConfig.ProtectClock = true;
|
||||
serviceConfig.ProtectControlGroups = true;
|
||||
serviceConfig.ProtectHome = true;
|
||||
serviceConfig.ProtectHostname = true;
|
||||
serviceConfig.ProtectKernelLogs = true;
|
||||
serviceConfig.ProtectKernelModules = true;
|
||||
serviceConfig.ProtectKernelTunables = true;
|
||||
serviceConfig.ProtectProc = "invisible";
|
||||
serviceConfig.ProtectSystem = "strict";
|
||||
serviceConfig.RemoveIPC = true;
|
||||
serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
|
||||
|
||||
serviceConfig.RestrictNamespaces = true;
|
||||
serviceConfig.RestrictSUIDSGID = true;
|
||||
serviceConfig.SystemCallArchitectures = "native";
|
||||
serviceConfig.SystemCallFilter = [ "@system-service" "@pkey" "@sandbox" ];
|
||||
};
|
||||
serviceConfig.RestrictNamespaces = true;
|
||||
serviceConfig.RestrictSUIDSGID = true;
|
||||
serviceConfig.SystemCallArchitectures = "native";
|
||||
serviceConfig.SystemCallFilter = [ "@system-service" "@pkey" "@sandbox" ];
|
||||
};
|
||||
|
||||
#v DO NOT REMOVE: defaults to 0.3, instead of latest, so always need to explicitly set this.
|
||||
services.pict-rs.package = pict-rs;
|
||||
#v DO NOT REMOVE: defaults to 0.3, instead of latest, so always need to explicitly set this.
|
||||
services.pict-rs.package = pict-rs;
|
||||
|
||||
systemd.services.pict-rs = {
|
||||
serviceConfig.ExecStart = lib.mkForce (lib.concatStringsSep " " [
|
||||
(lib.getExe pict-rs)
|
||||
"--config-file"
|
||||
tomlConfig
|
||||
"run"
|
||||
]);
|
||||
systemd.services.pict-rs = {
|
||||
serviceConfig.ExecStart = lib.mkForce (lib.concatStringsSep " " [
|
||||
(lib.getExe pict-rs)
|
||||
"--config-file"
|
||||
tomlConfig
|
||||
"run"
|
||||
]);
|
||||
|
||||
# hardening (systemd-analyze security pict-rs)
|
||||
# TODO: upstream into nixpkgs
|
||||
serviceConfig.LockPersonality = true;
|
||||
serviceConfig.NoNewPrivileges = true;
|
||||
serviceConfig.MemoryDenyWriteExecute = true;
|
||||
serviceConfig.PrivateDevices = true;
|
||||
serviceConfig.PrivateMounts = true;
|
||||
serviceConfig.PrivateTmp = true;
|
||||
serviceConfig.PrivateUsers = true;
|
||||
serviceConfig.ProcSubset = "pid";
|
||||
serviceConfig.ProtectClock = true;
|
||||
serviceConfig.ProtectControlGroups = true;
|
||||
serviceConfig.ProtectHome = true;
|
||||
serviceConfig.ProtectHostname = true;
|
||||
serviceConfig.ProtectKernelLogs = true;
|
||||
serviceConfig.ProtectKernelModules = true;
|
||||
serviceConfig.ProtectKernelTunables = true;
|
||||
serviceConfig.ProtectProc = "invisible";
|
||||
serviceConfig.ProtectSystem = "strict";
|
||||
serviceConfig.RemoveIPC = true;
|
||||
serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
|
||||
serviceConfig.RestrictNamespaces = true;
|
||||
serviceConfig.RestrictSUIDSGID = true;
|
||||
serviceConfig.SystemCallArchitectures = "native";
|
||||
serviceConfig.SystemCallFilter = [ "@system-service" ];
|
||||
# hardening (systemd-analyze security pict-rs)
|
||||
# TODO: upstream into nixpkgs
|
||||
serviceConfig.LockPersonality = true;
|
||||
serviceConfig.NoNewPrivileges = true;
|
||||
serviceConfig.MemoryDenyWriteExecute = true;
|
||||
serviceConfig.PrivateDevices = true;
|
||||
serviceConfig.PrivateMounts = true;
|
||||
serviceConfig.PrivateTmp = true;
|
||||
serviceConfig.PrivateUsers = true;
|
||||
serviceConfig.ProcSubset = "pid";
|
||||
serviceConfig.ProtectClock = true;
|
||||
serviceConfig.ProtectControlGroups = true;
|
||||
serviceConfig.ProtectHome = true;
|
||||
serviceConfig.ProtectHostname = true;
|
||||
serviceConfig.ProtectKernelLogs = true;
|
||||
serviceConfig.ProtectKernelModules = true;
|
||||
serviceConfig.ProtectKernelTunables = true;
|
||||
serviceConfig.ProtectProc = "invisible";
|
||||
serviceConfig.ProtectSystem = "strict";
|
||||
serviceConfig.RemoveIPC = true;
|
||||
serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
|
||||
serviceConfig.RestrictNamespaces = true;
|
||||
serviceConfig.RestrictSUIDSGID = true;
|
||||
serviceConfig.SystemCallArchitectures = "native";
|
||||
serviceConfig.SystemCallFilter = [ "@system-service" ];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@@ -14,207 +14,209 @@ let
|
||||
# logLevel = "debug";
|
||||
in
|
||||
{
|
||||
sane.persist.sys.byStore.private = [
|
||||
# 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.configs = [
|
||||
''
|
||||
import Config
|
||||
config = lib.mkIf (config.sane.maxBuildCost >= 2) {
|
||||
sane.persist.sys.byStore.private = [
|
||||
# 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.configs = [
|
||||
''
|
||||
import Config
|
||||
|
||||
config :pleroma, Pleroma.Web.Endpoint,
|
||||
url: [host: "fed.uninsane.org", scheme: "https", port: 443],
|
||||
http: [ip: {127, 0, 0, 1}, port: 4040]
|
||||
# secret_key_base: "{secrets.pleroma.secret_key_base}",
|
||||
# signing_salt: "{secrets.pleroma.signing_salt}"
|
||||
config :pleroma, Pleroma.Web.Endpoint,
|
||||
url: [host: "fed.uninsane.org", scheme: "https", port: 443],
|
||||
http: [ip: {127, 0, 0, 1}, port: 4040]
|
||||
# secret_key_base: "{secrets.pleroma.secret_key_base}",
|
||||
# signing_salt: "{secrets.pleroma.signing_salt}"
|
||||
|
||||
config :pleroma, :instance,
|
||||
name: "Perfectly Sane",
|
||||
description: "Single-user Pleroma instance",
|
||||
email: "admin.pleroma@uninsane.org",
|
||||
notify_email: "notify.pleroma@uninsane.org",
|
||||
limit: 5000,
|
||||
registrations_open: true,
|
||||
account_approval_required: true,
|
||||
max_pinned_statuses: 5,
|
||||
external_user_synchronization: true
|
||||
config :pleroma, :instance,
|
||||
name: "Perfectly Sane",
|
||||
description: "Single-user Pleroma instance",
|
||||
email: "admin.pleroma@uninsane.org",
|
||||
notify_email: "notify.pleroma@uninsane.org",
|
||||
limit: 5000,
|
||||
registrations_open: true,
|
||||
account_approval_required: true,
|
||||
max_pinned_statuses: 5,
|
||||
external_user_synchronization: true
|
||||
|
||||
# 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
|
||||
config :pleroma, Pleroma.Emails.Mailer,
|
||||
enabled: true,
|
||||
adapter: Swoosh.Adapters.Sendmail,
|
||||
cmd_path: "${lib.getExe' pkgs.postfix "sendmail"}"
|
||||
# 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
|
||||
config :pleroma, Pleroma.Emails.Mailer,
|
||||
enabled: true,
|
||||
adapter: Swoosh.Adapters.Sendmail,
|
||||
cmd_path: "${lib.getExe' pkgs.postfix "sendmail"}"
|
||||
|
||||
config :pleroma, Pleroma.User,
|
||||
restricted_nicknames: [ "admin", "uninsane", "root" ]
|
||||
config :pleroma, Pleroma.User,
|
||||
restricted_nicknames: [ "admin", "uninsane", "root" ]
|
||||
|
||||
config :pleroma, :media_proxy,
|
||||
enabled: false,
|
||||
redirect_on_failure: true
|
||||
#base_url: "https://cache.pleroma.social"
|
||||
config :pleroma, :media_proxy,
|
||||
enabled: false,
|
||||
redirect_on_failure: true
|
||||
#base_url: "https://cache.pleroma.social"
|
||||
|
||||
# see for reference:
|
||||
# - `force_custom_plan`: <https://docs.pleroma.social/backend/configuration/postgresql/#disable-generic-query-plans>
|
||||
config :pleroma, Pleroma.Repo,
|
||||
adapter: Ecto.Adapters.Postgres,
|
||||
username: "pleroma",
|
||||
database: "pleroma",
|
||||
hostname: "localhost",
|
||||
pool_size: 10,
|
||||
prepare: :named,
|
||||
parameters: [
|
||||
plan_cache_mode: "force_custom_plan"
|
||||
]
|
||||
# XXX: prepare: :named is needed only for PG <= 12
|
||||
# prepare: :named,
|
||||
# password: "{secrets.pleroma.db_password}",
|
||||
# see for reference:
|
||||
# - `force_custom_plan`: <https://docs.pleroma.social/backend/configuration/postgresql/#disable-generic-query-plans>
|
||||
config :pleroma, Pleroma.Repo,
|
||||
adapter: Ecto.Adapters.Postgres,
|
||||
username: "pleroma",
|
||||
database: "pleroma",
|
||||
hostname: "localhost",
|
||||
pool_size: 10,
|
||||
prepare: :named,
|
||||
parameters: [
|
||||
plan_cache_mode: "force_custom_plan"
|
||||
]
|
||||
# XXX: prepare: :named is needed only for PG <= 12
|
||||
# prepare: :named,
|
||||
# password: "{secrets.pleroma.db_password}",
|
||||
|
||||
# Configure web push notifications
|
||||
config :web_push_encryption, :vapid_details,
|
||||
subject: "mailto:notify.pleroma@uninsane.org"
|
||||
# public_key: "{secrets.pleroma.vapid_public_key}",
|
||||
# private_key: "{secrets.pleroma.vapid_private_key}"
|
||||
# Configure web push notifications
|
||||
config :web_push_encryption, :vapid_details,
|
||||
subject: "mailto:notify.pleroma@uninsane.org"
|
||||
# public_key: "{secrets.pleroma.vapid_public_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, :instance, static_dir: "/var/lib/pleroma/instance/static"
|
||||
config :pleroma, Pleroma.Uploaders.Local, uploads: "/var/lib/pleroma/uploads"
|
||||
config :pleroma, configurable_from_database: false
|
||||
config :pleroma, :database, rum_enabled: false
|
||||
config :pleroma, :instance, static_dir: "/var/lib/pleroma/instance/static"
|
||||
config :pleroma, Pleroma.Uploaders.Local, uploads: "/var/lib/pleroma/uploads"
|
||||
config :pleroma, configurable_from_database: false
|
||||
|
||||
# strip metadata from uploaded images
|
||||
config :pleroma, Pleroma.Upload, filters: [Pleroma.Upload.Filter.Exiftool.StripLocation]
|
||||
# strip metadata from uploaded images
|
||||
config :pleroma, Pleroma.Upload, filters: [Pleroma.Upload.Filter.Exiftool.StripLocation]
|
||||
|
||||
# fix log spam: <https://git.pleroma.social/pleroma/pleroma/-/issues/1659>
|
||||
# specifically, remove LAN addresses from `reserved`
|
||||
config :pleroma, Pleroma.Web.Plugs.RemoteIp,
|
||||
enabled: true,
|
||||
reserved: ["127.0.0.0/8", "::1/128", "fc00::/7", "172.16.0.0/12"]
|
||||
# fix log spam: <https://git.pleroma.social/pleroma/pleroma/-/issues/1659>
|
||||
# specifically, remove LAN addresses from `reserved`
|
||||
config :pleroma, Pleroma.Web.Plugs.RemoteIp,
|
||||
enabled: true,
|
||||
reserved: ["127.0.0.0/8", "::1/128", "fc00::/7", "172.16.0.0/12"]
|
||||
|
||||
# TODO: GET /api/pleroma/captcha is broken
|
||||
# there was a nixpkgs PR to fix this around 2022/10 though.
|
||||
config :pleroma, Pleroma.Captcha,
|
||||
enabled: false,
|
||||
method: Pleroma.Captcha.Native
|
||||
# TODO: GET /api/pleroma/captcha is broken
|
||||
# there was a nixpkgs PR to fix this around 2022/10 though.
|
||||
config :pleroma, Pleroma.Captcha,
|
||||
enabled: false,
|
||||
method: Pleroma.Captcha.Native
|
||||
|
||||
|
||||
# (enabled by colin)
|
||||
# Enable Strict-Transport-Security once SSL is working:
|
||||
config :pleroma, :http_security,
|
||||
sts: true
|
||||
# (enabled by colin)
|
||||
# Enable Strict-Transport-Security once SSL is working:
|
||||
config :pleroma, :http_security,
|
||||
sts: true
|
||||
|
||||
# docs: https://docs.pleroma.social/backend/configuration/cheatsheet/#logger
|
||||
config :logger,
|
||||
backends: [{ExSyslogger, :ex_syslogger}]
|
||||
# docs: https://docs.pleroma.social/backend/configuration/cheatsheet/#logger
|
||||
config :logger,
|
||||
backends: [{ExSyslogger, :ex_syslogger}]
|
||||
|
||||
config :logger, :ex_syslogger,
|
||||
level: :${logLevel}
|
||||
config :logger, :ex_syslogger,
|
||||
level: :${logLevel}
|
||||
|
||||
# policies => list of message rewriting facilities to be enabled
|
||||
# transparence => whether to publish these rules in node_info (and /about)
|
||||
config :pleroma, :mrf,
|
||||
policies: [Pleroma.Web.ActivityPub.MRF.SimplePolicy],
|
||||
transparency: true
|
||||
# policies => list of message rewriting facilities to be enabled
|
||||
# transparence => whether to publish these rules in node_info (and /about)
|
||||
config :pleroma, :mrf,
|
||||
policies: [Pleroma.Web.ActivityPub.MRF.SimplePolicy],
|
||||
transparency: true
|
||||
|
||||
# reject => { host, reason }
|
||||
config :pleroma, :mrf_simple,
|
||||
reject: [ {"threads.net", "megacorp"}, {"*.threads.net", "megacorp"} ]
|
||||
# reject: [ [host: "threads.net", reason: "megacorp"], [host: "*.threads.net", reason: "megacorp"] ]
|
||||
# reject => { host, reason }
|
||||
config :pleroma, :mrf_simple,
|
||||
reject: [ {"threads.net", "megacorp"}, {"*.threads.net", "megacorp"} ]
|
||||
# reject: [ [host: "threads.net", reason: "megacorp"], [host: "*.threads.net", reason: "megacorp"] ]
|
||||
|
||||
# XXX colin: not sure if this actually _does_ anything
|
||||
# better to steal emoji from other instances?
|
||||
# - <https://docs.pleroma.social/backend/configuration/cheatsheet/#mrf_steal_emoji>
|
||||
config :pleroma, :emoji,
|
||||
shortcode_globs: ["/emoji/**/*.png"],
|
||||
groups: [
|
||||
"Cirno": "/emoji/cirno/*.png",
|
||||
"Kirby": "/emoji/kirby/*.png",
|
||||
"Bun": "/emoji/bun/*.png",
|
||||
"Yuru Camp": "/emoji/yuru_camp/*.png",
|
||||
]
|
||||
''
|
||||
];
|
||||
# XXX colin: not sure if this actually _does_ anything
|
||||
# better to steal emoji from other instances?
|
||||
# - <https://docs.pleroma.social/backend/configuration/cheatsheet/#mrf_steal_emoji>
|
||||
config :pleroma, :emoji,
|
||||
shortcode_globs: ["/emoji/**/*.png"],
|
||||
groups: [
|
||||
"Cirno": "/emoji/cirno/*.png",
|
||||
"Kirby": "/emoji/kirby/*.png",
|
||||
"Bun": "/emoji/bun/*.png",
|
||||
"Yuru Camp": "/emoji/yuru_camp/*.png",
|
||||
]
|
||||
''
|
||||
];
|
||||
|
||||
systemd.services.pleroma.path = [
|
||||
# something inside pleroma invokes `sh` w/o specifying it by path, so this is needed to allow pleroma to start
|
||||
pkgs.bash
|
||||
# used by Pleroma to strip geo tags from uploads
|
||||
pkgs.exiftool
|
||||
# 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
|
||||
# config.sane.programs.gawk.package
|
||||
# needed for email operations like password reset
|
||||
pkgs.postfix
|
||||
];
|
||||
systemd.services.pleroma.path = [
|
||||
# something inside pleroma invokes `sh` w/o specifying it by path, so this is needed to allow pleroma to start
|
||||
pkgs.bash
|
||||
# used by Pleroma to strip geo tags from uploads
|
||||
pkgs.exiftool
|
||||
# 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
|
||||
# config.sane.programs.gawk.package
|
||||
# needed for email operations like password reset
|
||||
pkgs.postfix
|
||||
];
|
||||
|
||||
systemd.services.pleroma = {
|
||||
# postgres can be slow to service early requests, preventing pleroma from starting on the first try
|
||||
serviceConfig.Restart = "on-failure";
|
||||
serviceConfig.RestartSec = "10s";
|
||||
systemd.services.pleroma = {
|
||||
# postgres can be slow to service early requests, preventing pleroma from starting on the first try
|
||||
serviceConfig.Restart = "on-failure";
|
||||
serviceConfig.RestartSec = "10s";
|
||||
|
||||
# hardening (systemd-analyze security pleroma)
|
||||
# XXX(2024-07-28): this hasn't been rigorously tested:
|
||||
# possible that i've set something too strict and won't notice right away
|
||||
# make sure to test:
|
||||
# - image/media uploading
|
||||
serviceConfig.CapabilityBoundingSet = lib.mkForce [ "" "" ]; # nixos default is `~CAP_SYS_ADMIN`
|
||||
serviceConfig.LockPersonality = true;
|
||||
serviceConfig.NoNewPrivileges = true;
|
||||
serviceConfig.MemoryDenyWriteExecute = true;
|
||||
serviceConfig.PrivateDevices = lib.mkForce true; #< dunno why nixpkgs has this set false; it seems to work as true
|
||||
serviceConfig.PrivateMounts = true;
|
||||
serviceConfig.PrivateTmp = true;
|
||||
serviceConfig.PrivateUsers = true;
|
||||
# hardening (systemd-analyze security pleroma)
|
||||
# XXX(2024-07-28): this hasn't been rigorously tested:
|
||||
# possible that i've set something too strict and won't notice right away
|
||||
# make sure to test:
|
||||
# - image/media uploading
|
||||
serviceConfig.CapabilityBoundingSet = lib.mkForce [ "" "" ]; # nixos default is `~CAP_SYS_ADMIN`
|
||||
serviceConfig.LockPersonality = true;
|
||||
serviceConfig.NoNewPrivileges = true;
|
||||
serviceConfig.MemoryDenyWriteExecute = true;
|
||||
serviceConfig.PrivateDevices = lib.mkForce true; #< dunno why nixpkgs has this set false; it seems to work as true
|
||||
serviceConfig.PrivateMounts = true;
|
||||
serviceConfig.PrivateTmp = true;
|
||||
serviceConfig.PrivateUsers = true;
|
||||
|
||||
serviceConfig.ProtectProc = "invisible";
|
||||
serviceConfig.ProcSubset = "all"; #< needs /proc/sys/kernel/overflowuid for bwrap
|
||||
serviceConfig.ProtectProc = "invisible";
|
||||
serviceConfig.ProcSubset = "all"; #< needs /proc/sys/kernel/overflowuid for bwrap
|
||||
|
||||
serviceConfig.ProtectClock = true;
|
||||
serviceConfig.ProtectControlGroups = true;
|
||||
serviceConfig.ProtectHome = true;
|
||||
serviceConfig.ProtectKernelModules = true;
|
||||
serviceConfig.ProtectSystem = lib.mkForce "strict";
|
||||
serviceConfig.RemoveIPC = true;
|
||||
serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_NETLINK";
|
||||
serviceConfig.ProtectClock = true;
|
||||
serviceConfig.ProtectControlGroups = true;
|
||||
serviceConfig.ProtectHome = true;
|
||||
serviceConfig.ProtectKernelModules = true;
|
||||
serviceConfig.ProtectSystem = lib.mkForce "strict";
|
||||
serviceConfig.RemoveIPC = true;
|
||||
serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_NETLINK";
|
||||
|
||||
serviceConfig.RestrictSUIDSGID = true;
|
||||
serviceConfig.SystemCallArchitectures = "native";
|
||||
serviceConfig.SystemCallFilter = [ "@system-service" "@mount" "@sandbox" ]; #< "sandbox" might not actually be necessary
|
||||
serviceConfig.RestrictSUIDSGID = true;
|
||||
serviceConfig.SystemCallArchitectures = "native";
|
||||
serviceConfig.SystemCallFilter = [ "@system-service" "@mount" "@sandbox" ]; #< "sandbox" might not actually be necessary
|
||||
|
||||
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.ProtectKernelTunables = false; #< else breaks exiftool
|
||||
serviceConfig.RestrictNamespaces = false; # media uploads require bwrap
|
||||
};
|
||||
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.ProtectKernelTunables = false; #< else breaks exiftool
|
||||
serviceConfig.RestrictNamespaces = false; # media uploads require bwrap
|
||||
};
|
||||
|
||||
# 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.
|
||||
# hack to fix that.
|
||||
users.users.pleroma.extraGroups = [ "postdrop" ];
|
||||
# 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.
|
||||
# hack to fix that.
|
||||
users.users.pleroma.extraGroups = [ "postdrop" ];
|
||||
|
||||
# Pleroma server and web interface
|
||||
# TODO: enable publog?
|
||||
services.nginx.virtualHosts."fed.uninsane.org" = {
|
||||
forceSSL = true; # pleroma redirects to https anyway
|
||||
enableACME = true;
|
||||
# inherit kTLS;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:4040";
|
||||
recommendedProxySettings = true;
|
||||
# documented: https://git.pleroma.social/pleroma/pleroma/-/blob/develop/installation/pleroma.nginx
|
||||
extraConfig = ''
|
||||
# client_max_body_size defines the maximum upload size
|
||||
client_max_body_size 16m;
|
||||
'';
|
||||
# Pleroma server and web interface
|
||||
# TODO: enable publog?
|
||||
services.nginx.virtualHosts."fed.uninsane.org" = {
|
||||
forceSSL = true; # pleroma redirects to https anyway
|
||||
enableACME = true;
|
||||
# inherit kTLS;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:4040";
|
||||
recommendedProxySettings = true;
|
||||
# documented: https://git.pleroma.social/pleroma/pleroma/-/blob/develop/installation/pleroma.nginx
|
||||
extraConfig = ''
|
||||
# client_max_body_size defines the maximum upload size
|
||||
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;
|
||||
};
|
||||
}
|
||||
|
@@ -4,11 +4,12 @@
|
||||
# useful emergency utils
|
||||
boot.initrd.extraUtilsCommands = ''
|
||||
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.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.smartmontools "smartctl"}
|
||||
copy_bin_and_libs ${lib.getExe' pkgs.util-linux "{cfdisk,lsblk,lscpu}"}
|
||||
'';
|
||||
boot.kernelParams = [
|
||||
"boot.shell_on_fail"
|
||||
@@ -39,6 +40,10 @@
|
||||
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.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);
|
||||
|
||||
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)
|
||||
|
@@ -79,7 +79,7 @@ lib.mkMerge [
|
||||
(ifSshAuthorized (remoteHome "crappy" {}))
|
||||
(ifSshAuthorized (remoteHome "desko" {}))
|
||||
(ifSshAuthorized (remoteHome "flowy" {}))
|
||||
(ifSshAuthorized (remoteHome "lappy" {}))
|
||||
# (ifSshAuthorized (remoteHome "lappy" {}))
|
||||
(ifSshAuthorized (remoteHome "moby" { host = "moby-hn"; }))
|
||||
(ifSshAuthorized (remoteHome "servo" {}))
|
||||
]
|
||||
|
@@ -32,13 +32,13 @@
|
||||
lan-ip = "10.78.79.56";
|
||||
};
|
||||
|
||||
sane.hosts.by-name."lappy" = {
|
||||
ssh.user_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDpmFdNSVPRol5hkbbCivRhyeENzb9HVyf9KutGLP2Zu";
|
||||
ssh.host_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILSJnqmVl9/SYQ0btvGb0REwwWY8wkdkGXQZfn/1geEc";
|
||||
wg-home.pubkey = "FTUWGw2p4/cEcrrIE86PWVnqctbv8OYpw8Gt3+dC/lk=";
|
||||
wg-home.ip = "10.0.10.20";
|
||||
lan-ip = "10.78.79.53";
|
||||
};
|
||||
# sane.hosts.by-name."lappy" = {
|
||||
# ssh.user_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDpmFdNSVPRol5hkbbCivRhyeENzb9HVyf9KutGLP2Zu";
|
||||
# ssh.host_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILSJnqmVl9/SYQ0btvGb0REwwWY8wkdkGXQZfn/1geEc";
|
||||
# wg-home.pubkey = "FTUWGw2p4/cEcrrIE86PWVnqctbv8OYpw8Gt3+dC/lk=";
|
||||
# wg-home.ip = "10.0.10.20";
|
||||
# lan-ip = "10.78.79.53";
|
||||
# };
|
||||
|
||||
sane.hosts.by-name."moby" = {
|
||||
# ssh.authorized = lib.mkDefault false; # moby's too easy to hijack: don't let it ssh places
|
||||
|
@@ -6,8 +6,9 @@ let
|
||||
# nixpkgs' pam hardcodes unix_chkpwd path to the /run/wrappers one,
|
||||
# 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.
|
||||
# see: <repo:nixos/nixpkgs:pkgs/by-name/li/linux-pam/package.nix>
|
||||
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"
|
||||
'';
|
||||
});
|
||||
|
@@ -1194,6 +1194,10 @@ in
|
||||
|
||||
typescript-language-server.buildCost = 2;
|
||||
typescript-language-server.sandbox.whitelistPwd = true;
|
||||
typescript-language-server.persist.byStore.ephemeral = [
|
||||
".cache/typescript"
|
||||
".npm" # .npm/{_cacache,_logs}
|
||||
];
|
||||
|
||||
tumiki-fighters.buildCost = 1;
|
||||
tumiki-fighters.sandbox.whitelistAudio = true;
|
||||
|
@@ -16,6 +16,7 @@
|
||||
<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/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://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
|
||||
@@ -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.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.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="google">Search Google
|
||||
<dt><a href="https://www.google.com/search?tbm=shop&q=%s" shortcuturl="shopping">Search Google Shopping
|
||||
|
@@ -43,6 +43,10 @@ in
|
||||
"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.
|
||||
# alternative to PASSWORD_STORE_DIR:
|
||||
# fs.".password-store".symlink.target = "knowledge/secrets/accounts";
|
||||
|
@@ -16,7 +16,9 @@ let
|
||||
cfg.addons
|
||||
);
|
||||
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
|
||||
unwrapped = pkgs.firefox-unwrapped // {
|
||||
@@ -29,7 +31,8 @@ let
|
||||
# inherit the default librewolf.cfg
|
||||
# it can be further customized via ~/.librewolf/librewolf.overrides.cfg
|
||||
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);
|
||||
|
||||
|
@@ -143,9 +143,20 @@ defaultPref("browser.shell.checkDefaultBrowser", false);
|
||||
// disable extension updates
|
||||
defaultPref("extensions.update.autoUpdateDefault", false);
|
||||
defaultPref("extensions.update.enabled", false);
|
||||
defaultPref("extensions.systemAddon.update.enabled", false);
|
||||
// wipe the URIs used to check for updates, as a precaution.
|
||||
defaultPref("extensions.update.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.migration.version = 150
|
||||
|
@@ -36,7 +36,8 @@
|
||||
sandbox.extraPaths = [
|
||||
"/boot"
|
||||
"/mnt/desko"
|
||||
"/mnt/lappy"
|
||||
"/mnt/flowy"
|
||||
# "/mnt/lappy"
|
||||
"/mnt/moby"
|
||||
"/mnt/servo"
|
||||
# "nix"
|
||||
|
@@ -67,12 +67,12 @@ in
|
||||
viAlias = true;
|
||||
vimAlias = true;
|
||||
plugins = plugin-packages;
|
||||
customRC = ''
|
||||
${builtins.readFile ./vimrc}
|
||||
# customRC = ''
|
||||
# ${builtins.readFile ./vimrc}
|
||||
|
||||
""""" PLUGIN CONFIG
|
||||
${plugin-configs}
|
||||
'';
|
||||
# """"" PLUGIN CONFIG
|
||||
# ${plugin-configs}
|
||||
# '';
|
||||
};
|
||||
neovim-unwrapped' = with pkgs; neovim-unwrapped.overrideAttrs (upstream: {
|
||||
# fix cross compilation:
|
||||
@@ -122,9 +122,17 @@ in
|
||||
# due to <https://github.com/NixOS/nixpkgs/pull/344541>
|
||||
rubyEnv = null;
|
||||
withRuby = false;
|
||||
wrapRc = false; #< don't force VIMINIT env var
|
||||
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
|
||||
persist.byStore.private = [ ".cache/vim-swap" ];
|
||||
env.EDITOR = "vim";
|
||||
|
@@ -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
|
||||
" this used to be default, until <https://github.com/neovim/neovim/pull/19290>
|
||||
set mouse=
|
||||
|
@@ -1,4 +1,7 @@
|
||||
{ config, pkgs, ... }:
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.sane.programs.nvimpager;
|
||||
in
|
||||
{
|
||||
sane.programs.nvimpager = {
|
||||
packageUnwrapped = (pkgs.nvimpager.override {
|
||||
@@ -10,6 +13,9 @@
|
||||
|
||||
suggestedPrograms = [ "neovim" ];
|
||||
|
||||
sandbox.extraHomePaths = [
|
||||
".config/nvim"
|
||||
];
|
||||
sandbox.whitelistWayland = true; # for system clipboard integration
|
||||
|
||||
env.MANPAGER = "nvimpager";
|
||||
@@ -21,4 +27,8 @@
|
||||
env.MANWIDTH = "999";
|
||||
env.MANROFFOPT = "-c";
|
||||
};
|
||||
|
||||
sane.programs.man-db.sandbox.extraHomePaths = lib.mkIf cfg.enabled [
|
||||
".config/nvim"
|
||||
];
|
||||
}
|
||||
|
@@ -11,6 +11,10 @@ let
|
||||
type = lib.types.bool;
|
||||
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: {
|
||||
patches = (upstream.patches or []) ++ [
|
||||
(pkgs.fetchpatch {
|
||||
@@ -108,6 +112,9 @@ in
|
||||
|
||||
packageUnwrapped = (pkgs.nwg-panel.override {
|
||||
inherit playerctl;
|
||||
python3Packages = pkgs.python3Packages // {
|
||||
inherit i3ipc;
|
||||
};
|
||||
}).overrideAttrs (base: {
|
||||
# patches = (base.patches or []) ++ lib.optionals (!cfg.config.mediaPrevNext) [
|
||||
# ./playerctl-no-prev-next.diff
|
||||
|
@@ -65,7 +65,8 @@
|
||||
sandbox.extraPaths = [
|
||||
"/boot"
|
||||
"/mnt/desko"
|
||||
"/mnt/lappy"
|
||||
"/mnt/flowy"
|
||||
# "/mnt/lappy"
|
||||
"/mnt/moby"
|
||||
"/mnt/servo"
|
||||
# "nix"
|
||||
|
@@ -116,9 +116,9 @@ in
|
||||
# see: `man logind.conf`
|
||||
# don’t 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.
|
||||
services.logind.powerKey = "lock";
|
||||
services.logind.powerKeyLongPress = "poweroff";
|
||||
services.logind.lidSwitch = "lock";
|
||||
services.logind.settings.Login.HandlePowerKey = "lock";
|
||||
services.logind.settings.Login.HandlePowerKeyLongPress = "poweroff";
|
||||
services.logind.settings.Login.HandleLidSwitch = "lock";
|
||||
# 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.
|
||||
services.udev.extraRules = ''
|
||||
|
@@ -11,6 +11,7 @@ in
|
||||
config = lib.mkIf cfg.enable {
|
||||
# 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.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.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)
|
||||
|
@@ -209,9 +209,12 @@ in
|
||||
# from <repo:nixos/nixpkgs:nixos/modules/system/boot/kernel.nix> AKA pkgs.aggregateModules
|
||||
# but configured to **ignore collisions**
|
||||
system.modulesTree = lib.mkForce [(
|
||||
(pkgs.aggregateModules
|
||||
( config.boot.extraModulePackages ++ [ config.boot.kernelPackages.kernel ])
|
||||
).overrideAttrs {
|
||||
(pkgs.aggregateModules (
|
||||
config.boot.extraModulePackages ++ [
|
||||
(lib.getOutput "modules" config.boot.kernelPackages.kernel)
|
||||
]
|
||||
)).overrideAttrs {
|
||||
name = "kernel-modules-merged-sane";
|
||||
# earlier items override the contents of later items
|
||||
ignoreCollisions = true;
|
||||
# checkCollisionContents = false;
|
||||
|
@@ -417,7 +417,7 @@ in
|
||||
sort-key nixos
|
||||
version Generation 0 NixOS
|
||||
linux $efi_kernel
|
||||
initrd $initrd
|
||||
initrd $efi_initrd
|
||||
options init=$toplevel/init $kernel_params
|
||||
EOF
|
||||
cat > $out/loader/loader.conf <<EOF
|
||||
|
@@ -1,39 +1,6 @@
|
||||
# outstanding cross-compilation PRs/issues:
|
||||
# - all: <https://github.com/NixOS/nixpkgs/labels/6.topic%3A%20cross-compilation>
|
||||
# - qtsvg mixed deps: <https://github.com/NixOS/nixpkgs/issues/269756>
|
||||
# - 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.
|
||||
# tracking:
|
||||
# - all cross compilation PRs: <https://github.com/NixOS/nixpkgs/labels/6.topic%3A%20cross-compilation>
|
||||
# - potential idiom to fix cross cargo-inside-meson: <https://github.com/NixOS/nixpkgs/pull/434878>
|
||||
|
||||
final: prev:
|
||||
let
|
||||
@@ -85,63 +52,63 @@ let
|
||||
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
|
||||
crossCargo = let
|
||||
inherit (final.pkgsBuildHost) cargo;
|
||||
inherit (final.rust.envVars) setEnv rustHostPlatformSpec;
|
||||
in (final.pkgsBuildBuild.writeShellScriptBin "cargo" ''
|
||||
targetDir=target
|
||||
isFlavored=
|
||||
outDir=
|
||||
profile=
|
||||
# crossCargo = let
|
||||
# inherit (final.pkgsBuildHost) cargo;
|
||||
# inherit (final.rust.envVars) setEnv rustHostPlatformSpec;
|
||||
# in (final.pkgsBuildBuild.writeShellScriptBin "cargo" ''
|
||||
# targetDir=target
|
||||
# isFlavored=
|
||||
# outDir=
|
||||
# profile=
|
||||
|
||||
cargoArgs=("$@")
|
||||
nextIsOutDir=
|
||||
nextIsProfile=
|
||||
nextIsTargetDir=
|
||||
for arg in "''${cargoArgs[@]}"; do
|
||||
if [[ -n "$nextIsOutDir" ]]; then
|
||||
nextIsOutDir=
|
||||
outDir="$arg"
|
||||
elif [[ -n "$nextIsProfile" ]]; then
|
||||
nextIsProfile=
|
||||
profile="$arg"
|
||||
elif [[ -n "$nextIsTargetDir" ]]; then
|
||||
nextIsTargetDir=
|
||||
targetDir="$arg"
|
||||
elif [[ "$arg" = "build" ]]; then
|
||||
isFlavored=1
|
||||
elif [[ "$arg" = "--out-dir" ]]; then
|
||||
nextIsOutDir=1
|
||||
elif [[ "$arg" = "--profile" ]]; then
|
||||
nextIsProfile=1
|
||||
elif [[ "$arg" = "--release" ]]; then
|
||||
profile=release
|
||||
elif [[ "$arg" = "--target-dir" ]]; then
|
||||
nextIsTargetDir=1
|
||||
fi
|
||||
done
|
||||
# cargoArgs=("$@")
|
||||
# nextIsOutDir=
|
||||
# nextIsProfile=
|
||||
# nextIsTargetDir=
|
||||
# for arg in "''${cargoArgs[@]}"; do
|
||||
# if [[ -n "$nextIsOutDir" ]]; then
|
||||
# nextIsOutDir=
|
||||
# outDir="$arg"
|
||||
# elif [[ -n "$nextIsProfile" ]]; then
|
||||
# nextIsProfile=
|
||||
# profile="$arg"
|
||||
# elif [[ -n "$nextIsTargetDir" ]]; then
|
||||
# nextIsTargetDir=
|
||||
# targetDir="$arg"
|
||||
# elif [[ "$arg" = "build" ]]; then
|
||||
# isFlavored=1
|
||||
# elif [[ "$arg" = "--out-dir" ]]; then
|
||||
# nextIsOutDir=1
|
||||
# elif [[ "$arg" = "--profile" ]]; then
|
||||
# nextIsProfile=1
|
||||
# elif [[ "$arg" = "--release" ]]; then
|
||||
# profile=release
|
||||
# elif [[ "$arg" = "--target-dir" ]]; then
|
||||
# nextIsTargetDir=1
|
||||
# fi
|
||||
# done
|
||||
|
||||
extraFlags=()
|
||||
# extraFlags=()
|
||||
|
||||
# not all subcommands support flavored arguments like `--target`
|
||||
if [ -n "$isFlavored" ]; then
|
||||
# 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>
|
||||
extraFlags+=(
|
||||
--target "${rustHostPlatformSpec}"
|
||||
-Z unstable-options
|
||||
)
|
||||
if [ -z "$outDir" ]; then
|
||||
extraFlags+=(
|
||||
--out-dir "$targetDir"/''${profile:-debug}
|
||||
)
|
||||
fi
|
||||
fi
|
||||
# # not all subcommands support flavored arguments like `--target`
|
||||
# if [ -n "$isFlavored" ]; then
|
||||
# # 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>
|
||||
# extraFlags+=(
|
||||
# --target "${rustHostPlatformSpec}"
|
||||
# -Z unstable-options
|
||||
# )
|
||||
# if [ -z "$outDir" ]; then
|
||||
# extraFlags+=(
|
||||
# --out-dir "$targetDir"/''${profile:-debug}
|
||||
# )
|
||||
# fi
|
||||
# fi
|
||||
|
||||
exec ${setEnv} "${lib.getExe cargo}" "$@" "''${extraFlags[@]}"
|
||||
'').overrideAttrs {
|
||||
inherit (cargo) meta;
|
||||
};
|
||||
# exec ${setEnv} "${lib.getExe cargo}" "$@" "''${extraFlags[@]}"
|
||||
# '').overrideAttrs {
|
||||
# inherit (cargo) meta;
|
||||
# };
|
||||
in with final; {
|
||||
# binutils = prev.binutils.override {
|
||||
# # fix that resulting binary files would specify build #!sh as their interpreter.
|
||||
@@ -171,10 +138,10 @@ in with final; {
|
||||
'';
|
||||
});
|
||||
|
||||
# 2025/07/27: upstreaming is unblocked
|
||||
delfin = prev.delfin.override {
|
||||
cargo = crossCargo;
|
||||
};
|
||||
# 2025/08/26: upstreaming is unblocked, on desko branch `pr-delfin-cross`
|
||||
# delfin = prev.delfin.override {
|
||||
# cargo = crossCargo;
|
||||
# };
|
||||
|
||||
# 2025/07/27: upstreaming is unblocked
|
||||
# dtrx = prev.dtrx.override {
|
||||
@@ -185,6 +152,10 @@ in with final; {
|
||||
# binutils = binutils-unwrapped;
|
||||
# };
|
||||
|
||||
# envelope = prev.envelope.override {
|
||||
# cargo = crossCargo;
|
||||
# };
|
||||
|
||||
# 2025/07/27: upstreaming is unblocked
|
||||
# emacs = prev.emacs.override {
|
||||
# nativeComp = false; # will be renamed to `withNativeCompilation` in future
|
||||
@@ -192,10 +163,6 @@ in with final; {
|
||||
# # <https://www.gnu.org/software/autoconf/manual/autoconf-2.63/html_node/Runtime.html>
|
||||
# };
|
||||
|
||||
envelope = prev.envelope.override {
|
||||
cargo = crossCargo; #< fixes openssl not being able to find its library
|
||||
};
|
||||
|
||||
# 2025/07/27: upstreaming is unblocked
|
||||
# firejail = prev.firejail.overrideAttrs (upstream: {
|
||||
# # firejail executes its build outputs to produce the default filter list.
|
||||
@@ -232,15 +199,10 @@ in with final; {
|
||||
# };
|
||||
# });
|
||||
|
||||
# 2025/07/27: upstreaming is blocked by glycin-loaders
|
||||
fractal = prev.fractal.override {
|
||||
cargo = crossCargo;
|
||||
};
|
||||
|
||||
# 2025/07/27: upstreaming is unblocked
|
||||
glycin-loaders = prev.glycin-loaders.override {
|
||||
cargo = crossCargo;
|
||||
};
|
||||
# 2025/08/26: upstreaming is unblocked, out for PR: <https://github.com/NixOS/nixpkgs/pull/437038>
|
||||
# fractal = prev.fractal.override {
|
||||
# cargo = crossCargo;
|
||||
# };
|
||||
|
||||
# 2025/07/27: upstreaming is blocked on gnome-shell
|
||||
# fixes: "gdbus-codegen not found or executable"
|
||||
@@ -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
|
||||
# # gnustep is going to need a *lot* of work/domain-specific knowledge to truly cross-compile,
|
||||
# gnustep-base = prev.gnustep-base.overrideAttrs (upstream: {
|
||||
@@ -338,7 +295,7 @@ in with final; {
|
||||
# ];
|
||||
# });
|
||||
|
||||
lemoa = prev.lemoa.override { cargo = crossCargo; };
|
||||
# lemoa = prev.lemoa.override { cargo = crossCargo; };
|
||||
|
||||
# libsForQt5 = prev.libsForQt5.overrideScope (self: super: {
|
||||
# # 2025/07/27: upstreaming is blocked on qtsvg
|
||||
@@ -354,11 +311,6 @@ in with final; {
|
||||
# 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
|
||||
mepo = (prev.mepo.override {
|
||||
# nixpkgs mepo correctly puts `zig_0_13.hook` in nativeBuildInputs,
|
||||
@@ -397,46 +349,6 @@ in with final; {
|
||||
# 2025/07/27: upstreaming is unblocked by deps; but turns out to not be this simple
|
||||
# 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"
|
||||
# - by providing glib-compile-resources
|
||||
# 2025/07/27: upstreaming is blocked on gst-plugins-good, qtkeychain, qtmultimedia, qtquick3d, qt-jdenticon
|
||||
@@ -506,7 +418,7 @@ in with final; {
|
||||
# # buildInputs = lib.remove gnupg upstream.buildInputs;
|
||||
# });
|
||||
|
||||
# 2025/07/27: upstreaming is unblocked, but most of this belongs in _oils_ repo
|
||||
# 2025/08/17: upstreaming is unblocked, but most of this belongs in _oils_ repo
|
||||
oils-for-unix = prev.oils-for-unix.overrideAttrs (upstream: {
|
||||
postPatch = (upstream.postPatch or "") + ''
|
||||
substituteInPlace _build/oils.sh \
|
||||
@@ -530,10 +442,10 @@ in with final; {
|
||||
];
|
||||
});
|
||||
|
||||
# 2025/07/27: upstreaming is blocked on gnome-user-share, nautilus
|
||||
papers = prev.papers.override {
|
||||
cargo = crossCargo;
|
||||
};
|
||||
# 2025/08/26: upstreaming is unblocked; TODO: send `pr-papers-cross` desko branch out for PR!
|
||||
# papers = prev.papers.override {
|
||||
# cargo = crossCargo;
|
||||
# };
|
||||
|
||||
# 2025/07/27: upstreaming is blocked on gnome-session (itself blocked on gnome-shell)
|
||||
# phosh = prev.phosh.overrideAttrs (upstream: {
|
||||
@@ -561,11 +473,6 @@ in with final; {
|
||||
# ];
|
||||
# } prev.phosh-mobile-settings;
|
||||
|
||||
# 2025/07/27: upstreaming is unblocked
|
||||
pwvucontrol = prev.pwvucontrol.override {
|
||||
cargo = crossCargo;
|
||||
};
|
||||
|
||||
# pythonPackagesExtensions = prev.pythonPackagesExtensions ++ [
|
||||
# (pyself: pysuper: {
|
||||
# # 2025/07/23: upstreaming is unblocked, but solution is untested.
|
||||
@@ -728,16 +635,16 @@ in with final; {
|
||||
# # '';
|
||||
# });
|
||||
|
||||
# 2025/07/27: upstreaming is blocked on glycin-loaders
|
||||
snapshot = prev.snapshot.override {
|
||||
# fixes "error: linker `cc` not found"
|
||||
cargo = crossCargo;
|
||||
};
|
||||
# 2025/08/26: upstreaming is unblocked; implemented on desko `pr-snapshot-cross` branch
|
||||
# snapshot = prev.snapshot.override {
|
||||
# # fixes "error: linker `cc` not found"
|
||||
# cargo = crossCargo;
|
||||
# };
|
||||
|
||||
# 2025/07/27: upstreaming is unblocked
|
||||
spot = prev.spot.override {
|
||||
cargo = crossCargo;
|
||||
};
|
||||
# 2025/08/26: upstreaming is unblocked; patched on desko branch `pr-spot-cross`
|
||||
# spot = prev.spot.override {
|
||||
# cargo = crossCargo;
|
||||
# };
|
||||
|
||||
# 2025/07/27: upstreaming is unblocked
|
||||
# squeekboard = prev.squeekboard.overrideAttrs (upstream: {
|
||||
@@ -783,7 +690,7 @@ in with final; {
|
||||
# ];
|
||||
# });
|
||||
|
||||
# 2025/07/27: upstreaming blocked on gvfs -> udisks -> libblockdev -> {thin-provisioning-tools,libndctl -> ... -> ruby}
|
||||
# 2025/08/26: upstreaming blocked on gvfs -> udisks -> libblockdev -> {thin-provisioning-tools,libndctl -> ... -> ruby}
|
||||
swaynotificationcenter = mvToNativeInputs [ buildPackages.wayland-scanner ] prev.swaynotificationcenter;
|
||||
|
||||
# 2025/07/27: upstreaming is unblocked
|
||||
@@ -834,10 +741,10 @@ in with final; {
|
||||
# });
|
||||
# };
|
||||
|
||||
# 2025/05/01: upstreaming is unblocked
|
||||
video-trimmer = prev.video-trimmer.override {
|
||||
cargo = crossCargo;
|
||||
};
|
||||
# 2025/08/26: upstreaming is unblocked; implemented on desko branch `pr-video-trimmer-cross`
|
||||
# video-trimmer = prev.video-trimmer.override {
|
||||
# cargo = crossCargo;
|
||||
# };
|
||||
|
||||
# 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 {
|
||||
|
@@ -9,9 +9,11 @@
|
||||
libsoup_3,
|
||||
meson,
|
||||
ninja,
|
||||
nix-update-script,
|
||||
openssl,
|
||||
pkg-config,
|
||||
python3,
|
||||
rust,
|
||||
rustPlatform,
|
||||
rustc,
|
||||
stdenv,
|
||||
@@ -19,20 +21,21 @@
|
||||
wrapGAppsHook4,
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation {
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "envelope";
|
||||
version = "0.1.0-unstable-2024-09-13";
|
||||
version = "0.1.0-unstable-2025-05-17";
|
||||
|
||||
src = fetchFromGitLab {
|
||||
domain = "gitlab.gnome.org";
|
||||
owner = "felinira";
|
||||
repo = "envelope";
|
||||
rev = "11ce86da13793787a25e48ca23322b33fcf8bf34"; # last commit before libadwaita 1.6
|
||||
hash = "sha256-EX309RhisBx27TscMsibEvqCSCUSukTgf4Xs1Vws4YY=";
|
||||
rev = "e2a8a56aa9b68d82486b99790b86322715d2a6db";
|
||||
hash = "sha256-osVShCaKKoGhxWCjaYcMkOji8e0oETgDaDpCAfHauwQ=";
|
||||
};
|
||||
|
||||
cargoDeps = rustPlatform.importCargoLock {
|
||||
lockFile = ./Cargo.lock;
|
||||
cargoDeps = rustPlatform.fetchCargoVendor {
|
||||
inherit (finalAttrs) pname version src;
|
||||
hash = "sha256-8pK8cw9nYJmmybYRL+PUCK8FvUUPbyFp7oYYF461KPc=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
@@ -58,10 +61,21 @@ stdenv.mkDerivation {
|
||||
|
||||
postPatch = ''
|
||||
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; {
|
||||
description = "a mobile-first email client for the GNOME ecosystem";
|
||||
homepage = "https://gitlab.gnome.org/felinira/envelope/";
|
||||
@@ -70,4 +84,4 @@ stdenv.mkDerivation {
|
||||
platforms = platforms.linux;
|
||||
mainProgram = "envelope";
|
||||
};
|
||||
}
|
||||
})
|
||||
|
@@ -33,6 +33,12 @@ stdenv.mkDerivation rec {
|
||||
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 = [
|
||||
cargo
|
||||
desktop-file-utils
|
||||
@@ -49,6 +55,8 @@ stdenv.mkDerivation rec {
|
||||
openssl
|
||||
];
|
||||
|
||||
env.CARGO_BUILD_TARGET = stdenv.hostPlatform.rust.rustcTargetSpec;
|
||||
|
||||
passthru.updateScript = gitUpdater {
|
||||
rev-prefix = "v";
|
||||
};
|
||||
|
@@ -14,12 +14,12 @@
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "lpac";
|
||||
version = "2.2.1";
|
||||
version = "2.3.0";
|
||||
src = fetchFromGitHub {
|
||||
owner = "estkme-group";
|
||||
repo = "lpac";
|
||||
rev = "v${finalAttrs.version}";
|
||||
hash = "sha256-dxoYuX3dNj4piXQBqU4w1ICeyOGid35c+6ZITQiN6wA=";
|
||||
hash = "sha256-ALne5sHB6ff7cHAWe0rFwpP/Yz4EhZBiOrgdM2B8+OE=";
|
||||
};
|
||||
|
||||
# options:
|
||||
|
@@ -14,8 +14,8 @@
|
||||
mkNixpkgs ? import ./mkNixpkgs.nix {},
|
||||
}:
|
||||
mkNixpkgs {
|
||||
rev = "6207745fb2fb83330b7193fed31337050b075f40";
|
||||
sha256 = "sha256-NfKklCRVBW979loK3FIXjYYMO2oGfFx/ozfg37oWRcc=";
|
||||
version = "unstable-2025-08-15";
|
||||
rev = "9bd1c4b190d825cc25b3bacc0e612801837fc6c1";
|
||||
sha256 = "sha256-DjOO5XuELbVjN1xB+aQx4r/X8QXJ4ausEBSZUKjzUl8=";
|
||||
version = "unstable-2025-08-28";
|
||||
branch = "master";
|
||||
}
|
||||
|
@@ -45,51 +45,68 @@ in
|
||||
|
||||
# TODO: enable, once i can tolerate a mass rebuild
|
||||
# (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";
|
||||
# prUrl = "https://github.com/NixOS/nixpkgs/pull/429225";
|
||||
# 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' {
|
||||
name = "signal-desktop: fix cross compilation";
|
||||
prUrl = "https://github.com/NixOS/nixpkgs/pull/423089";
|
||||
# hash = "sha256-609snDT1Ru69ZTWfzu4PnhY0pj3xghPr8w880j7JZ5k=";
|
||||
hash = "sha256-bVMOanUcYNPf2JbaWS9ga+0jAwuZQSfMKlwtNRp9tYU=";
|
||||
hash = "sha256-4VEKjZsI7XW+/gbq3fn3bjjciPKtd2IU8SH4CsqqJ6Y=";
|
||||
})
|
||||
|
||||
(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-spot-cross`
|
||||
name = "spot: fix cross compilation";
|
||||
prUrl = "https://github.com/NixOS/nixpkgs/pull/437722";
|
||||
# saneCommit = "09558b2d4b0e5fb74fc5c40b4c6cb0b7e72f7d00";
|
||||
hash = "sha256-yiWUOMaq9g+5WTQYKo1DG9m3my1oWot4miULfvCzWI4=";
|
||||
})
|
||||
|
||||
(fetchpatch' {
|
||||
# desko nixpkgs branch: `pr-video-trimmer-cross`
|
||||
name = "video-trimmer: fix cross compilation";
|
||||
prUrl = "https://github.com/NixOS/nixpkgs/pull/437707";
|
||||
# saneCommit = "6809ffd293ec65ef44deae7b6436afdcc4a36efb";
|
||||
hash = "sha256-YBjzts0XmJ/szrNzmGm4Pp0EjPt37DXZwmP/ycG8M+k=";
|
||||
})
|
||||
|
||||
(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' {
|
||||
|
@@ -2,8 +2,8 @@
|
||||
mkNixpkgs ? import ./mkNixpkgs.nix {},
|
||||
}:
|
||||
mkNixpkgs {
|
||||
rev = "c0e9e1afcfdb5fcd0ae7466a20a9c1ced45ce8a1";
|
||||
sha256 = "sha256-njAuNOzJKhK4lAuabibqWqsziLZVCMQJmDZRm5MYbbQ=";
|
||||
version = "unstable-2025-08-15";
|
||||
rev = "31e6171f4eaf4ace50a742afaee052a6d646ca09";
|
||||
sha256 = "sha256-R3YOPbE2ipa7vCnUJqKtWe54/LYq+hC1hDJHCnHMEkg=";
|
||||
version = "unstable-2025-08-28";
|
||||
branch = "staging-next";
|
||||
}
|
||||
|
@@ -2,8 +2,8 @@
|
||||
mkNixpkgs ? import ./mkNixpkgs.nix {},
|
||||
}:
|
||||
mkNixpkgs {
|
||||
rev = "664c1d7072fbafa4c806ac6b22f9a6eee221cfcf";
|
||||
sha256 = "sha256-Y7DnNNQLKLdQwIwAEyGQPPcqDDLiCZcuJnQ9f/mWigM=";
|
||||
version = "unstable-2025-08-15";
|
||||
rev = "b4d7d83861f69b7c8bb73a5d289c4463033ba1a1";
|
||||
sha256 = "sha256-D//FMt4yjbo/2VptV9tU5l13Ni/CQ2SJp34Bf0DGRXM=";
|
||||
version = "unstable-2025-08-27";
|
||||
branch = "staging";
|
||||
}
|
||||
|
@@ -7,8 +7,8 @@ let
|
||||
src = fetchFromGitHub {
|
||||
owner = "nix-community";
|
||||
repo = "nixpkgs-wayland";
|
||||
rev = "9c452b9ea8e584d5085629e2b76703c94df64b6f";
|
||||
hash = "sha256-THPRayZls0/4rZSw4R5B7evCbGVr5AN3SQQZSgYpIiA=";
|
||||
rev = "9d72e7fb798cc10d895ccdaecb3f389642da7f95";
|
||||
hash = "sha256-RrsHuCKuDiNIFNqGwTulMCwYu2osu/zFvVZHCxiTuUI=";
|
||||
};
|
||||
flake = import "${src}/flake.nix";
|
||||
evaluated = flake.outputs {
|
||||
@@ -25,7 +25,7 @@ let
|
||||
in src.overrideAttrs (base: {
|
||||
# attributes required by update scripts
|
||||
pname = "nixpkgs-wayland";
|
||||
version = "0-unstable-2025-08-14";
|
||||
version = "0-unstable-2025-08-28";
|
||||
src = src;
|
||||
|
||||
# passthru only nixpkgs-wayland's own packages -- not the whole nixpkgs-with-nixpkgs-wayland-as-overlay:
|
||||
|
@@ -14,13 +14,13 @@
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "syshud";
|
||||
version = "0-unstable-2025-07-26";
|
||||
version = "0-unstable-2025-08-18";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "System64fumo";
|
||||
repo = "syshud";
|
||||
rev = "d954c124280b71f80930046a11e390a814c1b229";
|
||||
hash = "sha256-FUPnIUl9x0eZmhls4CmPGg4kZb1MNmKU5BKecFDQdHM=";
|
||||
rev = "6dbf17bb953342c844517d1b4eb672cbae7a1566";
|
||||
hash = "sha256-T9tWmgDIcmmRXAeWR7Pfjalkl6xogtuz1qfsSAuQmkg=";
|
||||
};
|
||||
|
||||
postPatch = ''
|
||||
|
@@ -6,12 +6,12 @@
|
||||
}:
|
||||
stdenvNoCC.mkDerivation {
|
||||
pname = "uassets";
|
||||
version = "0-unstable-2025-08-15";
|
||||
version = "0-unstable-2025-08-28";
|
||||
src = fetchFromGitHub {
|
||||
owner = "uBlockOrigin";
|
||||
repo = "uAssets";
|
||||
rev = "e1dd6d5aa73d9dc6d7a123ef585ba5d082bb6fa8";
|
||||
hash = "sha256-rGZWU2OXWjyweyWjST8CgpriEUB1Sa2wd3/FJ1cVMlw=";
|
||||
rev = "844b2b3d873044486ffbe4022934e797f30e560b";
|
||||
hash = "sha256-8yUuhFZNg/cn8i3n/6qmjqScKIcpoM8yMNEMQisRJXQ=";
|
||||
};
|
||||
|
||||
dontBuild = true;
|
||||
|
@@ -7,12 +7,12 @@
|
||||
}:
|
||||
buildDotnetModule rec {
|
||||
pname = "UVtools";
|
||||
version = "5.1.7";
|
||||
version = "5.2.0";
|
||||
src = fetchFromGitHub {
|
||||
owner = "sn4k3";
|
||||
repo = "UVtools";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-+3E8Ts+rv72Jq4jLcmyU3KUP7U0k6Ruo5+Dn0hdj+Yg=";
|
||||
hash = "sha256-4o+F56E80GElRb4DfmOv6mqwQ8+23E0aj/RjGr7Pg8U=";
|
||||
};
|
||||
|
||||
nugetDeps = ./deps.json;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{ mkVersionedHttpZim }: mkVersionedHttpZim {
|
||||
owner = "other";
|
||||
pname = "alpinelinux_en_all_maxi";
|
||||
version = "2025-07";
|
||||
hash = "sha256-B99/UhqhKsVqphXRuRFDTD4eIY6/MqkO0pfNKGadbsg=";
|
||||
version = "2025-08";
|
||||
hash = "sha256-/MW3BAvEnsWfIZawkRq8qKhaLzPivAByWE9qIEPP4wo=";
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{ mkVersionedHttpZim }: mkVersionedHttpZim {
|
||||
owner = "other";
|
||||
pname = "archlinux_en_all_maxi";
|
||||
version = "2025-07";
|
||||
hash = "sha256-Hz2KpptYh0j5f88AyIpy0JaT+qhAegZHOCdaIz22NHo=";
|
||||
version = "2025-08";
|
||||
hash = "sha256-++r0i57yLDEwVFj0fQm96zSW4kRgbtUkyq86c+Lz2FQ=";
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{ mkVersionedHttpZim }: mkVersionedHttpZim {
|
||||
owner = "wikipedia";
|
||||
pname = "wikipedia_en_all_maxi";
|
||||
version = "2024-01";
|
||||
hash = "sha256-GrRFV3TSFhm9fCFxhFOSD3EQnzBAPZJh96NPefh6p4Q=";
|
||||
version = "2025-08";
|
||||
hash = "sha256-OqVTmcWvputcJHcZTg0CLAUnYWQIvGRMIiTtMo2mLfs=";
|
||||
}
|
||||
|
@@ -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": {
|
||||
"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"
|
||||
}
|
||||
],
|
||||
"lastmodified": "2025-08-09T16:48:48Z",
|
||||
"mac": "ENC[AES256_GCM,data:lctLfwra+yCkgVyke4l3L5fqDQu6VTMspG48l54lOLYYEQGGYw/V+HDI6GdKVywvGfnthzf8C9LSTRJrD3gKv/Q9a4piaTCTabZ43s0rk5jRCRuUgW7dJqH2nYqZ4AZB2C3DqQn4tCUoRW0PQsZTv+jIwu+jethbn/mb81j2kGc=,iv:WgflsIi5zPGl6bn6A7W2Dvi3XMzck/LNsz/nKV1mLAk=,tag:+sn6kLAiiuXD9wk52VS0KQ==,type:str]",
|
||||
"lastmodified": "2025-08-20T17:31:03Z",
|
||||
"mac": "ENC[AES256_GCM,data:U86dC8cNZWILAGf/0WA/JOCq+pCIoKSzsUKgW89hNQJe0sUDgRPo23uvwWa6C/2YuSlP5Jv5ofp0hO6a39dJ83iQibyOIrf0VArRRy8whu1kn/bwIhWxWL7mF6WhKgKmPLy8BX2h0zAp6EL+ct9JdYPb2gdoXrfl0f0R0BDUnL8=,iv:80e1zdyRaPPeDSvfejFd/LjusL6aoKb9F/VTp46l0Kc=,tag:jMHHxG3Ycy5fr74BQnaBEg==,type:str]",
|
||||
"unencrypted_suffix": "_unencrypted",
|
||||
"version": "3.10.2"
|
||||
}
|
||||
|
Reference in New Issue
Block a user