Compare commits
154 Commits
staging/dn
...
staging/ni
Author | SHA1 | Date | |
---|---|---|---|
c29dd4094b | |||
049ded2a0d | |||
4854b8b409 | |||
55e90f531b | |||
3a6bb5a787 | |||
aae5e40e92 | |||
5d464b3c64 | |||
9b389416cd | |||
bd57bb7934 | |||
db2d4ca78e | |||
3812d935a7 | |||
bc993d1139 | |||
ec62b5f664 | |||
71e96fff18 | |||
33eaa00957 | |||
a5af1e0893 | |||
be21ac57f8 | |||
63a773d8a9 | |||
505fcf5111 | |||
f0e76ef11f | |||
cb721ac70e | |||
aae783876b | |||
5e3a8cf702 | |||
d9b9349572 | |||
b6b0e65ef6 | |||
a723d1274b | |||
d41ad9db01 | |||
d6720f3601 | |||
0b0d453916 | |||
59adddafc7 | |||
50fa70ca56 | |||
86855b0c40 | |||
931838fb0d | |||
ec3a7067b6 | |||
8cb236b0a9 | |||
5f47372f6a | |||
afe27fd9cb | |||
e8265807a9 | |||
85ecaf64e9 | |||
33b33a9237 | |||
fecd2fa7d3 | |||
74ec65c8a9 | |||
21a060d856 | |||
6249f7553c | |||
96c976a3b0 | |||
d48d3a979f | |||
ab8ee51321 | |||
74891fb2f0 | |||
f62bd83eb8 | |||
c977665214 | |||
b3a605c76b | |||
2cbd44b2b3 | |||
689c63a905 | |||
ed2480f48c | |||
7aad3a62ba | |||
1583b213f1 | |||
db851d960c | |||
fb7cb091e3 | |||
048dbc5809 | |||
bb1a2c9dcb | |||
86c8fe1466 | |||
95f6fd7082 | |||
5fb52ba38e | |||
4f8d0023ef | |||
280c4aa2e8 | |||
fd270dd0b8 | |||
8e17e2beb2 | |||
d68704474d | |||
0fa5b5bf52 | |||
9caa2a0a17 | |||
023e28fb03 | |||
bed33fae60 | |||
3b958ba356 | |||
adb6ff4c66 | |||
931c76c2e7 | |||
d95042ab65 | |||
0605094461 | |||
4eb6c1fd7d | |||
c553e74cd6 | |||
4eb6f59b01 | |||
9f55a8288d | |||
feb299eb22 | |||
b21c79a0b4 | |||
c819bc2d95 | |||
21006e52dc | |||
5562d60cbb | |||
17041384e9 | |||
9eb36441e1 | |||
0d0a9fce6a | |||
847e618dee | |||
c4e345e2e7 | |||
c75719e751 | |||
7a57cf5327 | |||
b81642ccc9 | |||
57ca3e67b3 | |||
bcca6b6096 | |||
79772d4e3d | |||
339c0a47ab | |||
b1be78529b | |||
cce53b968b | |||
1d55b98cd1 | |||
e9d45c3b31 | |||
32dde42ee2 | |||
b60986cfb8 | |||
60ef232bc0 | |||
7f7bc33be5 | |||
f52f56a34c | |||
425de71583 | |||
0bd87077c1 | |||
601bf567eb | |||
4f74078423 | |||
f170351de7 | |||
bee9dab513 | |||
16c3d4289e | |||
21e0c0d00f | |||
fdf85156bc | |||
79a7daca12 | |||
3996e1be08 | |||
8b1dbd42da | |||
a2c7edf340 | |||
9b365d1771 | |||
8cf3402be4 | |||
a92fa489cb | |||
837f20e892 | |||
3d56117d65 | |||
1724ac60e5 | |||
bf168c7f0f | |||
37cafcf610 | |||
27d2f756d2 | |||
3ab33956e4 | |||
0b71712208 | |||
f31619d9e9 | |||
61838a589f | |||
c10c887650 | |||
6df61525a1 | |||
e5ce7c02ef | |||
88e5efd1f3 | |||
e9200ffcdf | |||
ab78a36354 | |||
c92f216a5b | |||
eacd3c88d1 | |||
487fbf2236 | |||
97f93e8ec0 | |||
e1eac4ae46 | |||
44d0b4efd4 | |||
9ab85167c3 | |||
9730659f32 | |||
b45981e870 | |||
95c9b5d6a2 | |||
05f10f0115 | |||
86b15d381f | |||
ecaab07bce | |||
4fd4efa22f | |||
527585e7eb |
19
TODO.md
19
TODO.md
@@ -1,4 +1,5 @@
|
||||
## BUGS
|
||||
- fix NUR evaluation
|
||||
- why i need to manually restart `wireguard-wg-ovpns` on servo periodically
|
||||
- else DNS fails
|
||||
|
||||
@@ -19,7 +20,8 @@
|
||||
- add updateScripts to all my packages in nixpkgs
|
||||
- fix lightdm-mobile-greeter for newer libhandy
|
||||
- port zecwallet-lite to a from-source build
|
||||
- fix or abandon Whalebird
|
||||
- REVIEW/integrate jellyfin dataDir config: <https://github.com/NixOS/nixpkgs/pull/233617>
|
||||
- remove `libsForQt5.callPackage` broadly: <https://github.com/NixOS/nixpkgs/issues/180841>
|
||||
|
||||
|
||||
## IMPROVEMENTS:
|
||||
@@ -40,19 +42,18 @@
|
||||
- allows (maybe) to cache media for offline use
|
||||
- "newer" jellyfin client
|
||||
- not packaged for nix
|
||||
- find a nice desktop ActivityPub client
|
||||
- moby/sxmo: display numerical vol percentage in topbar
|
||||
- package Nix/NixOS docs for Zeal
|
||||
- install [doc-browser](https://github.com/qwfy/doc-browser)
|
||||
- this supports both dash (zeal) *and* the datasets from <https://devdocs.io> (which includes nix!)
|
||||
- install [devhelp](https://wiki.gnome.org/Apps/Devhelp) (gnome)
|
||||
- auto-mount servo
|
||||
- have xdg-open parse `<repo:...> URIs (or adjust them so that it _can_ parse)
|
||||
- `sane.programs`: auto-populate defaults with everything from `pkgs`
|
||||
- `sane.persist`: auto-create parent dirs in ~/private
|
||||
- currently if the application doesn't autocreate dirs leading to its destination, then ~/private storage fails
|
||||
- this might be why librewolf on mobile is still amnesiac
|
||||
- zsh: disable "command not found" corrections
|
||||
- sxmo: allow rotation to the upside-down position
|
||||
- see: <repo:mil/sxmo-utils:scripts/core/sxmo_autorotate.sh>
|
||||
- all orientations *except* upside down are supported
|
||||
- sxmo: launch with auto-rotation enabled
|
||||
- sane-bt-search: show details like 5.1 vs stereo, h264 vs h265
|
||||
|
||||
### perf
|
||||
- why does nixos-rebuild switch take 5 minutes when net is flakey?
|
||||
@@ -63,13 +64,13 @@
|
||||
- these use significant /tmp space.
|
||||
- either place /tmp on encrypted-cleared-at-boot storage
|
||||
- which probably causes each CPU load for the encryption
|
||||
- or have nix builds use a subdir of /tmp like /tmp/nix/...
|
||||
- and place that on non-encrypted clear-on-boot (with very lax writeback/swappiness to minimize writes)
|
||||
- **or set up encrypted swap**
|
||||
- encrypted swap could remove the need for my encrypted-cleared-at-boot stuff
|
||||
|
||||
|
||||
## NEW FEATURES:
|
||||
- add a FTP-accessible file share to servo
|
||||
- just /var/www?
|
||||
- migrate MAME cabinet to nix
|
||||
- boot it from PXE from servo?
|
||||
- enable IPv6
|
||||
|
34
flake.lock
generated
34
flake.lock
generated
@@ -36,11 +36,11 @@
|
||||
"nixpkgs": "nixpkgs"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1684319086,
|
||||
"narHash": "sha256-5wwlkWqP1cQUPXp/PJsi09FkgAule5yBghngRZZbUQg=",
|
||||
"lastModified": 1687251388,
|
||||
"narHash": "sha256-E9cVlgeCvzPbA/G3mCDCzz8TdRwXyGYzIjmwcvIfghg=",
|
||||
"owner": "edolstra",
|
||||
"repo": "nix-serve",
|
||||
"rev": "e6e3d09438e803daa5374ad8edf1271289348456",
|
||||
"rev": "d6df5bd8584f37e22cff627db2fc4058a4aab5ee",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -66,27 +66,27 @@
|
||||
},
|
||||
"nixpkgs-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1684632198,
|
||||
"narHash": "sha256-SdxMPd0WmU9MnDBuuy7ouR++GftrThmSGL7PCQj/uVI=",
|
||||
"lastModified": 1687031877,
|
||||
"narHash": "sha256-yMFcVeI+kZ6KD2QBrFPNsvBrLq2Gt//D0baHByMrjFY=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "d0dade110dc7072d67ce27826cfe9ab2ab0cf247",
|
||||
"rev": "e2e2059d19668dab1744301b8b0e821e3aae9c99",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "release-22.11",
|
||||
"ref": "release-23.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-unpatched": {
|
||||
"locked": {
|
||||
"lastModified": 1684935479,
|
||||
"narHash": "sha256-6QMMsXMr2nhmOPHdti2j3KRHt+bai2zw+LJfdCl97Mk=",
|
||||
"lastModified": 1687502512,
|
||||
"narHash": "sha256-dBL/01TayOSZYxtY4cMXuNCBk8UMLoqRZA+94xiFpJA=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "f91ee3065de91a3531329a674a45ddcb3467a650",
|
||||
"rev": "3ae20aa58a6c0d1ca95c9b11f59a2d12eebc511f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -113,11 +113,11 @@
|
||||
"nixpkgs-stable": "nixpkgs-stable"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1684637723,
|
||||
"narHash": "sha256-0vAxL7MVMhGbTkAyvzLvleELHjVsaS43p+PR1h9gzNQ=",
|
||||
"lastModified": 1687398569,
|
||||
"narHash": "sha256-e/umuIKFcFtZtWeX369Hbdt9r+GQ48moDmlTcyHWL28=",
|
||||
"owner": "Mic92",
|
||||
"repo": "sops-nix",
|
||||
"rev": "4ccdfb573f323a108a44c13bb7730e42baf962a9",
|
||||
"rev": "2ff6973350682f8d16371f8c071a304b8067f192",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -134,11 +134,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1684528780,
|
||||
"narHash": "sha256-QdYxjcTCCLPv++1v9tJBL98nn/AFx0fmzlgzcLK6KRE=",
|
||||
"lastModified": 1686876043,
|
||||
"narHash": "sha256-71SNPU2aeeJx29JSeW4JCJb8HXAuZRvL7sbh+c3wgkk=",
|
||||
"ref": "refs/heads/master",
|
||||
"rev": "f3747a1dad3d34880613821faf26357ba432d3d7",
|
||||
"revCount": 194,
|
||||
"rev": "0e0aa12aca143639f158b3a5c0c00349fcc2166c",
|
||||
"revCount": 199,
|
||||
"type": "git",
|
||||
"url": "https://git.uninsane.org/colin/uninsane"
|
||||
},
|
||||
|
@@ -252,7 +252,7 @@
|
||||
deployScript = action: pkgs.writeShellScript "deploy-moby" ''
|
||||
nixos-rebuild --flake '.#moby' build $@
|
||||
sudo nix sign-paths -r -k /run/secrets/nix_serve_privkey $(readlink ./result)
|
||||
nixos-rebuild --flake '.#moby' ${action} --target-host colin@moby-hn --use-remote-sudo $@
|
||||
nixos-rebuild --flake '.#moby' ${action} --target-host colin@moby --use-remote-sudo $@
|
||||
'';
|
||||
in {
|
||||
update-feeds = {
|
||||
|
@@ -19,6 +19,7 @@
|
||||
sane.programs.iphoneUtils.enableFor.user.colin = true;
|
||||
|
||||
sane.programs.guiApps.suggestedPrograms = [ "desktopGuiApps" ];
|
||||
sane.programs.consoleUtils.suggestedPrograms = [ "consoleMediaUtils" ];
|
||||
|
||||
boot.loader.efi.canTouchEfiVariables = false;
|
||||
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
||||
|
@@ -19,6 +19,7 @@
|
||||
"desktopGuiApps"
|
||||
"stepmania"
|
||||
];
|
||||
sane.programs.consoleUtils.suggestedPrograms = [ "consoleMediaUtils" ];
|
||||
|
||||
sops.secrets.colin-passwd.neededForUsers = true;
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# doesn't actually *enable* anything,
|
||||
# but sets up any modules such that if they *were* enabled, they'll act as expected.
|
||||
{ ... }:
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
sane.gui.sxmo = {
|
||||
greeter = "sway";
|
||||
@@ -28,5 +28,11 @@
|
||||
# see <repo:mil/sxmo-utils:scripts/deviceprofiles>
|
||||
# SXMO_DEVICE_NAME = "pine64,pinephone-1.2";
|
||||
};
|
||||
package = pkgs.sxmo-utils.overrideAttrs (base: {
|
||||
postPatch = (base.postPatch or "") + ''
|
||||
# after volume-button navigation mode, restore full keyboard functionality
|
||||
cp ${./xkb_mobile_normal_buttons} ./configs/xkb/xkb_mobile_normal_buttons
|
||||
'';
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@@ -33,11 +33,16 @@
|
||||
".config/pulse" # persist pulseaudio volume
|
||||
];
|
||||
|
||||
sane.gui.phosh.enable = true;
|
||||
sane.gui.sxmo.enable = true;
|
||||
# sane.programs.consoleUtils.enableFor.user.colin = false;
|
||||
# sane.programs.guiApps.enableFor.user.colin = false;
|
||||
sane.programs.sequoia.enableFor.user.colin = false;
|
||||
sane.programs.tuiApps.enableFor.user.colin = false; # visidata, others, don't compile well
|
||||
# disabled for faster deploys (gthumb depends on webkitgtk, particularly)
|
||||
sane.programs.soundconverter.enableFor.user.colin = false;
|
||||
sane.programs.gthumb.enableFor.user.colin = false;
|
||||
sane.programs.jellyfin-media-player.enableFor.user.colin = false;
|
||||
# sane.programs.mpv.enableFor.user.colin = true;
|
||||
|
||||
boot.loader.efi.canTouchEfiVariables = false;
|
||||
# /boot space is at a premium. default was 20.
|
||||
|
@@ -1,23 +1,25 @@
|
||||
{ sane-lib, ... }:
|
||||
{ pkgs, sane-lib, ... }:
|
||||
{
|
||||
sane.gui.sxmo = {
|
||||
settings = {
|
||||
# touch screen
|
||||
SXMO_LISGD_INPUT_DEVICE = "/dev/input/by-path/platform-1c2ac00.i2c-event";
|
||||
# vol and power are detected correctly by upstream
|
||||
|
||||
# preferences
|
||||
# N.B. some deviceprofiles explicitly set SXMO_SWAY_SCALE, overwriting what we put here.
|
||||
SXMO_SWAY_SCALE = "1.5";
|
||||
SXMO_ROTATION_GRAVITY = "12800";
|
||||
DEFAULT_COUNTRY = "US";
|
||||
BROWSWER = "librewolf";
|
||||
};
|
||||
package = pkgs.sxmo-utils.overrideAttrs (base: {
|
||||
postPatch = (base.postPatch or "") + ''
|
||||
cat <<EOF >> ./configs/default_hooks/sxmo_hook_start.sh
|
||||
# rotate UI based on physical display angle by default
|
||||
sxmo_daemons.sh start autorotate sxmo_autorotate.sh
|
||||
EOF
|
||||
'';
|
||||
});
|
||||
};
|
||||
# TODO: only populate this if sxmo is enabled?
|
||||
sane.user.fs.".config/sxmo/profile" = sane-lib.fs.wantedText ''
|
||||
# sourced by sxmo_init.sh
|
||||
. sxmo_common.sh
|
||||
|
||||
export SXMO_SWAY_SCALE=1.5
|
||||
export SXMO_ROTATION_GRAVITY=12800
|
||||
|
||||
export DEFAULT_COUNTRY=US
|
||||
export BROWSER=librewolf
|
||||
|
||||
export SXMO_BG_IMG="$(xdg_data_path sxmo/background.jpg)"
|
||||
'';
|
||||
}
|
||||
|
@@ -30,5 +30,5 @@ lib.mkIf false
|
||||
proxyPass = "http://${ip}:${builtins.toString port}";
|
||||
};
|
||||
};
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."calibre" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."calibre" = "native";
|
||||
}
|
||||
|
@@ -7,6 +7,7 @@
|
||||
./email
|
||||
./ejabberd.nix
|
||||
./freshrss.nix
|
||||
./ftp
|
||||
./gitea.nix
|
||||
./goaccess.nix
|
||||
./ipfs.nix
|
||||
@@ -17,6 +18,7 @@
|
||||
./lemmy.nix
|
||||
./matrix
|
||||
./navidrome.nix
|
||||
./nfs.nix
|
||||
./nixserve.nix
|
||||
./nginx.nix
|
||||
./pict-rs.nix
|
||||
|
@@ -115,7 +115,7 @@
|
||||
useACMEHost = "uninsane.org";
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet = {
|
||||
sane.dns.zones."uninsane.org".inet = {
|
||||
# XXX: SRV records have to point to something with a A/AAAA record; no CNAMEs
|
||||
A."xmpp" = "%ANATIVE%";
|
||||
CNAME."muc.xmpp" = "xmpp";
|
||||
|
@@ -24,7 +24,7 @@
|
||||
enableACME = true;
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet = {
|
||||
sane.dns.zones."uninsane.org".inet = {
|
||||
CNAME."imap" = "native";
|
||||
};
|
||||
|
||||
|
@@ -50,7 +50,7 @@ in
|
||||
};
|
||||
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet = {
|
||||
sane.dns.zones."uninsane.org".inet = {
|
||||
MX."@" = "10 mx.uninsane.org.";
|
||||
# XXX: RFC's specify that the MX record CANNOT BE A CNAME
|
||||
A."mx" = "185.157.162.178";
|
||||
|
@@ -59,5 +59,5 @@
|
||||
# the routing is handled by services.freshrss.virtualHost
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."rss" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."rss" = "native";
|
||||
}
|
||||
|
70
hosts/by-name/servo/services/ftp/default.nix
Normal file
70
hosts/by-name/servo/services/ftp/default.nix
Normal file
@@ -0,0 +1,70 @@
|
||||
# docs:
|
||||
# - <https://github.com/drakkan/sftpgo>
|
||||
# - config options: <https://github.com/drakkan/sftpgo/blob/main/docs/full-configuration.md>
|
||||
# - config defaults: <https://github.com/drakkan/sftpgo/blob/main/sftpgo.json>
|
||||
# - nixos options: <repo:nixos/nixpkgs:nixos/modules/services/web-apps/sftpgo.nix>
|
||||
#
|
||||
# sftpgo is a FTP server that also supports WebDAV, SFTP, and web clients.
|
||||
|
||||
|
||||
{ lib, pkgs, sane-lib, ... }:
|
||||
let
|
||||
authProgram = pkgs.static-nix-shell.mkBash {
|
||||
pname = "sftpgo_external_auth_hook";
|
||||
src = ./.;
|
||||
};
|
||||
in
|
||||
{
|
||||
# Client initiates a FTP "control connection" on port 21.
|
||||
# - this handles the client -> server commands, and the server -> client status, but not the actual data
|
||||
# - file data, directory listings, etc need to be transferred on an ephemeral "data port".
|
||||
# - 50000-50100 is a common port range for this.
|
||||
sane.ports.ports = {
|
||||
"21" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
description = "colin-FTP server";
|
||||
};
|
||||
} // (sane-lib.mapToAttrs
|
||||
(port: {
|
||||
name = builtins.toString port;
|
||||
value = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
description = "colin-FTP server data port range";
|
||||
};
|
||||
})
|
||||
(lib.range 50000 50100)
|
||||
);
|
||||
|
||||
services.sftpgo = {
|
||||
enable = true;
|
||||
settings = {
|
||||
ftpd = {
|
||||
bindings = [{
|
||||
address = "10.0.10.5";
|
||||
port = 21;
|
||||
debug = true;
|
||||
}];
|
||||
|
||||
# active mode is susceptible to "bounce attacks", without much benefit over passive mode
|
||||
disable_active_mode = true;
|
||||
hash_support = true;
|
||||
passive_port_range = {
|
||||
start = 50000;
|
||||
end = 50100;
|
||||
};
|
||||
|
||||
banner = ''
|
||||
Welcome, friends, to Colin's read-only FTP server! Also available via NFS on the same host.
|
||||
Please let me know if anything's broken or not as it should be. Otherwise, browse and DL freely :)
|
||||
'';
|
||||
|
||||
};
|
||||
data_provider = {
|
||||
driver = "memory";
|
||||
external_auth_hook = "${authProgram}/bin/sftpgo_external_auth_hook";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
55
hosts/by-name/servo/services/ftp/sftpgo_external_auth_hook
Executable file
55
hosts/by-name/servo/services/ftp/sftpgo_external_auth_hook
Executable file
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash
|
||||
# vim: set filetype=bash :
|
||||
#
|
||||
# available environment variables:
|
||||
# - SFTPGO_AUTHD_USERNAME
|
||||
# - SFTPGO_AUTHD_USER
|
||||
# - SFTPGO_AUTHD_IP
|
||||
# - SFTPGO_AUTHD_PROTOCOL = { "DAV", "FTP", "HTTP", "SSH" }
|
||||
# - SFTPGO_AUTHD_PASSWORD
|
||||
# - SFTPGO_AUTHD_PUBLIC_KEY
|
||||
# - SFTPGO_AUTHD_KEYBOARD_INTERACTIVE
|
||||
# - SFTPGO_AUTHD_TLS_CERT
|
||||
#
|
||||
# user permissions:
|
||||
# - see <repo:drakkan/sftpgo:internal/dataprovider/user.go>
|
||||
# - "*" = grant all permissions
|
||||
# - read-only perms:
|
||||
# - "list" = list files and directories
|
||||
# - "download"
|
||||
# - rw perms:
|
||||
# - "upload"
|
||||
# - "overwrite" = allow uploads to replace existing files
|
||||
# - "delete" = delete files and directories
|
||||
# - "delete_files"
|
||||
# - "delete_dirs"
|
||||
# - "rename" = rename files and directories
|
||||
# - "rename_files"
|
||||
# - "rename_dirs"
|
||||
# - "create_dirs"
|
||||
# - "create_symlinks"
|
||||
# - "chmod"
|
||||
# - "chown"
|
||||
# - "chtimes" = change atime/mtime (access and modification times)
|
||||
#
|
||||
# home_dir:
|
||||
# - it seems (empirically) that a user can't cd above their home directory.
|
||||
# though i don't have a reference for that in the docs.
|
||||
# TODO: don't reuse /var/nfs/export here. formalize this some other way.
|
||||
|
||||
|
||||
if [ "$SFTPGO_AUTHD_USERNAME" = "anonymous" ]; then
|
||||
echo '{'
|
||||
echo ' "status":1,'
|
||||
echo ' "username":"anonymous","expiration_date":0,'
|
||||
echo ' "home_dir":"/var/nfs/export","uid":65534,"gid":65534,"max_sessions":0,"quota_size":0,"quota_files":100000,'
|
||||
echo ' "permissions":{'
|
||||
echo ' "/":["list", "download"]'
|
||||
echo ' },'
|
||||
echo ' "upload_bandwidth":0,"download_bandwidth":0,'
|
||||
echo ' "filters":{"allowed_ip":[],"denied_ip":[]},"public_keys":[]'
|
||||
echo '}'
|
||||
else
|
||||
echo '{"username":""}'
|
||||
fi
|
@@ -98,7 +98,7 @@
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."git" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."git" = "native";
|
||||
|
||||
sane.ports.ports."22" = {
|
||||
protocol = [ "tcp" ];
|
||||
|
@@ -64,5 +64,5 @@
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."sink" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."sink" = "native";
|
||||
}
|
||||
|
@@ -34,7 +34,7 @@ lib.mkIf false # i don't actively use ipfs anymore
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."ipfs" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."ipfs" = "native";
|
||||
|
||||
# services.ipfs.enable = true;
|
||||
services.kubo.localDiscovery = true;
|
||||
|
@@ -24,9 +24,10 @@
|
||||
locations."/" = {
|
||||
# proxyPass = "http://ovpns.uninsane.org:9117";
|
||||
proxyPass = "http://10.0.1.6:9117";
|
||||
recommendedProxySettings = true;
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."jackett" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."jackett" = "native";
|
||||
}
|
||||
|
||||
|
@@ -121,7 +121,7 @@
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."jelly" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."jelly" = "native";
|
||||
|
||||
services.jellyfin.enable = true;
|
||||
}
|
||||
|
@@ -13,5 +13,5 @@
|
||||
locations."/".proxyPass = "http://127.0.0.1:8013";
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."w" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."w" = "native";
|
||||
}
|
||||
|
@@ -18,5 +18,5 @@ in
|
||||
proxyPass = "http://127.0.0.1:${builtins.toString port}";
|
||||
};
|
||||
};
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."komga" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."komga" = "native";
|
||||
}
|
||||
|
@@ -14,8 +14,8 @@ in {
|
||||
services.lemmy = {
|
||||
enable = true;
|
||||
settings.hostname = "lemmy.uninsane.org";
|
||||
settings.federation.enabled = true;
|
||||
# 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;
|
||||
@@ -32,6 +32,7 @@ in {
|
||||
systemd.services.lemmy.environment = {
|
||||
RUST_BACKTRACE = "full";
|
||||
# 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:
|
||||
@@ -54,5 +55,5 @@ in {
|
||||
enableACME = true;
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."lemmy" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."lemmy" = "native";
|
||||
}
|
||||
|
@@ -132,7 +132,7 @@
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet = {
|
||||
sane.dns.zones."uninsane.org".inet = {
|
||||
CNAME."matrix" = "native";
|
||||
CNAME."web.matrix" = "native";
|
||||
};
|
||||
|
@@ -108,6 +108,12 @@ in
|
||||
{ user = "matrix-appservice-irc"; group = "matrix-appservice-irc"; directory = "/var/lib/matrix-appservice-irc"; }
|
||||
];
|
||||
|
||||
# XXX: matrix-appservice-irc PreStart tries to chgrp the registration.yml to matrix-synapse,
|
||||
# which requires matrix-appservice-irc to be of that group
|
||||
users.users.matrix-appservice-irc.extraGroups = [ "matrix-synapse" ];
|
||||
# weird race conditions around registration.yml mean we want matrix-synapse to be of matrix-appservice-irc group too.
|
||||
users.users.matrix-synapse.extraGroups = [ "matrix-appservice-irc" ];
|
||||
|
||||
services.matrix-synapse.settings.app_service_config_files = [
|
||||
"/var/lib/matrix-appservice-irc/registration.yml" # auto-created by irc appservice
|
||||
];
|
||||
@@ -153,4 +159,10 @@ in
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.matrix-appservice-irc.serviceConfig = {
|
||||
# XXX 2023/06/20: nixos specifies this + @aio and @memlock as forbidden
|
||||
# the service actively uses at least one of these, and both of them are fairly innocuous
|
||||
SystemCallFilter = lib.mkForce "~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @setuid @swap";
|
||||
};
|
||||
}
|
||||
|
@@ -36,5 +36,5 @@
|
||||
locations."/".proxyPass = "http://127.0.0.1:4533";
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."music" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."music" = "native";
|
||||
}
|
||||
|
67
hosts/by-name/servo/services/nfs.nix
Normal file
67
hosts/by-name/servo/services/nfs.nix
Normal file
@@ -0,0 +1,67 @@
|
||||
# docs:
|
||||
# - <https://nixos.wiki/wiki/NFS>
|
||||
# - <https://wiki.gentoo.org/wiki/Nfs-utils>
|
||||
|
||||
{ ... }:
|
||||
{
|
||||
services.nfs.server.enable = true;
|
||||
|
||||
# see which ports NFS uses with:
|
||||
# - `rpcinfo -p`
|
||||
sane.ports.ports."111" = {
|
||||
protocol = [ "tcp" "udp" ];
|
||||
visibleTo.lan = true;
|
||||
description = "NFS server portmapper";
|
||||
};
|
||||
sane.ports.ports."2049" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
description = "NFS server";
|
||||
};
|
||||
sane.ports.ports."4000" = {
|
||||
protocol = [ "udp" ];
|
||||
visibleTo.lan = true;
|
||||
description = "NFS server status daemon";
|
||||
};
|
||||
sane.ports.ports."4001" = {
|
||||
protocol = [ "tcp" "udp" ];
|
||||
visibleTo.lan = true;
|
||||
description = "NFS server lock daemon";
|
||||
};
|
||||
sane.ports.ports."4002" = {
|
||||
protocol = [ "tcp" "udp" ];
|
||||
visibleTo.lan = true;
|
||||
description = "NFS server mount daemon";
|
||||
};
|
||||
|
||||
# NFS4 allows these to float, but NFS3 mandates specific ports, so fix them for backwards compat.
|
||||
services.nfs.server.lockdPort = 4001;
|
||||
services.nfs.server.mountdPort = 4002;
|
||||
services.nfs.server.statdPort = 4000;
|
||||
|
||||
# format:
|
||||
# fspoint visibility(options)
|
||||
# options:
|
||||
# - see: <https://wiki.gentoo.org/wiki/Nfs-utils#Exports>
|
||||
# - see [man 5 exports](https://linux.die.net/man/5/exports)
|
||||
# - insecure: require clients use src port > 1024
|
||||
# - rw, ro (default)
|
||||
# - async, sync (default)
|
||||
# - no_subtree_check (default), subtree_check: verify not just that files requested by the client live
|
||||
# in the expected fs, but also that they live under whatever subdirectory of that fs is exported.
|
||||
# - no_root_squash, root_squash (default): map requests from uid 0 to user `nobody`.
|
||||
# - crossmnt: reveal filesystems that are mounted under this endpoint
|
||||
# - fsid: must be zero for the root export
|
||||
# - mountpoint[=/path]: only export the directory if it's a mountpoint. used to avoid exporting failed mounts.
|
||||
#
|
||||
# 10.0.0.0/8 to export (readonly) both to LAN (unencrypted) and wg vpn (encrypted)
|
||||
services.nfs.server.exports = ''
|
||||
/var/nfs/export 10.78.79.0/22(ro,crossmnt,fsid=0,subtree_check) 10.0.10.0/24(rw,no_root_squash,crossmnt,fsid=0,subtree_check)
|
||||
'';
|
||||
|
||||
fileSystems."/var/nfs/export/media" = {
|
||||
# everything in here could be considered publicly readable (based on the viewer's legal jurisdiction)
|
||||
device = "/var/lib/uninsane/media";
|
||||
options = [ "rbind" ];
|
||||
};
|
||||
}
|
@@ -14,7 +14,7 @@
|
||||
'';
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."nixcache" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."nixcache" = "native";
|
||||
|
||||
sane.services.nixserve.enable = true;
|
||||
sane.services.nixserve.secretKeyFile = config.sops.secrets.nix_serve_privkey.path;
|
||||
|
@@ -182,7 +182,7 @@
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."fed" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."fed" = "native";
|
||||
|
||||
sops.secrets."pleroma_secrets" = {
|
||||
owner = config.users.users.pleroma.name;
|
||||
|
@@ -75,6 +75,6 @@
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."bt" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."bt" = "native";
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
{ config, pkgs, ... }:
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
sane.services.trust-dns.enable = true;
|
||||
@@ -11,7 +11,7 @@
|
||||
];
|
||||
sane.services.trust-dns.quiet = true;
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".TTL = 900;
|
||||
sane.dns.zones."uninsane.org".TTL = 900;
|
||||
|
||||
# SOA record structure: <https://en.wikipedia.org/wiki/SOA_record#Structure>
|
||||
# SOA MNAME RNAME (... rest)
|
||||
@@ -21,7 +21,7 @@
|
||||
# Refresh = how frequently secondary NS should query master
|
||||
# Retry = how long secondary NS should wait until re-querying master after a failure (must be < Refresh)
|
||||
# Expire = how long secondary NS should continue to reply to queries after master fails (> Refresh + Retry)
|
||||
sane.services.trust-dns.zones."uninsane.org".inet = {
|
||||
sane.dns.zones."uninsane.org".inet = {
|
||||
SOA."@" = ''
|
||||
ns1.uninsane.org. admin-dns.uninsane.org. (
|
||||
2022122101 ; Serial
|
||||
@@ -51,7 +51,9 @@
|
||||
];
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".file = "uninsane.org.zone";
|
||||
# we need trust-dns to load our zone by relative path instead of /nix/store path
|
||||
# because we generate it at runtime.
|
||||
sane.services.trust-dns.zones."uninsane.org".file = lib.mkForce "uninsane.org.zone";
|
||||
sane.services.trust-dns.zonedir = null;
|
||||
|
||||
sane.services.trust-dns.package =
|
||||
@@ -60,7 +62,7 @@
|
||||
zone-dir = "/var/lib/trust-dns";
|
||||
zone-wan = "${zone-dir}/wan/uninsane.org.zone";
|
||||
zone-lan = "${zone-dir}/lan/uninsane.org.zone";
|
||||
zone-template = pkgs.writeText "uninsane.org.zone.in" config.sane.services.trust-dns.generatedZones."uninsane.org";
|
||||
zone-template = pkgs.writeText "uninsane.org.zone.in" config.sane.services.trust-dns.zones."uninsane.org".text;
|
||||
in pkgs.writeShellScriptBin "named" ''
|
||||
# compute wan/lan values
|
||||
mkdir -p ${zone-dir}/{ovpn,wan,lan}
|
||||
|
@@ -79,12 +79,14 @@ let
|
||||
(fromDb "feeds.transistor.fm/acquired" // tech)
|
||||
## ACQ2 - more "Acquired" episodes
|
||||
(fromDb "acquiredlpbonussecretsecret.libsyn.com" // tech)
|
||||
# The Intercept - Deconstructed; also available: <rss.acast.com/deconstructed>
|
||||
(fromDb "rss.prod.firstlook.media/deconstructed/podcast.rss" // pol)
|
||||
# The Intercept - Deconstructed
|
||||
(fromDb "rss.acast.com/deconstructed")
|
||||
# (fromDb "rss.prod.firstlook.media/deconstructed/podcast.rss" // pol) #< possible URL rot
|
||||
## The Daily
|
||||
(mkPod "https://feeds.simplecast.com/54nAGcIl" // pol // daily)
|
||||
# The Intercept - Intercepted; also available: <https://rss.acast.com/intercepted-with-jeremy-scahill>
|
||||
(fromDb "rss.prod.firstlook.media/intercepted/podcast.rss" // pol)
|
||||
# The Intercept - Intercepted
|
||||
(fromDb "rss.acast.com/intercepted-with-jeremy-scahill")
|
||||
# (fromDb "rss.prod.firstlook.media/intercepted/podcast.rss" // pol) #< possible URL rot
|
||||
(fromDb "podcast.posttv.com/itunes/post-reports.xml" // pol)
|
||||
## Eric Weinstein
|
||||
(fromDb "rss.art19.com/the-portal" // rat)
|
||||
|
@@ -1,72 +1,131 @@
|
||||
{ pkgs, ... }:
|
||||
# docs
|
||||
# - x-systemd options: <https://www.freedesktop.org/software/systemd/man/systemd.mount.html>
|
||||
|
||||
let sshOpts = rec {
|
||||
fsType = "fuse.sshfs";
|
||||
optionsBase = [
|
||||
"x-systemd.automount"
|
||||
{ pkgs, sane-lib, ... }:
|
||||
|
||||
let fsOpts = rec {
|
||||
common = [
|
||||
"_netdev"
|
||||
"noatime"
|
||||
"x-systemd.requires=network-online.target"
|
||||
"x-systemd.after=network-online.target"
|
||||
"x-systemd.mount-timeout=10s" # how long to wait for mount **and** how long to wait for unmount
|
||||
];
|
||||
auto = [ "x-systemd.automount" ];
|
||||
noauto = [ "noauto" ]; # don't mount as part of remote-fs.target
|
||||
wg = [
|
||||
"x-systemd.requires=wireguard-wg-home.service"
|
||||
"x-systemd.after=wireguard-wg-home.service"
|
||||
];
|
||||
|
||||
ssh = common ++ [
|
||||
"user"
|
||||
"identityfile=/home/colin/.ssh/id_ed25519"
|
||||
"allow_other"
|
||||
"default_permissions"
|
||||
];
|
||||
optionsColin = optionsBase ++ [
|
||||
sshColin = ssh ++ [
|
||||
"transform_symlinks"
|
||||
"idmap=user"
|
||||
"uid=1000"
|
||||
"gid=100"
|
||||
];
|
||||
|
||||
optionsRoot = optionsBase ++ [
|
||||
sshRoot = ssh ++ [
|
||||
# we don't transform_symlinks because that breaks the validity of remote /nix stores
|
||||
"sftp_server=/run/wrappers/bin/sudo\\040/run/current-system/sw/libexec/sftp-server"
|
||||
];
|
||||
# in the event of hunt NFS mounts, consider:
|
||||
# - <https://unix.stackexchange.com/questions/31979/stop-broken-nfs-mounts-from-locking-a-directory>
|
||||
|
||||
# NFS options: <https://linux.die.net/man/5/nfs>
|
||||
# actimeo=n = how long (in seconds) to cache file/dir attributes (default: 3-60s)
|
||||
# bg = retry failed mounts in the background
|
||||
# retry=n = for how many minutes `mount` will retry NFS mount operation
|
||||
# soft = on "major timeout", report I/O error to userspace
|
||||
# retrans=n = how many times to retry a NFS request before giving userspace a "server not responding" error (default: 3)
|
||||
# timeo=n = number of *deciseconds* to wait for a response before retrying it (default: 600)
|
||||
# note: client uses a linear backup, so the second request will have double this timeout, then triple, etc.
|
||||
nfs = common ++ [
|
||||
# "actimeo=10"
|
||||
"bg"
|
||||
"retrans=4"
|
||||
"retry=0"
|
||||
"soft"
|
||||
"timeo=15"
|
||||
"nofail" # don't fail remote-fs.target when this mount fails (not an option for sshfs else would be common)
|
||||
];
|
||||
};
|
||||
in
|
||||
{
|
||||
# fileSystems."/mnt/servo-nfs" = {
|
||||
# device = "servo-hn:/";
|
||||
# noCheck = true;
|
||||
# fsType = "nfs";
|
||||
# options = fsOpts.nfs ++ fsOpts.auto ++ fsOpts.wg;
|
||||
# };
|
||||
fileSystems."/mnt/servo-nfs/media" = {
|
||||
device = "servo-hn:/media";
|
||||
noCheck = true;
|
||||
fsType = "nfs";
|
||||
options = fsOpts.nfs ++ fsOpts.auto ++ fsOpts.wg;
|
||||
};
|
||||
# fileSystems."/mnt/servo-media-nfs" = {
|
||||
# device = "servo-hn:/media";
|
||||
# noCheck = true;
|
||||
# fsType = "nfs";
|
||||
# options = fsOpts.common ++ fsOpts.auto;
|
||||
# };
|
||||
sane.fs."/mnt/servo-media" = sane-lib.fs.wantedSymlinkTo "/mnt/servo-nfs/media";
|
||||
|
||||
fileSystems."/mnt/servo-media-wan" = {
|
||||
device = "colin@uninsane.org:/var/lib/uninsane/media";
|
||||
fsType = "fuse.sshfs";
|
||||
options = fsOpts.sshColin ++ fsOpts.noauto;
|
||||
noCheck = true;
|
||||
};
|
||||
sane.fs."/mnt/servo-media-wan" = sane-lib.fs.wantedDir;
|
||||
fileSystems."/mnt/servo-media-lan" = {
|
||||
device = "colin@servo:/var/lib/uninsane/media";
|
||||
fsType = "fuse.sshfs";
|
||||
options = fsOpts.sshColin ++ fsOpts.noauto;
|
||||
noCheck = true;
|
||||
};
|
||||
sane.fs."/mnt/servo-media-lan" = sane-lib.fs.wantedDir;
|
||||
fileSystems."/mnt/servo-root-wan" = {
|
||||
device = "colin@uninsane.org:/";
|
||||
fsType = "fuse.sshfs";
|
||||
options = fsOpts.sshRoot ++ fsOpts.noauto;
|
||||
noCheck = true;
|
||||
};
|
||||
sane.fs."/mnt/servo-root-wan" = sane-lib.fs.wantedDir;
|
||||
fileSystems."/mnt/servo-root-lan" = {
|
||||
device = "colin@servo:/";
|
||||
fsType = "fuse.sshfs";
|
||||
options = fsOpts.sshRoot ++ fsOpts.noauto;
|
||||
noCheck = true;
|
||||
};
|
||||
sane.fs."/mnt/servo-root-lan" = sane-lib.fs.wantedDir;
|
||||
fileSystems."/mnt/desko-home" = {
|
||||
device = "colin@desko:/home/colin";
|
||||
fsType = "fuse.sshfs";
|
||||
options = fsOpts.sshColin ++ fsOpts.noauto;
|
||||
noCheck = true;
|
||||
};
|
||||
sane.fs."/mnt/desko-home" = sane-lib.fs.wantedDir;
|
||||
fileSystems."/mnt/desko-root" = {
|
||||
device = "colin@desko:/";
|
||||
fsType = "fuse.sshfs";
|
||||
options = fsOpts.sshRoot ++ fsOpts.noauto;
|
||||
noCheck = true;
|
||||
};
|
||||
sane.fs."/mnt/desko-root" = sane-lib.fs.wantedDir;
|
||||
|
||||
environment.pathsToLink = [
|
||||
# needed to achieve superuser access for user-mounted filesystems (see optionsRoot above)
|
||||
# we can only link whole directories here, even though we're only interested in pkgs.openssh
|
||||
"/libexec"
|
||||
];
|
||||
|
||||
fileSystems."/mnt/servo-media-wan" = {
|
||||
device = "colin@uninsane.org:/var/lib/uninsane/media";
|
||||
inherit (sshOpts) fsType;
|
||||
options = sshOpts.optionsColin;
|
||||
noCheck = true;
|
||||
};
|
||||
fileSystems."/mnt/servo-media-lan" = {
|
||||
device = "colin@servo:/var/lib/uninsane/media";
|
||||
inherit (sshOpts) fsType;
|
||||
options = sshOpts.optionsColin;
|
||||
noCheck = true;
|
||||
};
|
||||
fileSystems."/mnt/servo-root-wan" = {
|
||||
device = "colin@uninsane.org:/";
|
||||
inherit (sshOpts) fsType;
|
||||
options = sshOpts.optionsRoot;
|
||||
noCheck = true;
|
||||
};
|
||||
fileSystems."/mnt/servo-root-lan" = {
|
||||
device = "colin@servo:/";
|
||||
inherit (sshOpts) fsType;
|
||||
options = sshOpts.optionsRoot;
|
||||
noCheck = true;
|
||||
};
|
||||
fileSystems."/mnt/desko-home" = {
|
||||
device = "colin@desko:/home/colin";
|
||||
inherit (sshOpts) fsType;
|
||||
options = sshOpts.optionsColin;
|
||||
noCheck = true;
|
||||
};
|
||||
fileSystems."/mnt/desko-root" = {
|
||||
device = "colin@desko:/";
|
||||
inherit (sshOpts) fsType;
|
||||
options = sshOpts.optionsRoot;
|
||||
noCheck = true;
|
||||
};
|
||||
|
||||
environment.systemPackages = [
|
||||
pkgs.sshfs-fuse
|
||||
];
|
||||
|
@@ -40,6 +40,8 @@
|
||||
sane.ids.lemmy.gid = 2408;
|
||||
sane.ids.pict-rs.uid = 2409;
|
||||
sane.ids.pict-rs.gid = 2409;
|
||||
sane.ids.sftpgo.uid = 2410;
|
||||
sane.ids.sftpgo.gid = 2410;
|
||||
|
||||
sane.ids.colin.uid = 1000;
|
||||
sane.ids.guest.uid = 1100;
|
||||
|
@@ -5,6 +5,9 @@
|
||||
nix.nixPath = [
|
||||
"nixpkgs=${pkgs.path}"
|
||||
# note the import starts at repo root: this allows `./overlay/default.nix` to access the stuff at the root
|
||||
"nixpkgs-overlays=${../../..}/hosts/common/nix-path/overlay"
|
||||
# "nixpkgs-overlays=${../../..}/hosts/common/nix-path/overlay"
|
||||
# as long as my system itself doesn't rely on NIXPKGS at runtime, we can point the overlays to git
|
||||
# to avoid switching so much during development
|
||||
"nixpkgs-overlays=/home/colin/dev/nixos/hosts/common/nix-path/overlay"
|
||||
];
|
||||
}
|
||||
|
387
hosts/common/programs/assorted.nix
Normal file
387
hosts/common/programs/assorted.nix
Normal file
@@ -0,0 +1,387 @@
|
||||
{ lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (builtins) attrNames;
|
||||
|
||||
flattenedPkgs = pkgs // (with pkgs; {
|
||||
# XXX can't `inherit` a nested attr, so we move them to the toplevel
|
||||
"cacert.unbundled" = pkgs.cacert.unbundled;
|
||||
"gnome.cheese" = gnome.cheese;
|
||||
"gnome.dconf-editor" = gnome.dconf-editor;
|
||||
"gnome.file-roller" = gnome.file-roller;
|
||||
"gnome.gnome-disk-utility" = gnome.gnome-disk-utility;
|
||||
"gnome.gnome-maps" = gnome.gnome-maps;
|
||||
"gnome.nautilus" = gnome.nautilus;
|
||||
"gnome.gnome-system-monitor" = gnome.gnome-system-monitor;
|
||||
"gnome.gnome-terminal" = gnome.gnome-terminal;
|
||||
"gnome.gnome-weather" = gnome.gnome-weather;
|
||||
"gnome.totem" = gnome.totem;
|
||||
"libsForQt5.plasmatube" = libsForQt5.plasmatube;
|
||||
});
|
||||
|
||||
sysadminPkgs = {
|
||||
inherit (flattenedPkgs)
|
||||
btrfs-progs
|
||||
"cacert.unbundled" # some services require unbundled /etc/ssl/certs
|
||||
cryptsetup
|
||||
dig
|
||||
efibootmgr
|
||||
fatresize
|
||||
fd
|
||||
file
|
||||
gawk
|
||||
git
|
||||
gptfdisk
|
||||
hdparm
|
||||
htop
|
||||
iftop
|
||||
inetutils # for telnet
|
||||
iotop
|
||||
iptables
|
||||
jq
|
||||
killall
|
||||
lsof
|
||||
miniupnpc
|
||||
nano
|
||||
netcat
|
||||
nethogs
|
||||
nmap
|
||||
openssl
|
||||
parted
|
||||
pciutils
|
||||
powertop
|
||||
pstree
|
||||
ripgrep
|
||||
screen
|
||||
smartmontools
|
||||
socat
|
||||
strace
|
||||
subversion
|
||||
tcpdump
|
||||
tree
|
||||
usbutils
|
||||
wget
|
||||
wirelesstools # iwlist
|
||||
;
|
||||
};
|
||||
sysadminExtraPkgs = {
|
||||
# application-specific packages
|
||||
inherit (pkgs)
|
||||
backblaze-b2
|
||||
duplicity
|
||||
sqlite # to debug sqlite3 databases
|
||||
;
|
||||
};
|
||||
|
||||
iphonePkgs = {
|
||||
inherit (pkgs)
|
||||
ifuse
|
||||
ipfs
|
||||
libimobiledevice
|
||||
;
|
||||
};
|
||||
|
||||
tuiPkgs = {
|
||||
inherit (pkgs)
|
||||
aerc # email client
|
||||
offlineimap # email mailox sync
|
||||
sfeed # RSS fetcher
|
||||
visidata # TUI spreadsheet viewer/editor
|
||||
w3m
|
||||
;
|
||||
};
|
||||
|
||||
consoleMediaPkgs = {
|
||||
inherit (pkgs)
|
||||
ffmpeg
|
||||
imagemagick
|
||||
sox
|
||||
yt-dlp
|
||||
;
|
||||
};
|
||||
# TODO: split these into smaller groups.
|
||||
# - moby doesn't want a lot of these.
|
||||
# - categories like
|
||||
# - dev?
|
||||
# - debugging?
|
||||
consolePkgs = {
|
||||
inherit (pkgs)
|
||||
alsaUtils # for aplay, speaker-test
|
||||
# cdrtools
|
||||
clinfo
|
||||
dmidecode
|
||||
efivar
|
||||
# flashrom
|
||||
fwupd
|
||||
gh # MS GitHub cli
|
||||
git # needed as a user package, for config.
|
||||
# gnupg
|
||||
# gocryptfs
|
||||
# gopass
|
||||
# gopass-jsonapi
|
||||
kitty # TODO: move to GUI, but `ssh servo` from kitty sets `TERM=xterm-kitty` in the remove and breaks things
|
||||
libsecret # for managing user keyrings. TODO: what needs this? lift into the consumer
|
||||
lm_sensors # for sensors-detect. TODO: what needs this? lift into the consumer
|
||||
lshw
|
||||
# memtester
|
||||
neovim
|
||||
# nettools
|
||||
# networkmanager
|
||||
nixpkgs-review
|
||||
# nixos-generators
|
||||
nmon
|
||||
# node2nix
|
||||
# oathToolkit # for oathtool
|
||||
# ponymix
|
||||
pulsemixer
|
||||
python3
|
||||
ripgrep # needed as a user package so that its user-level config file can be installed
|
||||
rsync
|
||||
# python3Packages.eyeD3 # music tagging
|
||||
sane-scripts
|
||||
sequoia
|
||||
snapper
|
||||
sops
|
||||
speedtest-cli
|
||||
# ssh-to-age
|
||||
sudo
|
||||
# tageditor # music tagging
|
||||
unar
|
||||
wireguard-tools
|
||||
xdg-utils # for xdg-open
|
||||
# yarn
|
||||
zsh
|
||||
;
|
||||
};
|
||||
|
||||
guiPkgs = {
|
||||
inherit (flattenedPkgs)
|
||||
# celluloid # mpv frontend
|
||||
cozy # audiobook player
|
||||
# emote
|
||||
evince # works on phosh
|
||||
|
||||
# { pkg = fluffychat-moby; persist.plaintext = [ ".local/share/chat.fluffy.fluffychat" ]; } # TODO: ship normal fluffychat on non-moby?
|
||||
|
||||
# foliate # e-book reader
|
||||
|
||||
# XXX by default fractal stores its state in ~/.local/share/<UUID>.
|
||||
# after logging in, manually change ~/.local/share/keyrings/... to point it to some predictable subdir.
|
||||
# then reboot (so that libsecret daemon re-loads the keyring...?)
|
||||
# { pkg = fractal-latest; persist.private = [ ".local/share/fractal" ]; }
|
||||
# { pkg = fractal-next; persist.private = [ ".local/share/fractal" ]; }
|
||||
|
||||
# "gnome.cheese"
|
||||
# gnome-feeds # RSS reader (with claimed mobile support)
|
||||
"gnome.file-roller"
|
||||
# "gnome.gnome-maps" # works on phosh
|
||||
"gnome.nautilus"
|
||||
# gnome-podcasts
|
||||
# "gnome.gnome-system-monitor"
|
||||
# "gnome.gnome-terminal" # works on phosh
|
||||
# "gnome.gnome-weather"
|
||||
gpodder
|
||||
gthumb
|
||||
jellyfin-media-player
|
||||
komikku
|
||||
koreader
|
||||
# lollypop
|
||||
mepo # maps viewer
|
||||
# mpv
|
||||
# networkmanagerapplet
|
||||
# newsflash
|
||||
nheko
|
||||
pavucontrol
|
||||
# picard # music tagging
|
||||
# "libsForQt5.plasmatube" # Youtube player
|
||||
soundconverter
|
||||
# sublime-music
|
||||
# tdesktop # broken on phosh
|
||||
# tokodon
|
||||
tuba # mastodon/pleroma client (stores pw in keyring)
|
||||
vlc
|
||||
# pleroma client (Electron). input is broken on phosh. TODO(2023/02/02): fix electron19 input (insecure)
|
||||
# whalebird
|
||||
xterm # broken on phosh
|
||||
;
|
||||
};
|
||||
desktopGuiPkgs = {
|
||||
inherit (flattenedPkgs)
|
||||
audacity
|
||||
brave # for the integrated wallet -- as a backup
|
||||
chromium
|
||||
dino
|
||||
electrum
|
||||
element-desktop
|
||||
font-manager
|
||||
gajim # XMPP client
|
||||
gimp # broken on phosh
|
||||
"gnome.dconf-editor"
|
||||
"gnome.gnome-disk-utility"
|
||||
# "gnome.totem" # video player, supposedly supports UPnP
|
||||
handbrake
|
||||
hase
|
||||
inkscape
|
||||
kdenlive
|
||||
kid3 # audio tagging
|
||||
krita
|
||||
libreoffice-fresh
|
||||
mumble
|
||||
obsidian
|
||||
slic3r
|
||||
steam
|
||||
wireshark # could maybe ship the cli as sysadmin pkg
|
||||
;
|
||||
};
|
||||
x86GuiPkgs = {
|
||||
inherit (pkgs)
|
||||
discord
|
||||
|
||||
# kaiteki # Pleroma client
|
||||
# gnome.zenity # for kaiteki (it will use qarma, kdialog, or zenity)
|
||||
# gpt2tc # XXX: unreliable mirror
|
||||
|
||||
# logseq # Personal Knowledge Management
|
||||
losslesscut-bin
|
||||
makemkv
|
||||
monero-gui
|
||||
signal-desktop
|
||||
spotify
|
||||
tor-browser-bundle-bin
|
||||
zecwallet-lite
|
||||
;
|
||||
};
|
||||
|
||||
# packages not part of any package set; not enabled by default
|
||||
otherPkgs = {
|
||||
inherit (pkgs)
|
||||
lemmy-server
|
||||
mx-sanebot
|
||||
stepmania
|
||||
;
|
||||
};
|
||||
|
||||
# define -- but don't enable -- the packages in some attrset.
|
||||
declarePkgs = pkgsAsAttrs: lib.mapAttrs (_n: p: {
|
||||
# no need to actually define the package here: it's defaulted
|
||||
# package = mkDefault p;
|
||||
}) pkgsAsAttrs;
|
||||
in
|
||||
{
|
||||
sane.programs = lib.mkMerge [
|
||||
(declarePkgs consoleMediaPkgs)
|
||||
(declarePkgs consolePkgs)
|
||||
(declarePkgs desktopGuiPkgs)
|
||||
(declarePkgs guiPkgs)
|
||||
(declarePkgs iphonePkgs)
|
||||
(declarePkgs sysadminPkgs)
|
||||
(declarePkgs sysadminExtraPkgs)
|
||||
(declarePkgs tuiPkgs)
|
||||
(declarePkgs x86GuiPkgs)
|
||||
(declarePkgs otherPkgs)
|
||||
{
|
||||
# link the various package sets into their own meta packages
|
||||
consoleMediaUtils = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames consoleMediaPkgs;
|
||||
};
|
||||
consoleUtils = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames consolePkgs;
|
||||
};
|
||||
desktopGuiApps = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames desktopGuiPkgs;
|
||||
};
|
||||
guiApps = {
|
||||
package = null;
|
||||
suggestedPrograms = (attrNames guiPkgs)
|
||||
++ [ "web-browser" ]
|
||||
++ [ "tuiApps" ]
|
||||
++ lib.optional (pkgs.system == "x86_64-linux") "x86GuiApps";
|
||||
};
|
||||
iphoneUtils = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames iphonePkgs;
|
||||
};
|
||||
sysadminUtils = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames sysadminPkgs;
|
||||
};
|
||||
sysadminExtraUtils = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames sysadminExtraPkgs;
|
||||
};
|
||||
tuiApps = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames tuiPkgs;
|
||||
};
|
||||
x86GuiApps = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames x86GuiPkgs;
|
||||
};
|
||||
}
|
||||
{
|
||||
# nontrivial package definitions
|
||||
|
||||
dino.persist.private = [ ".local/share/dino" ];
|
||||
|
||||
# creds, but also 200 MB of node modules, etc
|
||||
discord.persist.private = [ ".config/discord" ];
|
||||
|
||||
# creds/session keys, etc
|
||||
element-desktop.persist.private = [ ".config/Element" ];
|
||||
|
||||
# `emote` will show a first-run dialog based on what's in this directory.
|
||||
# mostly, it just keeps a LRU of previously-used emotes to optimize display order.
|
||||
# TODO: package [smile](https://github.com/mijorus/smile) for probably a better mobile experience.
|
||||
emote.persist.plaintext = [ ".local/share/Emote" ];
|
||||
|
||||
# MS GitHub stores auth token in .config
|
||||
# TODO: we can populate gh's stuff statically; it even lets us use the same oauth across machines
|
||||
gh.persist.private = [ ".config/gh" ];
|
||||
|
||||
# actual monero blockchain (not wallet/etc; safe to delete, just slow to regenerate)
|
||||
# XXX: is it really safe to persist this? it doesn't have info that could de-anonymize if captured?
|
||||
monero-gui.persist.plaintext = [ ".bitmonero" ];
|
||||
|
||||
mumble.persist.private = [ ".local/share/Mumble" ];
|
||||
|
||||
# not strictly necessary, but allows caching articles; offline use, etc.
|
||||
nheko.persist.private = [
|
||||
".config/nheko" # config file (including client token)
|
||||
".cache/nheko" # media cache
|
||||
".local/share/nheko" # per-account state database
|
||||
];
|
||||
|
||||
# settings (electron app)
|
||||
obsidian.persist.plaintext = [ ".config/obsidian" ];
|
||||
|
||||
# creds, media
|
||||
signal-desktop.persist.private = [ ".config/Signal" ];
|
||||
|
||||
# printer/filament settings
|
||||
slic3r.persist.plaintext = [ ".Slic3r" ];
|
||||
|
||||
# creds, widevine .so download. TODO: could easily manage these statically.
|
||||
spotify.persist.plaintext = [ ".config/spotify" ];
|
||||
|
||||
tdesktop.persist.private = [ ".local/share/TelegramDesktop" ];
|
||||
|
||||
tokodon.persist.private = [ ".cache/KDE/tokodon" ];
|
||||
|
||||
# hardenedMalloc solves a crash at startup
|
||||
# TODO 2023/02/02: is this safe to remove yet?
|
||||
tor-browser-bundle-bin.package = pkgs.tor-browser-bundle-bin.override {
|
||||
useHardenedMalloc = false;
|
||||
};
|
||||
|
||||
whalebird.persist.private = [ ".config/Whalebird" ];
|
||||
|
||||
yarn.persist.plaintext = [ ".cache/yarn" ];
|
||||
|
||||
# zcash coins. safe to delete, just slow to regenerate (10-60 minutes)
|
||||
zecwallet-lite.persist.private = [ ".zcash" ];
|
||||
}
|
||||
];
|
||||
}
|
11
hosts/common/programs/cozy.nix
Normal file
11
hosts/common/programs/cozy.nix
Normal file
@@ -0,0 +1,11 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
sane.programs.cozy = {
|
||||
# cozy uses a sqlite db for its config and exposes no CLI options other than --help and --debug
|
||||
persist.plaintext = [
|
||||
".local/share/cozy" # sqlite db (config & index?)
|
||||
".cache/cozy" # offline cache
|
||||
];
|
||||
};
|
||||
}
|
@@ -1,278 +1,28 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
{ pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (builtins) attrNames concatLists;
|
||||
inherit (lib) mapAttrs mapAttrsToList mkDefault mkIf mkMerge optional;
|
||||
|
||||
flattenedPkgs = pkgs // (with pkgs; {
|
||||
# XXX can't `inherit` a nested attr, so we move them to the toplevel
|
||||
"cacert.unbundled" = pkgs.cacert.unbundled;
|
||||
"gnome.cheese" = gnome.cheese;
|
||||
"gnome.dconf-editor" = gnome.dconf-editor;
|
||||
"gnome.file-roller" = gnome.file-roller;
|
||||
"gnome.gnome-disk-utility" = gnome.gnome-disk-utility;
|
||||
"gnome.gnome-maps" = gnome.gnome-maps;
|
||||
"gnome.nautilus" = gnome.nautilus;
|
||||
"gnome.gnome-system-monitor" = gnome.gnome-system-monitor;
|
||||
"gnome.gnome-terminal" = gnome.gnome-terminal;
|
||||
"gnome.gnome-weather" = gnome.gnome-weather;
|
||||
"gnome.totem" = gnome.totem;
|
||||
"libsForQt5.plasmatube" = libsForQt5.plasmatube;
|
||||
});
|
||||
|
||||
sysadminPkgs = {
|
||||
inherit (flattenedPkgs)
|
||||
btrfs-progs
|
||||
"cacert.unbundled" # some services require unbundled /etc/ssl/certs
|
||||
cryptsetup
|
||||
dig
|
||||
efibootmgr
|
||||
fatresize
|
||||
fd
|
||||
file
|
||||
gawk
|
||||
git
|
||||
gptfdisk
|
||||
hdparm
|
||||
htop
|
||||
iftop
|
||||
inetutils # for telnet
|
||||
iotop
|
||||
iptables
|
||||
jq
|
||||
killall
|
||||
lsof
|
||||
miniupnpc
|
||||
nano
|
||||
netcat
|
||||
nethogs
|
||||
nmap
|
||||
openssl
|
||||
parted
|
||||
pciutils
|
||||
powertop
|
||||
pstree
|
||||
ripgrep
|
||||
screen
|
||||
smartmontools
|
||||
socat
|
||||
strace
|
||||
subversion
|
||||
tcpdump
|
||||
tree
|
||||
usbutils
|
||||
wget
|
||||
wirelesstools # iwlist
|
||||
;
|
||||
};
|
||||
sysadminExtraPkgs = {
|
||||
# application-specific packages
|
||||
inherit (pkgs)
|
||||
backblaze-b2
|
||||
duplicity
|
||||
sqlite # to debug sqlite3 databases
|
||||
;
|
||||
};
|
||||
|
||||
iphonePkgs = {
|
||||
inherit (pkgs)
|
||||
ifuse
|
||||
ipfs
|
||||
libimobiledevice
|
||||
;
|
||||
};
|
||||
|
||||
tuiPkgs = {
|
||||
inherit (pkgs)
|
||||
aerc # email client
|
||||
offlineimap # email mailox sync
|
||||
visidata # TUI spreadsheet viewer/editor
|
||||
w3m
|
||||
;
|
||||
};
|
||||
|
||||
# TODO: split these into smaller groups.
|
||||
# - transcoders (ffmpeg, imagemagick) only wanted on desko/lappy ("powerutils"?)
|
||||
consolePkgs = {
|
||||
inherit (pkgs)
|
||||
alsaUtils # for aplay, speaker-test
|
||||
cdrtools
|
||||
dmidecode
|
||||
efivar
|
||||
flashrom
|
||||
fwupd
|
||||
gh # MS GitHub cli
|
||||
git # needed as a user package, for config.
|
||||
gnupg
|
||||
gocryptfs
|
||||
gopass # TODO: shouldn't be needed here
|
||||
gopass-jsonapi
|
||||
imagemagick
|
||||
kitty # TODO: move to GUI, but `ssh servo` from kitty sets `TERM=xterm-kitty` in the remove and breaks things
|
||||
libsecret # for managing user keyrings
|
||||
lm_sensors # for sensors-detect
|
||||
lshw
|
||||
ffmpeg
|
||||
# memtester
|
||||
neovim
|
||||
# nettools
|
||||
# networkmanager
|
||||
nixpkgs-review
|
||||
# nixos-generators
|
||||
nmon
|
||||
# node2nix
|
||||
# oathToolkit # for oathtool
|
||||
# ponymix
|
||||
pulsemixer
|
||||
python3
|
||||
ripgrep # needed as a user package, for config.
|
||||
rsync
|
||||
# python3Packages.eyeD3 # music tagging
|
||||
sane-scripts
|
||||
sequoia
|
||||
snapper
|
||||
sops
|
||||
sox
|
||||
speedtest-cli
|
||||
# ssh-to-age
|
||||
sudo
|
||||
# tageditor # music tagging
|
||||
unar
|
||||
wireguard-tools
|
||||
xdg-utils # for xdg-open
|
||||
# yarn
|
||||
# youtube-dl
|
||||
yt-dlp
|
||||
zsh
|
||||
;
|
||||
};
|
||||
|
||||
guiPkgs = {
|
||||
inherit (flattenedPkgs)
|
||||
# celluloid # mpv frontend
|
||||
clinfo
|
||||
emote
|
||||
evince # works on phosh
|
||||
|
||||
# { pkg = fluffychat-moby; persist.plaintext = [ ".local/share/chat.fluffy.fluffychat" ]; } # TODO: ship normal fluffychat on non-moby?
|
||||
|
||||
# foliate # e-book reader
|
||||
|
||||
# XXX by default fractal stores its state in ~/.local/share/<UUID>.
|
||||
# after logging in, manually change ~/.local/share/keyrings/... to point it to some predictable subdir.
|
||||
# then reboot (so that libsecret daemon re-loads the keyring...?)
|
||||
# { pkg = fractal-latest; persist.private = [ ".local/share/fractal" ]; }
|
||||
# { pkg = fractal-next; persist.private = [ ".local/share/fractal" ]; }
|
||||
|
||||
# "gnome.cheese"
|
||||
"gnome.dconf-editor"
|
||||
# gnome-feeds # RSS reader (with claimed mobile support)
|
||||
"gnome.file-roller"
|
||||
# "gnome.gnome-maps" # works on phosh
|
||||
"gnome.nautilus"
|
||||
# gnome-podcasts
|
||||
"gnome.gnome-system-monitor"
|
||||
# "gnome.gnome-terminal" # works on phosh
|
||||
# "gnome.gnome-weather"
|
||||
gpodder
|
||||
gthumb
|
||||
jellyfin-media-player
|
||||
# lollypop
|
||||
# mpv
|
||||
networkmanagerapplet
|
||||
# newsflash
|
||||
nheko
|
||||
pavucontrol
|
||||
# picard # music tagging
|
||||
playerctl
|
||||
# "libsForQt5.plasmatube" # Youtube player
|
||||
soundconverter
|
||||
sublime-music
|
||||
# tdesktop # broken on phosh
|
||||
# tokodon
|
||||
vlc
|
||||
# pleroma client (Electron). input is broken on phosh. TODO(2023/02/02): fix electron19 input (insecure)
|
||||
# whalebird
|
||||
xterm # broken on phosh
|
||||
;
|
||||
};
|
||||
desktopGuiPkgs = {
|
||||
inherit (flattenedPkgs)
|
||||
audacity
|
||||
brave # for the integrated wallet -- as a backup
|
||||
chromium
|
||||
dino
|
||||
electrum
|
||||
element-desktop
|
||||
font-manager
|
||||
gajim # XMPP client
|
||||
gimp # broken on phosh
|
||||
"gnome.gnome-disk-utility"
|
||||
# "gnome.totem" # video player, supposedly supports UPnP
|
||||
handbrake
|
||||
hase
|
||||
inkscape
|
||||
kdenlive
|
||||
kid3 # audio tagging
|
||||
krita
|
||||
libreoffice-fresh
|
||||
mumble
|
||||
obsidian
|
||||
slic3r
|
||||
steam
|
||||
wireshark # could maybe ship the cli as sysadmin pkg
|
||||
;
|
||||
};
|
||||
x86GuiPkgs = {
|
||||
inherit (pkgs)
|
||||
discord
|
||||
|
||||
# kaiteki # Pleroma client
|
||||
# gnome.zenity # for kaiteki (it will use qarma, kdialog, or zenity)
|
||||
# gpt2tc # XXX: unreliable mirror
|
||||
|
||||
# logseq # Personal Knowledge Management
|
||||
losslesscut-bin
|
||||
makemkv
|
||||
monero-gui
|
||||
signal-desktop
|
||||
spotify
|
||||
tor-browser-bundle-bin
|
||||
zecwallet-lite
|
||||
;
|
||||
};
|
||||
|
||||
# packages not part of any package set; not enabled by default
|
||||
otherPkgs = {
|
||||
inherit (pkgs)
|
||||
lemmy-server
|
||||
mx-sanebot
|
||||
stepmania
|
||||
;
|
||||
};
|
||||
|
||||
# define -- but don't enable -- the packages in some attrset.
|
||||
declarePkgs = pkgsAsAttrs: mapAttrs (_n: p: {
|
||||
# no need to actually define the package here: it's defaulted
|
||||
# package = mkDefault p;
|
||||
}) pkgsAsAttrs;
|
||||
in
|
||||
{
|
||||
|
||||
imports = [
|
||||
./aerc.nix
|
||||
./assorted.nix
|
||||
./cozy.nix
|
||||
./git.nix
|
||||
./gnome-feeds.nix
|
||||
./gpodder.nix
|
||||
./imagemagick.nix
|
||||
./jellyfin-media-player.nix
|
||||
./kitty
|
||||
./komikku.nix
|
||||
./koreader
|
||||
./libreoffice.nix
|
||||
./mepo.nix
|
||||
./mpv.nix
|
||||
./neovim.nix
|
||||
./newsflash.nix
|
||||
./offlineimap.nix
|
||||
./ripgrep.nix
|
||||
./sfeed.nix
|
||||
./splatmoji.nix
|
||||
./steam.nix
|
||||
./sublime-music.nix
|
||||
./vlc.nix
|
||||
./web-browser.nix
|
||||
@@ -282,141 +32,8 @@ in
|
||||
];
|
||||
|
||||
config = {
|
||||
sane.programs = mkMerge [
|
||||
(declarePkgs consolePkgs)
|
||||
(declarePkgs desktopGuiPkgs)
|
||||
(declarePkgs guiPkgs)
|
||||
(declarePkgs iphonePkgs)
|
||||
(declarePkgs sysadminPkgs)
|
||||
(declarePkgs sysadminExtraPkgs)
|
||||
(declarePkgs tuiPkgs)
|
||||
(declarePkgs x86GuiPkgs)
|
||||
(declarePkgs otherPkgs)
|
||||
{
|
||||
# link the various package sets into their own meta packages
|
||||
consoleUtils = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames consolePkgs;
|
||||
};
|
||||
desktopGuiApps = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames desktopGuiPkgs;
|
||||
};
|
||||
guiApps = {
|
||||
package = null;
|
||||
suggestedPrograms = (attrNames guiPkgs)
|
||||
++ [ "web-browser" ]
|
||||
++ [ "tuiApps" ]
|
||||
++ optional (pkgs.system == "x86_64-linux") "x86GuiApps";
|
||||
};
|
||||
iphoneUtils = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames iphonePkgs;
|
||||
};
|
||||
sysadminUtils = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames sysadminPkgs;
|
||||
};
|
||||
sysadminExtraUtils = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames sysadminExtraPkgs;
|
||||
};
|
||||
tuiApps = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames tuiPkgs;
|
||||
};
|
||||
x86GuiApps = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames x86GuiPkgs;
|
||||
};
|
||||
}
|
||||
{
|
||||
# nontrivial package definitions
|
||||
|
||||
dino.persist.private = [ ".local/share/dino" ];
|
||||
|
||||
# creds, but also 200 MB of node modules, etc
|
||||
discord.persist.private = [ ".config/discord" ];
|
||||
|
||||
# creds/session keys, etc
|
||||
element-desktop.persist.private = [ ".config/Element" ];
|
||||
|
||||
# `emote` will show a first-run dialog based on what's in this directory.
|
||||
# mostly, it just keeps a LRU of previously-used emotes to optimize display order.
|
||||
# TODO: package [smile](https://github.com/mijorus/smile) for probably a better mobile experience.
|
||||
emote.persist.plaintext = [ ".local/share/Emote" ];
|
||||
|
||||
# MS GitHub stores auth token in .config
|
||||
# TODO: we can populate gh's stuff statically; it even lets us use the same oauth across machines
|
||||
gh.persist.private = [ ".config/gh" ];
|
||||
|
||||
ghostscript = {}; # used by imagemagick
|
||||
|
||||
imagemagick = {
|
||||
package = pkgs.imagemagick.override {
|
||||
ghostscriptSupport = true;
|
||||
};
|
||||
suggestedPrograms = [ "ghostscript" ];
|
||||
};
|
||||
|
||||
# actual monero blockchain (not wallet/etc; safe to delete, just slow to regenerate)
|
||||
# XXX: is it really safe to persist this? it doesn't have info that could de-anonymize if captured?
|
||||
monero-gui.persist.plaintext = [ ".bitmonero" ];
|
||||
|
||||
mumble.persist.private = [ ".local/share/Mumble" ];
|
||||
|
||||
# not strictly necessary, but allows caching articles; offline use, etc.
|
||||
nheko.persist.private = [
|
||||
".config/nheko" # config file (including client token)
|
||||
".cache/nheko" # media cache
|
||||
".local/share/nheko" # per-account state database
|
||||
];
|
||||
|
||||
# settings (electron app)
|
||||
obsidian.persist.plaintext = [ ".config/obsidian" ];
|
||||
|
||||
# creds, media
|
||||
signal-desktop.persist.private = [ ".config/Signal" ];
|
||||
|
||||
# printer/filament settings
|
||||
slic3r.persist.plaintext = [ ".Slic3r" ];
|
||||
|
||||
# creds, widevine .so download. TODO: could easily manage these statically.
|
||||
spotify.persist.plaintext = [ ".config/spotify" ];
|
||||
|
||||
steam.persist.plaintext = [
|
||||
".steam"
|
||||
".local/share/Steam"
|
||||
];
|
||||
|
||||
tdesktop.persist.private = [ ".local/share/TelegramDesktop" ];
|
||||
|
||||
tokodon.persist.private = [ ".cache/KDE/tokodon" ];
|
||||
|
||||
# hardenedMalloc solves a crash at startup
|
||||
# TODO 2023/02/02: is this safe to remove yet?
|
||||
tor-browser-bundle-bin.package = pkgs.tor-browser-bundle-bin.override {
|
||||
useHardenedMalloc = false;
|
||||
};
|
||||
|
||||
whalebird.persist.private = [ ".config/Whalebird" ];
|
||||
|
||||
yarn.persist.plaintext = [ ".cache/yarn" ];
|
||||
|
||||
# zcash coins. safe to delete, just slow to regenerate (10-60 minutes)
|
||||
zecwallet-lite.persist.private = [ ".zcash" ];
|
||||
}
|
||||
];
|
||||
|
||||
# XXX: this might not be necessary. try removing this and cacert.unbundled (servo)?
|
||||
environment.etc."ssl/certs".source = "${pkgs.cacert.unbundled}/etc/ssl/certs/*";
|
||||
|
||||
# steam requires system-level config for e.g. firewall or controller support
|
||||
programs.steam = mkIf config.sane.programs.steam.enabled {
|
||||
enable = true;
|
||||
# not sure if needed: stole this whole snippet from the wiki
|
||||
remotePlay.openFirewall = true; # Open ports in the firewall for Steam Remote Play
|
||||
dedicatedServer.openFirewall = true; # Open ports in the firewall for Source Dedicated Server
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@@ -11,7 +11,10 @@ in
|
||||
user.name = "Colin";
|
||||
user.email = "colin@uninsane.org";
|
||||
|
||||
alias.co = "checkout";
|
||||
alias.co = "checkout";
|
||||
alias.d = "difftool";
|
||||
alias.st = "status";
|
||||
alias.stat = "status";
|
||||
|
||||
# difftastic docs:
|
||||
# - <https://difftastic.wilfred.me.uk/git.html>
|
||||
|
@@ -7,7 +7,8 @@ let
|
||||
wanted-feeds = feeds.filterByFormat ["podcast"] all-feeds;
|
||||
in {
|
||||
sane.programs.gpodder = {
|
||||
package = pkgs.gpodder-configured;
|
||||
package = pkgs.gpodder-adaptive-configured;
|
||||
# package = pkgs.gpodder-configured;
|
||||
fs.".config/gpodderFeeds.opml".symlink.text = feeds.feedsToOpml wanted-feeds;
|
||||
|
||||
# XXX: we preserve the whole thing because if we only preserve gPodder/Downloads
|
||||
|
10
hosts/common/programs/imagemagick.nix
Normal file
10
hosts/common/programs/imagemagick.nix
Normal file
@@ -0,0 +1,10 @@
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
sane.programs.imagemagick = {
|
||||
package = pkgs.imagemagick.override {
|
||||
ghostscriptSupport = true;
|
||||
};
|
||||
suggestedPrograms = [ "ghostscript" ];
|
||||
};
|
||||
sane.programs.ghostscript = {};
|
||||
}
|
@@ -2,8 +2,8 @@
|
||||
|
||||
{
|
||||
sane.programs.jellyfin-media-player = {
|
||||
package = pkgs.jellyfin-media-player;
|
||||
# package = pkgs.jellyfin-media-player-qt6;
|
||||
# package = pkgs.jellyfin-media-player;
|
||||
package = pkgs.jellyfin-media-player-qt6;
|
||||
|
||||
# jellyfin stores things in a bunch of directories: this one persists auth info.
|
||||
# it *might* be possible to populate this externally (it's Qt stuff), but likely to
|
||||
|
8
hosts/common/programs/komikku.nix
Normal file
8
hosts/common/programs/komikku.nix
Normal file
@@ -0,0 +1,8 @@
|
||||
{ ... }:
|
||||
{
|
||||
sane.programs.komikku = {
|
||||
secrets.".local/share/komikku/keyrings/plaintext.keyring" = ../../../secrets/common/komikku_accounts.json.bin;
|
||||
# downloads end up here, and without the toplevel database komikku doesn't know they exist.
|
||||
persist.plaintext = [ ".local/share/komikku" ];
|
||||
};
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
-- as of 2023.05.1, koreader FTP browser always fails to load.
|
||||
-- it's convinced that it's offline, and asks to connect to wifi.
|
||||
-- this seems to be because of the following in <frontend/device/sdl/device.lua>:
|
||||
--
|
||||
-- function Device:initNetworkManager(NetworkMgr)
|
||||
-- function NetworkMgr:isWifiOn() return true end
|
||||
-- function NetworkMgr:isConnected()
|
||||
-- -- Pull the default gateway first, so we don't even try to ping anything if there isn't one...
|
||||
-- local default_gw = Device:getDefaultRoute()
|
||||
-- if not default_gw then
|
||||
-- return false
|
||||
-- end
|
||||
-- return 0 == os.execute("ping -c1 -w2 " .. default_gw .. " > /dev/null")
|
||||
-- end
|
||||
-- end
|
||||
--
|
||||
-- specifically, `os.execute` is not *expected* to return 0. it returns `true` on success:
|
||||
-- <https://www.lua.org/manual/5.3/manual.html#pdf-os.execute>
|
||||
-- this apparently changed from 5.1 -> 5.2
|
||||
--
|
||||
-- XXX: this same bug likely applies to `isCommand` and `runCommand` in <frontend/device/sdl/device.lua>
|
||||
-- - that would manifest as wikipedia links failing to open in external application (xdg-open)
|
||||
|
||||
local logger = require("logger")
|
||||
logger.info("applying colin patch")
|
||||
|
||||
local Device = require("device")
|
||||
logger.info("Device:" .. tostring(Device))
|
||||
|
||||
local orig_initNetworkManager = Device.initNetworkManager
|
||||
Device.initNetworkManager = function(self, NetworkMgr)
|
||||
logger.info("Device:initNetworkManager")
|
||||
orig_initNetworkManager(self, NetworkMgr)
|
||||
function NetworkMgr:isConnected()
|
||||
logger.info("mocked `NetworkMgr:isConnected` to return true")
|
||||
return true
|
||||
-- unpatch to show that the boolean form works
|
||||
-- local rc = os.execute("ping -c1 -w2 10.78.79.1 > /dev/null")
|
||||
-- logger.info("ping rc: " .. tostring(rc))
|
||||
-- return rc
|
||||
end
|
||||
end
|
46
hosts/common/programs/koreader/default.nix
Normal file
46
hosts/common/programs/koreader/default.nix
Normal file
@@ -0,0 +1,46 @@
|
||||
{ config, lib, sane-lib, ... }:
|
||||
|
||||
let
|
||||
feeds = sane-lib.feeds;
|
||||
allFeeds = config.sane.feeds;
|
||||
wantedFeeds = feeds.filterByFormat [ "image" "text" ] allFeeds;
|
||||
koreaderRssEntries = builtins.map (feed:
|
||||
# format:
|
||||
# { "<rss/atom url>", limit = <int>, download_full_article=<bool>, include_images=<bool>, enable_filter=<bool>, filter_element = "<css selector>"},
|
||||
# limit = 0 => download and keep *all* articles
|
||||
# download_full_article = true => populate feed by downloading the webpage -- not just what's encoded in the RSS <article> tags
|
||||
# - use this for articles where the RSS only encodes content previews
|
||||
# enable_filter = true => only render content that matches the filter_element css selector.
|
||||
let fields = [
|
||||
(lib.escapeShellArg feed.url)
|
||||
"limit = 5"
|
||||
"download_full_article = false"
|
||||
"include_images = true"
|
||||
"enable_filter = false"
|
||||
"filter_element = \"\""
|
||||
]; in "{ ${lib.concatStringsSep ", " fields } }"
|
||||
) wantedFeeds;
|
||||
in {
|
||||
sane.programs.koreader = {
|
||||
# koreader applies these lua "patches" at boot:
|
||||
# - <https://github.com/koreader/koreader/wiki/User-patches>
|
||||
# - TODO: upstream this patch to koreader
|
||||
# fs.".config/koreader/patches".symlink.target = "${./.}";
|
||||
fs.".config/koreader/patches/2-colin-NetworkManager-isConnected.lua".symlink.target = "${./2-colin-NetworkManager-isConnected.lua}";
|
||||
|
||||
# koreader news plugin, enabled by default. file format described here:
|
||||
# - <repo:koreader/koreader:plugins/newsdownloader.koplugin/feed_config.lua>
|
||||
fs.".config/koreader/news/feed_config.lua".symlink.text = ''
|
||||
return {--do NOT change this line
|
||||
${lib.concatStringsSep ",\n " koreaderRssEntries}
|
||||
}--do NOT change this line
|
||||
'';
|
||||
|
||||
# koreader on aarch64 errors if there's no fonts directory (sandboxing thing, i guess)
|
||||
fs.".local/share/fonts".dir = {};
|
||||
|
||||
# history, cache, dictionaries...
|
||||
# could be more explicit if i symlinked the history.lua file to somewhere it can persist better.
|
||||
persist.plaintext = [ ".config/koreader" ];
|
||||
};
|
||||
}
|
18
hosts/common/programs/mepo.nix
Normal file
18
hosts/common/programs/mepo.nix
Normal file
@@ -0,0 +1,18 @@
|
||||
# docs: <https://git.sr.ht/~mil/mepo>
|
||||
# irc #mepo:irc.oftc.net
|
||||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
sane.programs.mepo = {
|
||||
persist.plaintext = [ ".cache/mepo/tiles" ];
|
||||
# ~/.cache/mepo/savestate has precise coordinates and pins: keep those private
|
||||
persist.private = [ ".cache/mepo/savestate" ];
|
||||
};
|
||||
|
||||
programs.mepo = lib.mkIf config.sane.programs.mepo.enabled {
|
||||
# enable location services (via geoclue)
|
||||
enable = true;
|
||||
# more precise, via gpsd ("may require additional config")
|
||||
# programs.mepo.gpsd.enable = true
|
||||
};
|
||||
}
|
28
hosts/common/programs/sfeed.nix
Normal file
28
hosts/common/programs/sfeed.nix
Normal file
@@ -0,0 +1,28 @@
|
||||
# simple RSS and Atom parser
|
||||
# - <https://codemadness.org/sfeed-simple-feed-parser.html>
|
||||
# - used by sxmo
|
||||
# - man 5 sfeedrc
|
||||
#
|
||||
# call `sfeed_update` to query each feed and populate entries in ~/.sfeed/feeds
|
||||
{ lib, config, sane-lib, ... }:
|
||||
let
|
||||
feeds = sane-lib.feeds;
|
||||
allFeeds = config.sane.feeds;
|
||||
wantedFeeds = feeds.filterByFormat ["text"] allFeeds;
|
||||
sfeedEntries = builtins.map (feed:
|
||||
# format:
|
||||
# feed <name> <feedurl> [basesiteurl] [encoding]
|
||||
lib.escapeShellArgs [ "feed" (if feed.title != null then feed.title else feed.url) feed.url ]
|
||||
) wantedFeeds;
|
||||
in {
|
||||
sane.programs.sfeed = {
|
||||
fs.".sfeed/sfeedrc".symlink.text = ''
|
||||
feeds() {
|
||||
${lib.concatStringsSep "\n " sfeedEntries}
|
||||
}
|
||||
'';
|
||||
|
||||
# this is where the parsed feed items go
|
||||
persist.plaintext = [ ".sfeed/feeds" ];
|
||||
};
|
||||
}
|
16
hosts/common/programs/steam.nix
Normal file
16
hosts/common/programs/steam.nix
Normal file
@@ -0,0 +1,16 @@
|
||||
{ config, lib, ...}:
|
||||
{
|
||||
sane.programs.steam = {
|
||||
persist.plaintext = [
|
||||
".steam"
|
||||
".local/share/Steam"
|
||||
];
|
||||
};
|
||||
# steam requires system-level config for e.g. firewall or controller support
|
||||
programs.steam = lib.mkIf config.sane.programs.steam.enabled {
|
||||
enable = true;
|
||||
# not sure if needed: stole this whole snippet from the wiki
|
||||
remotePlay.openFirewall = true; # Open ports in the firewall for Steam Remote Play
|
||||
dedicatedServer.openFirewall = true; # Open ports in the firewall for Source Dedicated Server
|
||||
};
|
||||
}
|
@@ -63,6 +63,7 @@ in
|
||||
"jackett_apikey".owner = config.users.users.colin.name;
|
||||
"mx-sanebot-env".owner = config.users.users.colin.name;
|
||||
"snippets".owner = config.users.users.colin.name;
|
||||
"transmission_passwd".owner = config.users.users.colin.name;
|
||||
}
|
||||
];
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{ config, lib, sane-data, sane-lib, ... }:
|
||||
|
||||
let
|
||||
inherit (builtins) head map mapAttrs tail;
|
||||
inherit (builtins) attrValues head map mapAttrs tail;
|
||||
inherit (lib) concatStringsSep mkMerge reverseList;
|
||||
in
|
||||
{
|
||||
@@ -18,11 +18,21 @@ in
|
||||
|
||||
# [{ path :: [String], value :: String }] for the keys we want to install
|
||||
globalKeys = sane-lib.flattenAttrs sane-data.keys;
|
||||
|
||||
keysForHost = hostCfg: sane-lib.mapToAttrs
|
||||
(name: {
|
||||
inherit name;
|
||||
value = {
|
||||
colin = hostCfg.ssh.user_pubkey;
|
||||
root = hostCfg.ssh.host_pubkey;
|
||||
};
|
||||
})
|
||||
hostCfg.names
|
||||
;
|
||||
domainKeys = sane-lib.flattenAttrs (
|
||||
mapAttrs (host: cfg: {
|
||||
colin = cfg.ssh.user_pubkey;
|
||||
root = cfg.ssh.host_pubkey;
|
||||
}) config.sane.hosts.by-name
|
||||
sane-lib.joinAttrsets (
|
||||
map keysForHost (builtins.attrValues config.sane.hosts.by-name)
|
||||
)
|
||||
);
|
||||
in mkMerge (map
|
||||
({ path, value }: {
|
||||
|
@@ -38,6 +38,7 @@ in
|
||||
"input" # for /dev/input/<xyz>: sxmo
|
||||
"networkmanager"
|
||||
"nixbuild"
|
||||
"transmission" # servo, to admin /var/lib/uninsane/media
|
||||
"video" # phosh/mobile. XXX colin: unsure if necessary
|
||||
"wheel"
|
||||
"wireshark"
|
||||
|
@@ -63,29 +63,13 @@ in
|
||||
"sway" => layered sway greeter. behaves as if you booted to swaylock.
|
||||
'';
|
||||
};
|
||||
sane.gui.sxmo.hooks = mkOption {
|
||||
sane.gui.sxmo.package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.runCommand "sxmo-hooks" { } ''
|
||||
mkdir -p $out
|
||||
ln -s ${pkgs.sxmo-utils}/share/sxmo/default_hooks $out/bin
|
||||
'';
|
||||
default = pkgs.sxmo-utils;
|
||||
description = ''
|
||||
hooks to make visible to sxmo.
|
||||
a hook is a script generally of the name sxmo_hook_<thing>.sh
|
||||
which is called by sxmo at key moments to proide user programmability.
|
||||
'';
|
||||
};
|
||||
sane.gui.sxmo.deviceHooks = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.runCommand "sxmo-device-hooks" { } ''
|
||||
mkdir -p $out
|
||||
ln -s ${pkgs.sxmo-utils}/share/sxmo/default_hooks/unknown $out/bin
|
||||
'';
|
||||
description = ''
|
||||
device-specific hooks to make visible to sxmo.
|
||||
this package supplies things like `sxmo_hook_inputhandler.sh`.
|
||||
a hook is a script generally of the name sxmo_hook_<thing>.sh
|
||||
which is called by sxmo at key moments to proide user programmability.
|
||||
sxmo base scripts and hooks collection.
|
||||
consider overriding the outputs under /share/sxmo/default_hooks
|
||||
to insert your own user scripts.
|
||||
'';
|
||||
};
|
||||
sane.gui.sxmo.terminal = mkOption {
|
||||
@@ -108,12 +92,29 @@ in
|
||||
'';
|
||||
};
|
||||
sane.gui.sxmo.settings = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = {};
|
||||
description = ''
|
||||
environment variables used to configure sxmo.
|
||||
e.g. SXMO_UNLOCK_IDLE_TIME or SXMO_VOLUME_BUTTON.
|
||||
'';
|
||||
type = types.submodule {
|
||||
freeformType = types.attrsOf types.str;
|
||||
options =
|
||||
let
|
||||
mkSettingsOpt = default: description: mkOption {
|
||||
inherit default description;
|
||||
type = types.nullOr types.str;
|
||||
};
|
||||
in {
|
||||
SXMO_BAR_SHOW_BAT_PER = mkSettingsOpt "1" "show battery percentage in statusbar";
|
||||
SXMO_UNLOCK_IDLE_TIME = mkSettingsOpt "300" "how many seconds of inactivity before locking the screen"; # lock -> screenoff happens 8s later, not configurable
|
||||
};
|
||||
};
|
||||
default = {};
|
||||
};
|
||||
sane.gui.sxmo.noidle = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "inhibit lock-on-idle and screenoff-on-idle";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -123,18 +124,25 @@ in
|
||||
package = null;
|
||||
suggestedPrograms = [
|
||||
"guiApps"
|
||||
"sfeed" # want this here so that the user's ~/.sfeed/sfeedrc gets created
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
{
|
||||
# TODO: lift to option declaration
|
||||
sane.gui.sxmo.settings.TERMCMD = lib.mkIf (cfg.terminal != null)
|
||||
(lib.mkDefault (if cfg.terminal == "vte" then "vte-2.91" else cfg.terminal));
|
||||
sane.gui.sxmo.settings.KEYBOARD = lib.mkIf (cfg.keyboard != null)
|
||||
(lib.mkDefault (if cfg.keyboard == "wvkbd" then "wvkbd-mobintl" else cfg.keyboard));
|
||||
}
|
||||
|
||||
(lib.mkIf cfg.enable {
|
||||
sane.programs.sxmoApps.enableFor.user.colin = true;
|
||||
|
||||
# some programs (e.g. fractal/nheko) **require** a "Secret Service Provider"
|
||||
services.gnome.gnome-keyring.enable = true;
|
||||
|
||||
# TODO: probably need to enable pipewire
|
||||
|
||||
networking.useDHCP = false;
|
||||
networking.networkmanager.enable = true;
|
||||
networking.wireless.enable = lib.mkForce false;
|
||||
@@ -146,10 +154,12 @@ in
|
||||
security.doas.enable = true;
|
||||
security.doas.wheelNeedsPassword = false;
|
||||
|
||||
# TODO: not all of these fonts seem to be mapped to the correct icon
|
||||
# TODO: nerdfonts is 4GB. it accepts an option to ship only some fonts: probably want to use that.
|
||||
fonts.fonts = [ pkgs.nerdfonts ];
|
||||
|
||||
# i believe sxmo recomments a different audio stack
|
||||
# sxmo has first-class support only for pulseaudio and alsa -- not pipewire.
|
||||
# however, pipewire can emulate pulseaudio support via `services.pipewire.pulse.enable = true`
|
||||
# after which the stock pulseaudio binaries magically work
|
||||
# administer with pw-cli, pw-mon, pw-top commands
|
||||
services.pipewire = {
|
||||
enable = true;
|
||||
@@ -160,45 +170,19 @@ in
|
||||
systemd.user.services."pipewire".wantedBy = [ "graphical-session.target" ];
|
||||
|
||||
# TODO: could use `displayManager.sessionPackages`?
|
||||
environment.systemPackages = with pkgs; [
|
||||
bc
|
||||
bemenu
|
||||
bonsai
|
||||
conky
|
||||
gojq
|
||||
inotify-tools
|
||||
jq
|
||||
libnotify
|
||||
lisgd
|
||||
mako
|
||||
superd
|
||||
sway
|
||||
swayidle
|
||||
sxmo-utils
|
||||
wob
|
||||
wvkbd
|
||||
xdg-user-dirs
|
||||
|
||||
# X11 only?
|
||||
xdotool
|
||||
|
||||
cfg.deviceHooks
|
||||
cfg.hooks
|
||||
environment.systemPackages = [
|
||||
cfg.package
|
||||
] ++ lib.optionals (cfg.terminal != null) [ pkgs."${cfg.terminal}" ]
|
||||
++ lib.optionals (cfg.keyboard != null) [ pkgs."${cfg.keyboard}" ];
|
||||
|
||||
environment.sessionVariables = {
|
||||
XDG_DATA_DIRS = [
|
||||
# TODO: only need the share/sxmo directly linked
|
||||
"${pkgs.sxmo-utils}/share"
|
||||
"${cfg.package}/share"
|
||||
];
|
||||
} // lib.optionalAttrs (cfg.terminal != null) {
|
||||
TERMCMD = lib.mkDefault (if cfg.terminal == "vte" then "vte-2.91" else cfg.terminal);
|
||||
} // lib.optionalAttrs (cfg.keyboard != null) {
|
||||
KEYBOARD = lib.mkDefault (if cfg.keyboard == "wvkbd" then "wvkbd-mobintl" else cfg.keyboard);
|
||||
} // cfg.settings;
|
||||
|
||||
sane.user.fs.".cache/sxmo/sxmo.noidle" = sane-lib.fs.wantedText "";
|
||||
sane.user.fs.".cache/sxmo/sxmo.noidle" = lib.mkIf cfg.noidle (sane-lib.fs.wantedText "");
|
||||
|
||||
|
||||
## greeter
|
||||
@@ -213,7 +197,7 @@ in
|
||||
'';
|
||||
|
||||
displayManager.sessionPackages = with pkgs; [
|
||||
sxmo-utils # this gets share/wayland-sessions/swmo.desktop linked
|
||||
cfg.package # this gets share/wayland-sessions/swmo.desktop linked
|
||||
];
|
||||
|
||||
# taken from gui/phosh:
|
||||
@@ -248,6 +232,15 @@ in
|
||||
in "${sway-as-greeter}/bin/sway-as-greeter";
|
||||
};
|
||||
|
||||
systemd.services."sxmo-set-permissions" = {
|
||||
description = "configure specific /sys and /dev nodes to be writable by sxmo scripts";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = "${cfg.package}/bin/sxmo_setpermissions.sh";
|
||||
};
|
||||
wantedBy = [ "display-manager.service" ];
|
||||
};
|
||||
|
||||
sane.fs."/var/log/sway" = lib.mkIf (cfg.greeter == "sway") {
|
||||
dir.acl.mode = "0777";
|
||||
wantedBeforeBy = [ "greetd.service" "display-manager.service" ];
|
||||
@@ -260,7 +253,7 @@ in
|
||||
# name = "sxmo";
|
||||
# desktopNames = [ "sxmo" ];
|
||||
# start = ''
|
||||
# ${pkgs.sxmo-utils}/bin/sxmo_xinit.sh &
|
||||
# ${cfg.package}/bin/sxmo_xinit.sh &
|
||||
# waitPID=$!
|
||||
# '';
|
||||
# }];
|
||||
@@ -270,7 +263,7 @@ in
|
||||
# enable = true;
|
||||
# settings = {
|
||||
# default_session = {
|
||||
# command = "${pkgs.sxmo-utils}/bin/sxmo_winit.sh";
|
||||
# command = "${cfg.package}/bin/sxmo_winit.sh";
|
||||
# user = "colin";
|
||||
# };
|
||||
# };
|
||||
|
@@ -11,6 +11,7 @@
|
||||
name = cfg.lan-ip;
|
||||
value = [ host ];
|
||||
}) config.sane.hosts.by-name)
|
||||
|
||||
(lib.mapAttrs' (host: cfg: {
|
||||
# -hn suffixed name for communication over my wg-home VPN.
|
||||
# hn = "home network"
|
||||
|
@@ -4,8 +4,14 @@ let
|
||||
inherit (lib) attrValues filterAttrs mkMerge mkOption types;
|
||||
cfg = config.sane.hosts;
|
||||
|
||||
host = types.submodule ({ config, ... }: {
|
||||
host = types.submodule ({ config, name, ... }: {
|
||||
options = {
|
||||
names = mkOption {
|
||||
type = types.listOf types.str;
|
||||
description = ''
|
||||
all names by which this host is reachable
|
||||
'';
|
||||
};
|
||||
ssh.user_pubkey = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
@@ -48,6 +54,11 @@ let
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
names = [ name ]
|
||||
++ lib.optional (config.wg-home.ip != null) "${name}-hn";
|
||||
};
|
||||
});
|
||||
in
|
||||
{
|
||||
|
@@ -17,7 +17,7 @@ in
|
||||
config = mkMerge [
|
||||
({
|
||||
sane.programs.docsets.config.rustPkgs = [
|
||||
"lemmy-server"
|
||||
# "lemmy-server"
|
||||
"mx-sanebot"
|
||||
];
|
||||
})
|
||||
|
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"bozo": 0,
|
||||
"content_length": 918085,
|
||||
"content_type": "application/xml; charset=utf-8",
|
||||
"description": "A show that cuts through all the political drivel and media misinformation to give you a straight take on one big news story of the week.",
|
||||
"favicon": "",
|
||||
"favicon_data_uri": "",
|
||||
"hubs": [],
|
||||
"is_podcast": true,
|
||||
"is_push": false,
|
||||
"item_count": 238,
|
||||
"last_updated": "2023-06-06T16:03:38+00:00",
|
||||
"score": 10,
|
||||
"self_url": "https://feeds.acast.com/public/shows/1d1223a2-9d05-473b-9e79-c2b65b71d676",
|
||||
"site_name": "",
|
||||
"site_url": "",
|
||||
"title": "Deconstructed",
|
||||
"url": "https://feeds.acast.com/public/shows/1d1223a2-9d05-473b-9e79-c2b65b71d676",
|
||||
"velocity": 0.123,
|
||||
"version": "rss20"
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"bozo": 0,
|
||||
"content_length": 1131706,
|
||||
"content_type": "application/xml; charset=utf-8",
|
||||
"description": "The people behind The Intercept\u2019s fearless reporting and incisive commentary discuss the crucial issues of our time.",
|
||||
"favicon": "",
|
||||
"favicon_data_uri": "",
|
||||
"hubs": [],
|
||||
"is_podcast": true,
|
||||
"is_push": false,
|
||||
"item_count": 261,
|
||||
"last_updated": "2023-06-07T09:30:43+00:00",
|
||||
"score": 10,
|
||||
"self_url": "https://feeds.acast.com/public/shows/f5b64019-68c3-57d4-b70b-043e63e5cbf6",
|
||||
"site_name": "",
|
||||
"site_url": "",
|
||||
"title": "Intercepted",
|
||||
"url": "https://feeds.acast.com/public/shows/f5b64019-68c3-57d4-b70b-043e63e5cbf6",
|
||||
"velocity": 0.111,
|
||||
"version": "rss20"
|
||||
}
|
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"bozo": 0,
|
||||
"content_length": 809084,
|
||||
"content_type": "application/xml+rss; charset=utf-8",
|
||||
"description": "A show that cuts through all the political drivel and media misinformation to give you a straight take on one big news story of the week.",
|
||||
"favicon": null,
|
||||
"hubs": [],
|
||||
"is_podcast": true,
|
||||
"is_push": false,
|
||||
"item_count": 217,
|
||||
"last_seen": "2023-01-11T13:40:50.240217+00:00",
|
||||
"last_updated": "2023-01-06T10:37:50+00:00",
|
||||
"score": 16,
|
||||
"self_url": "https://feeds.acast.com/public/shows/1d1223a2-9d05-473b-9e79-c2b65b71d676",
|
||||
"site_name": null,
|
||||
"site_url": null,
|
||||
"title": "Deconstructed",
|
||||
"url": "https://rss.prod.firstlook.media/deconstructed/podcast.rss",
|
||||
"velocity": 0.122,
|
||||
"version": "rss20"
|
||||
}
|
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"bozo": 0,
|
||||
"content_length": 1034995,
|
||||
"content_type": "application/xml+rss; charset=utf-8",
|
||||
"description": "The people behind The Intercept’s fearless reporting and incisive commentary discuss the crucial issues of our time.",
|
||||
"favicon": null,
|
||||
"hubs": [],
|
||||
"is_podcast": true,
|
||||
"is_push": false,
|
||||
"item_count": 243,
|
||||
"last_seen": "2023-01-11T14:04:41.283509+00:00",
|
||||
"last_updated": "2022-12-21T10:30:43+00:00",
|
||||
"score": 16,
|
||||
"self_url": "https://feeds.acast.com/public/shows/f5b64019-68c3-57d4-b70b-043e63e5cbf6",
|
||||
"site_name": null,
|
||||
"site_url": null,
|
||||
"title": "Intercepted",
|
||||
"url": "https://rss.prod.firstlook.media/intercepted/podcast.rss",
|
||||
"velocity": 0.112,
|
||||
"version": "rss20"
|
||||
}
|
@@ -2,6 +2,7 @@
|
||||
|
||||
{
|
||||
imports = [
|
||||
./dns.nix
|
||||
./feeds.nix
|
||||
./fs
|
||||
./ids.nix
|
||||
|
146
modules/dns.nix
Normal file
146
modules/dns.nix
Normal file
@@ -0,0 +1,146 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with builtins;
|
||||
let
|
||||
cfg = config.sane.dns;
|
||||
toml = pkgs.formats.toml { };
|
||||
recordFormatters = {
|
||||
# quote rules for zone files:
|
||||
# - any character may be encoded by `\DDD`, where `DDD` represents its ascii value in base 8.
|
||||
# - any non-digit `X` may be encoded by `\X`.
|
||||
# - stated in: <https://www.ietf.org/rfc/rfc1035.txt>: 5.1 Format
|
||||
# - visible in <trust-dns:crates/proto/src/serialize/txt/zone_lex.rs:escape_seq>
|
||||
# for us, we can just replace `\` => `\\ and `"` -> `\"`
|
||||
TXT = value: "\"" + (lib.escape [ "\\" "\"" ] value) + "\"";
|
||||
};
|
||||
# proto: "INET", etc
|
||||
# rrtype: "TXT", "A", "CNAME", etc
|
||||
fmtRecord = proto: rrtype: name: value:
|
||||
let
|
||||
formatter = recordFormatters."${rrtype}" or lib.id;
|
||||
in
|
||||
"${name}\t${proto}\t${rrtype}\t${formatter value}";
|
||||
fmtRecordList = proto: rrtype: name: values: concatStringsSep
|
||||
"\n"
|
||||
(map (fmtRecord proto rrtype name) values)
|
||||
;
|
||||
fmtRecordAttrs = proto: rrtype: rrAttrs:
|
||||
concatStringsSep
|
||||
"\n"
|
||||
(
|
||||
attrValues (
|
||||
mapAttrs
|
||||
(name: fmtRecordList proto rrtype name)
|
||||
rrAttrs
|
||||
)
|
||||
);
|
||||
# format other .zone files to include into this one
|
||||
fmtIncludes = paths: concatStringsSep
|
||||
"\n"
|
||||
(map (path: "$INCLUDE ${path}") paths);
|
||||
|
||||
genZone = zcfg: ''
|
||||
$TTL ${toString zcfg.TTL}
|
||||
${fmtRecordAttrs "IN" "SOA" zcfg.inet.SOA}
|
||||
${fmtRecordAttrs "IN" "A" zcfg.inet.A}
|
||||
${fmtRecordAttrs "IN" "CNAME" zcfg.inet.CNAME}
|
||||
${fmtRecordAttrs "IN" "MX" zcfg.inet.MX}
|
||||
${fmtRecordAttrs "IN" "NS" zcfg.inet.NS}
|
||||
${fmtRecordAttrs "IN" "SRV" zcfg.inet.SRV}
|
||||
${fmtRecordAttrs "IN" "TXT" zcfg.inet.TXT}
|
||||
${fmtIncludes zcfg.include}
|
||||
${zcfg.extraConfig}
|
||||
'';
|
||||
|
||||
# (listOf ty) type which also accepts single-assignment of `ty`.
|
||||
# it's used to allow the user to write:
|
||||
# CNAME."foo" = "bar";
|
||||
# as shorthand for
|
||||
# CNAME."foo" = [ "bar" ];
|
||||
listOrUnit = with lib; ty: types.coercedTo ty (elem: [ elem ]) (types.listOf ty);
|
||||
in
|
||||
{
|
||||
options = {
|
||||
sane.dns = with lib; {
|
||||
zones = mkOption {
|
||||
type = types.attrsOf (types.submodule {
|
||||
options = {
|
||||
name = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
description = "zone name. defaults to the attribute name in zones";
|
||||
default = null;
|
||||
};
|
||||
TTL = mkOption {
|
||||
type = types.int;
|
||||
description = "default TTL";
|
||||
default = 3600;
|
||||
};
|
||||
include = mkOption {
|
||||
type = types.listOf types.str;
|
||||
description = "paths of other zone files to $INCLUDE into this one";
|
||||
default = [];
|
||||
};
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
description = "extra lines to append to the zone file";
|
||||
default = "";
|
||||
};
|
||||
inet = {
|
||||
SOA = mkOption {
|
||||
type = types.attrsOf (listOrUnit types.str);
|
||||
description = "Start of Authority record(s)";
|
||||
default = {};
|
||||
};
|
||||
A = mkOption {
|
||||
type = types.attrsOf (listOrUnit types.str);
|
||||
description = "IPv4 address record(s)";
|
||||
default = {};
|
||||
};
|
||||
CNAME = mkOption {
|
||||
type = types.attrsOf (listOrUnit types.str);
|
||||
description = "canonical name record(s)";
|
||||
default = {};
|
||||
};
|
||||
MX = mkOption {
|
||||
type = types.attrsOf (listOrUnit types.str);
|
||||
description = "mail exchanger record(s)";
|
||||
default = {};
|
||||
};
|
||||
NS = mkOption {
|
||||
type = types.attrsOf (listOrUnit types.str);
|
||||
description = "name server record(s)";
|
||||
default = {};
|
||||
};
|
||||
SRV = mkOption {
|
||||
type = types.attrsOf (listOrUnit types.str);
|
||||
description = "service record(s)";
|
||||
default = {};
|
||||
};
|
||||
TXT = mkOption {
|
||||
type = types.attrsOf (listOrUnit types.str);
|
||||
description = "text record(s)";
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
|
||||
file = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
instead of using the generated zone file, use the specified path (user should populate the file specified here).
|
||||
'';
|
||||
};
|
||||
};
|
||||
});
|
||||
default = {};
|
||||
description = "Declarative zone config";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
sane.services.trust-dns.zones = mapAttrs (_name: zcfg: {
|
||||
text = genZone zcfg;
|
||||
}) cfg.zones;
|
||||
};
|
||||
}
|
@@ -25,7 +25,7 @@ lib.mkIf config.sane.persist.enable
|
||||
"nosuid"
|
||||
"allow_other"
|
||||
"passfile=${key}"
|
||||
"defaults"
|
||||
# "defaults" # "unknown flag: --defaults. Try 'gocryptfs -help'"
|
||||
];
|
||||
noCheck = true;
|
||||
};
|
||||
|
@@ -35,7 +35,7 @@ lib.mkIf config.sane.persist.enable
|
||||
"nodev"
|
||||
"nosuid"
|
||||
"quiet"
|
||||
"defaults"
|
||||
# "defaults" # "unknown flag: --defaults. Try 'gocryptfs -help'"
|
||||
];
|
||||
noCheck = true;
|
||||
};
|
||||
|
@@ -52,11 +52,17 @@ let
|
||||
};
|
||||
enableFor.user = mkOption {
|
||||
type = types.attrsOf types.bool;
|
||||
default = joinAttrsets (mapAttrsToList (otherName: otherPkg:
|
||||
optionalAttrs
|
||||
(otherName != name && elem name otherPkg.suggestedPrograms && otherPkg.enableSuggested)
|
||||
(filterAttrs (user: en: en) otherPkg.enableFor.user)
|
||||
) cfg);
|
||||
default =
|
||||
let
|
||||
suggestedBy = mapAttrsToList (otherName: otherPkg:
|
||||
optionalAttrs
|
||||
(otherName != name && elem name otherPkg.suggestedPrograms && otherPkg.enableSuggested)
|
||||
(filterAttrs (user: en: en) otherPkg.enableFor.user)
|
||||
) cfg;
|
||||
in
|
||||
# we can just // the attrs since each set is flat and the only value
|
||||
# each attr can have here is `true`, never `false`
|
||||
lib.foldl' (prev: next: prev // next) {} suggestedBy;
|
||||
description = ''
|
||||
place this program on the PATH for some specified user(s).
|
||||
'';
|
||||
|
@@ -7,50 +7,6 @@ with lib;
|
||||
let
|
||||
cfg = config.sane.services.trust-dns;
|
||||
toml = pkgs.formats.toml { };
|
||||
recordFormatters = {
|
||||
# quote rules for zone files:
|
||||
# - any character may be encoded by `\DDD`, where `DDD` represents its ascii value in base 8.
|
||||
# - any non-digit `X` may be encoded by `\X`.
|
||||
# - stated in: <https://www.ietf.org/rfc/rfc1035.txt>: 5.1 Format
|
||||
# - visible in <trust-dns:crates/proto/src/serialize/txt/zone_lex.rs:escape_seq>
|
||||
# for us, we can just replace `\` => `\\ and `"` -> `\"`
|
||||
TXT = value: "\"" + (lib.escape [ "\\" "\"" ] value) + "\"";
|
||||
};
|
||||
fmtRecord = proto: rrtype: name: value:
|
||||
let
|
||||
formatter = recordFormatters."${rrtype}" or lib.id;
|
||||
in
|
||||
"${name}\t${proto}\t${rrtype}\t${formatter value}";
|
||||
fmtRecordList = proto: rrtype: name: values: concatStringsSep
|
||||
"\n"
|
||||
(map (fmtRecord proto rrtype name) values)
|
||||
;
|
||||
fmtRecordAttrs = proto: rrtype: rrAttrs:
|
||||
concatStringsSep
|
||||
"\n"
|
||||
(
|
||||
attrValues (
|
||||
mapAttrs
|
||||
(name: fmtRecordList proto rrtype name)
|
||||
rrAttrs
|
||||
)
|
||||
);
|
||||
fmtIncludes = paths: concatStringsSep
|
||||
"\n"
|
||||
(map (path: "$INCLUDE ${path}") paths);
|
||||
|
||||
genZone = zcfg: ''
|
||||
$TTL ${toString zcfg.TTL}
|
||||
${fmtRecordAttrs "IN" "SOA" zcfg.inet.SOA}
|
||||
${fmtRecordAttrs "IN" "A" zcfg.inet.A}
|
||||
${fmtRecordAttrs "IN" "CNAME" zcfg.inet.CNAME}
|
||||
${fmtRecordAttrs "IN" "MX" zcfg.inet.MX}
|
||||
${fmtRecordAttrs "IN" "NS" zcfg.inet.NS}
|
||||
${fmtRecordAttrs "IN" "SRV" zcfg.inet.SRV}
|
||||
${fmtRecordAttrs "IN" "TXT" zcfg.inet.TXT}
|
||||
${fmtIncludes zcfg.include}
|
||||
${zcfg.extraConfig}
|
||||
'';
|
||||
|
||||
configFile = toml.generate "trust-dns.toml" {
|
||||
listen_addrs_ipv4 = cfg.listenAddrsIPv4;
|
||||
@@ -58,20 +14,10 @@ let
|
||||
mapAttrs (zname: zcfg: rec {
|
||||
zone = if zcfg.name == null then zname else zcfg.name;
|
||||
zone_type = "Primary";
|
||||
file = if zcfg.file == null then
|
||||
pkgs.writeText "${zone}.zone" (genZone zcfg)
|
||||
else
|
||||
zcfg.file;
|
||||
file = zcfg.file;
|
||||
}) cfg.zones
|
||||
);
|
||||
};
|
||||
|
||||
# (listOf ty) type which also accepts single-assignment of `ty`.
|
||||
# it's used to allow the user to write:
|
||||
# CNAME."foo" = "bar";
|
||||
# as shorthand for
|
||||
# CNAME."foo" = [ "bar" ];
|
||||
listOrUnit = ty: types.coercedTo ty (elem: [ elem ]) (types.listOf ty);
|
||||
in
|
||||
{
|
||||
options = {
|
||||
@@ -106,89 +52,37 @@ in
|
||||
};
|
||||
# reference <nixpkgs:nixos/modules/services/web-servers/nginx/vhost-options.nix>
|
||||
zones = mkOption {
|
||||
type = types.attrsOf (types.submodule {
|
||||
type = types.attrsOf (types.submodule ({ config, name, ... }: {
|
||||
options = {
|
||||
name = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
description = "zone name. defaults to the attribute name in zones";
|
||||
default = name;
|
||||
};
|
||||
text = mkOption {
|
||||
type = types.nullOr types.lines;
|
||||
default = null;
|
||||
};
|
||||
TTL = mkOption {
|
||||
type = types.int;
|
||||
description = "default TTL";
|
||||
default = 3600;
|
||||
};
|
||||
include = mkOption {
|
||||
type = types.listOf types.str;
|
||||
description = "paths of other zone files to $INCLUDE into this one";
|
||||
default = [];
|
||||
};
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
description = "extra lines to append to the zone file";
|
||||
default = "";
|
||||
};
|
||||
inet = {
|
||||
SOA = mkOption {
|
||||
type = types.attrsOf (listOrUnit types.str);
|
||||
description = "Start of Authority record(s)";
|
||||
default = {};
|
||||
};
|
||||
A = mkOption {
|
||||
type = types.attrsOf (listOrUnit types.str);
|
||||
description = "IPv4 address record(s)";
|
||||
default = {};
|
||||
};
|
||||
CNAME = mkOption {
|
||||
type = types.attrsOf (listOrUnit types.str);
|
||||
description = "canonical name record(s)";
|
||||
default = {};
|
||||
};
|
||||
MX = mkOption {
|
||||
type = types.attrsOf (listOrUnit types.str);
|
||||
description = "mail exchanger record(s)";
|
||||
default = {};
|
||||
};
|
||||
NS = mkOption {
|
||||
type = types.attrsOf (listOrUnit types.str);
|
||||
description = "name server record(s)";
|
||||
default = {};
|
||||
};
|
||||
SRV = mkOption {
|
||||
type = types.attrsOf (listOrUnit types.str);
|
||||
description = "service record(s)";
|
||||
default = {};
|
||||
};
|
||||
TXT = mkOption {
|
||||
type = types.attrsOf (listOrUnit types.str);
|
||||
description = "text record(s)";
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
|
||||
file = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
type = types.nullOr (types.either types.path types.str);
|
||||
description = ''
|
||||
instead of using the generated zone file, use the specified path (user should populate the file specified here).
|
||||
path to a .zone file.
|
||||
if omitted, will be generated from the `text` option.
|
||||
'';
|
||||
};
|
||||
};
|
||||
});
|
||||
|
||||
config = {
|
||||
file = lib.mkIf (config.text != null) (pkgs.writeText "${config.name}.zone" config.text);
|
||||
};
|
||||
}));
|
||||
default = {};
|
||||
description = "Declarative zone config";
|
||||
};
|
||||
|
||||
generatedZones = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
description = "generated zone text for each zone";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
sane.services.trust-dns.generatedZones = mapAttrs (zone: zcfg: genZone zcfg) cfg.zones;
|
||||
|
||||
sane.ports.ports."53" = {
|
||||
protocol = [ "udp" "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
|
31
nixpatches/2023-06-02-qt6-qtwebengine-cross.patch
Normal file
31
nixpatches/2023-06-02-qt6-qtwebengine-cross.patch
Normal file
@@ -0,0 +1,31 @@
|
||||
diff --git a/pkgs/development/libraries/qt-6/modules/qtwebengine.nix b/pkgs/development/libraries/qt-6/modules/qtwebengine.nix
|
||||
index fadbc5d2bfa..e4f2aec5a32 100644
|
||||
--- a/pkgs/development/libraries/qt-6/modules/qtwebengine.nix
|
||||
+++ b/pkgs/development/libraries/qt-6/modules/qtwebengine.nix
|
||||
@@ -97,6 +97,9 @@
|
||||
, xnu
|
||||
}:
|
||||
|
||||
+let
|
||||
+ buildPython = buildPackages.python3.withPackages (ps: with ps; [ html5lib ]);
|
||||
+in
|
||||
qtModule {
|
||||
pname = "qtwebengine";
|
||||
qtInputs = [ qtdeclarative qtwebchannel qtwebsockets qtpositioning ];
|
||||
@@ -108,7 +111,7 @@ qtModule {
|
||||
gperf
|
||||
ninja
|
||||
pkg-config
|
||||
- (python3.withPackages (ps: with ps; [ html5lib ]))
|
||||
+ buildPython
|
||||
which
|
||||
gn
|
||||
nodejs
|
||||
@@ -304,6 +307,7 @@ qtModule {
|
||||
|
||||
preConfigure = ''
|
||||
export NINJAFLAGS="-j$NIX_BUILD_CORES"
|
||||
+ export CMAKE_PREFIX_PATH="${buildPython}/bin:$CMAKE_PREFIX_PATH"
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
@@ -0,0 +1,60 @@
|
||||
diff --git a/pkgs/applications/video/jellyfin-media-player/default.nix b/pkgs/applications/video/jellyfin-media-player/default.nix
|
||||
index e781f80e455..d1990294141 100644
|
||||
--- a/pkgs/applications/video/jellyfin-media-player/default.nix
|
||||
+++ b/pkgs/applications/video/jellyfin-media-player/default.nix
|
||||
@@ -1,7 +1,6 @@
|
||||
{ lib
|
||||
, fetchFromGitHub
|
||||
, fetchzip
|
||||
-, mkDerivation
|
||||
, stdenv
|
||||
, Cocoa
|
||||
, CoreAudio
|
||||
@@ -12,21 +11,20 @@
|
||||
, libGL
|
||||
, libX11
|
||||
, libXrandr
|
||||
+, libsForQt5
|
||||
, libvdpau
|
||||
, mpv
|
||||
, ninja
|
||||
, pkg-config
|
||||
, python3
|
||||
-, qtbase
|
||||
-, qtwayland
|
||||
-, qtwebchannel
|
||||
-, qtwebengine
|
||||
-, qtx11extras
|
||||
, jellyfin-web
|
||||
, withDbus ? stdenv.isLinux, dbus
|
||||
}:
|
||||
|
||||
-mkDerivation rec {
|
||||
+let
|
||||
+ inherit (libsForQt5) qtbase qtwayland qtwebchannel qtwebengine qtx11extras wrapQtAppsHook;
|
||||
+in
|
||||
+stdenv.mkDerivation rec {
|
||||
pname = "jellyfin-media-player";
|
||||
version = "1.9.1";
|
||||
|
||||
@@ -69,6 +67,7 @@ mkDerivation rec {
|
||||
ninja
|
||||
pkg-config
|
||||
python3
|
||||
+ wrapQtAppsHook
|
||||
];
|
||||
|
||||
cmakeFlags = [
|
||||
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
|
||||
index eb309c9b283..d8a718db698 100644
|
||||
--- a/pkgs/top-level/all-packages.nix
|
||||
+++ b/pkgs/top-level/all-packages.nix
|
||||
@@ -5289,7 +5289,7 @@ with pkgs;
|
||||
|
||||
jellyfin-ffmpeg = callPackage ../development/libraries/jellyfin-ffmpeg { };
|
||||
|
||||
- jellyfin-media-player = libsForQt5.callPackage ../applications/video/jellyfin-media-player {
|
||||
+ jellyfin-media-player = callPackage ../applications/video/jellyfin-media-player {
|
||||
inherit (darwin.apple_sdk.frameworks) CoreFoundation Cocoa CoreAudio MediaPlayer;
|
||||
# Disable pipewire to avoid segfault, see https://github.com/jellyfin/jellyfin-media-player/issues/341
|
||||
mpv = wrapMpv (mpv-unwrapped.override { pipewireSupport = false; }) { };
|
@@ -1,15 +1,15 @@
|
||||
diff --git a/pkgs/servers/web-apps/lemmy/pin.json b/pkgs/servers/web-apps/lemmy/pin.json
|
||||
index b2a1f1923ce..621b5945b6b 100644
|
||||
index 5b7b9aa49a5..6cd30d294d8 100644
|
||||
--- a/pkgs/servers/web-apps/lemmy/pin.json
|
||||
+++ b/pkgs/servers/web-apps/lemmy/pin.json
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
- "version": "0.17.2",
|
||||
- "serverSha256": "sha256-fkpMVm52XLyrk9RfzJpthT8fctIilawAIgfK+4TXHvU=",
|
||||
- "serverCargoSha256": "sha256-AC6EP612uaeGfqHbrHrz89h0tsNlMceEg6GxEsm1QMA=",
|
||||
- "version": "0.17.4",
|
||||
- "serverSha256": "sha256-nztT6o5Tur64dMWII+wf5CBVJBJ59MGXKdS5OJO0SSc=",
|
||||
- "serverCargoSha256": "sha256-3In2W+cSVtMkaKrn1hWOVL/V/qkKlH30qGPi3rNdpQI=",
|
||||
+ "version": "88a0d2feec3f9b4a06f2d8d090894111afcbd9e2",
|
||||
+ "serverSha256": "sha256-jVa7SckpH21TG+i1yjJOkhEgjnZ0Zgk2IUP7sCdtv1Y=",
|
||||
+ "serverCargoSha256": "sha256-trp/TCGtAtZlKdZk2CaJ3E9Lj95cq797PLWUF/DD6/M=",
|
||||
"uiSha256": "sha256-0Zhm6Jgc6rlN4c7ryRnR45+fZEdzQhuOXSwU8Wz0D5g=",
|
||||
"uiSha256": "sha256-Ebc4VzuCJhPoO16qCgSVyYFXH7YcymxcGcN/Sgyg5Gs=",
|
||||
"uiYarnDepsSha256": "sha256-aZAclSaFZJvuK+FpCBWboGaVEOEJTxq2jnWk0A6iAFw="
|
||||
}
|
@@ -20,6 +20,24 @@ let
|
||||
);
|
||||
in [
|
||||
|
||||
# (fetchpatch' {
|
||||
# # XXX: doesn't cleanly apply; fetch `firefox-pmos-mobile` branch from my git instead
|
||||
# title = "firefox-pmos-mobile: init at -pmos-2.2.0";
|
||||
# prUrl = "https://github.com/NixOS/nixpkgs/pull/121356";
|
||||
# hash = "sha256-eDsR1cJC/IMmhJl5wERpTB1VGawcnMw/gck9sI64GtQ=";
|
||||
# })
|
||||
|
||||
(fetchpatch' {
|
||||
saneCommit = "70c12451b783d6310ab90229728d63e8a903c8cb";
|
||||
title = "firefox-pmos-mobile: init at -pmos-2.2.0";
|
||||
hash = "sha256-o67YRjo31raaYhIpfqQP/tdjbXrjeLLhEr/qzqyPLgQ=";
|
||||
})
|
||||
(fetchpatch' {
|
||||
saneCommit = "f0ed1651158c33504fbd2e04db497d5504dd8570";
|
||||
title = "librewolf-pmos-mobile: init";
|
||||
hash = "sha256-oQEM3EZfAOmfZzDu9faCqyOFZsdHYGn1mVBgkxt68Zg=";
|
||||
})
|
||||
|
||||
# splatmoji: init at 1.2.0
|
||||
(fetchpatch' {
|
||||
saneCommit = "75149039b6eaf57d8a92164e90aab20eb5d89196";
|
||||
@@ -52,38 +70,12 @@ in [
|
||||
# TODO: why doesn't this apply?
|
||||
# ./2023-03-04-ccache-cross-fix.patch
|
||||
|
||||
# 2023-04-11: bambu-studio: init at unstable-2023-01-11
|
||||
# 2023-04-11: bambu-studio: init at 01.06.02.04
|
||||
(fetchpatch' {
|
||||
prUrl = "https://github.com/NixOS/nixpkgs/pull/206495";
|
||||
hash = "sha256-RbQzAtFTr7Nrk2YBcHpKQMYoPlFMVSXNl96B/lkKluQ=";
|
||||
hash = "sha256-jl6SZwSDhQTlpM5FyGaFU/svwTb1ySdKtvWMgsneq3A=";
|
||||
})
|
||||
|
||||
# update to newer lemmy-server.
|
||||
# should be removable when > 0.17.2 releases?
|
||||
# removing this now causes:
|
||||
# INFO lemmy_server::code_migrations: No Local Site found, creating it.
|
||||
# Error: LemmyError { message: None, inner: duplicate key value violates unique constraint "local_site_site_id_key", context: "SpanTrace" }
|
||||
# though perhaps this error doesn't occur on fresh databases (idk).
|
||||
./2023-04-29-lemmy.patch
|
||||
|
||||
(fetchpatch' {
|
||||
title = "cargo-docset: init at 0.3.1";
|
||||
saneCommit = "5a09e84c6159ce545029483384580708bc04c08f";
|
||||
prUrl = "https://github.com/NixOS/nixpkgs/pull/231188";
|
||||
hash = "sha256-Z1HOps3w/WvxAiyUAHWszKqwS9EwA6rf4XfgPGp+2sQ=";
|
||||
})
|
||||
|
||||
(fetchpatch' {
|
||||
title = "nixos/lemmy: support nginx";
|
||||
saneCommit = "4c86db6dcb78795ac9bb514d9c779fd591070b23";
|
||||
hash = "sha256-G7jGhSPUp9BMxh2yTzo0KUUVabMJeZ28YTA+0iPldRI=";
|
||||
})
|
||||
|
||||
(fetchpatch' {
|
||||
title = "feedbackd: 0.1.0 -> 0.2.0";
|
||||
saneCommit = "a0186a5782708a640cd6eaad6e9742b9cccebe9d";
|
||||
hash = "sha256-f8he7pQow4fZkTVVqU/A5KgovZA7m7MccRQNTnDxw5o=";
|
||||
})
|
||||
# (fetchpatch' {
|
||||
# # phoc: 0.25.0 -> 0.27.0
|
||||
# # TODO: move wayland-scanner & glib to nativeBuildInputs
|
||||
@@ -153,6 +145,55 @@ in [
|
||||
# make alsa-project members overridable
|
||||
./2023-05-31-toplevel-alsa.patch
|
||||
|
||||
# qt6 qtwebengine: specify `python` as buildPackages
|
||||
./2023-06-02-qt6-qtwebengine-cross.patch
|
||||
|
||||
# Jellyfin: don't build via `libsForQt5.callPackage`
|
||||
./2023-06-06-jellyfin-no-libsForQt5-callPackage.patch
|
||||
|
||||
# pin to a pre-0.17.3 release
|
||||
# removing this and using stock 0.17.3 causes:
|
||||
# INFO lemmy_server::code_migrations: No Local Site found, creating it.
|
||||
# Error: LemmyError { message: None, inner: duplicate key value violates unique constraint "local_site_site_id_key", context: "SpanTrace" }
|
||||
# more specifically, lemmy can't find the site because it receives an error from diesel:
|
||||
# Err(DeserializationError("Unrecognized enum variant"))
|
||||
# this is likely some mis-ordered db migrations
|
||||
# or perhaps the whole set of migrations here isn't being running right.
|
||||
# related: <https://github.com/NixOS/nixpkgs/issues/236890#issuecomment-1585030861>
|
||||
./2023-06-10-lemmy-downgrade.patch
|
||||
|
||||
# (fetchpatch' {
|
||||
# title = "gpodder: wrap with missing `xdg-utils` path";
|
||||
# saneCommit = "10d0ac11bc083cbcf0d6340950079b3888095abf";
|
||||
# hash = "sha256-cu8L30ZiUJnWFGRR/SK917TC7TalzpGkurGkUAAxl54=";
|
||||
# })
|
||||
|
||||
(fetchpatch' {
|
||||
title = "sequoia: 0.28.0 -> 0.30.1";
|
||||
prUrl = "https://github.com/NixOS/nixpkgs/pull/237698";
|
||||
saneCommit = "71f47689d11e09b6ff70cbd4238e386b50d46899";
|
||||
hash = "sha256-cadnRzZ0sjwdSc845zFtgYzLrsPGsZ9ShELibvQWLUU=";
|
||||
})
|
||||
|
||||
(fetchpatch' {
|
||||
title = "koreader: 2023.04 -> 2023.05.1";
|
||||
saneCommit = "a5c471bd263abe93e291239e0078ac4255a94262";
|
||||
hash = "sha256-m++Vv/FK7cxONCz6n0MLO3CiKNrRH0ttFmoC1Xmba+A=";
|
||||
})
|
||||
|
||||
(fetchpatch' {
|
||||
title = "mepo: 1.1 -> 1.1.2";
|
||||
saneCommit = "eee68d7146a6cd985481cdd8bca52ffb204de423";
|
||||
hash = "sha256-0lNSgq8ahSvQDEpuF0lyblA8cB9ulv1zGasHo6lUWAU=";
|
||||
})
|
||||
|
||||
# (fetchpatch' {
|
||||
# # N.B.: compiles, but runtime error on launch suggestive of some module not being shipped
|
||||
# title = "matrix-appservice-irc: 0.38.0 -> 1.0.0";
|
||||
# saneCommit = "b168bf862d53535151b9142a15fbd53e18e688c5";
|
||||
# hash = "sha256-dDa2mrCJ416PIYsDH9ya/4aQdqtp4BwzIisa8HdVFxo=";
|
||||
# })
|
||||
|
||||
# for raspberry pi: allow building u-boot for rpi 4{,00}
|
||||
# TODO: remove after upstreamed: https://github.com/NixOS/nixpkgs/pull/176018
|
||||
# (it's a dupe of https://github.com/NixOS/nixpkgs/pull/112677 )
|
||||
|
@@ -82,11 +82,12 @@ in {
|
||||
ibus # "error: cannot run test program while cross compiling"
|
||||
jellyfin-web # in node-dependencies-jellyfin-web: "node: command not found" (nodePackages don't cross compile)
|
||||
# libgccjit # "../../gcc-9.5.0/gcc/jit/jit-result.c:52:3: error: 'dlclose' was not declared in this scope" (needed by emacs!)
|
||||
# libsForQt5 # qtbase # make: g++: No such file or directory
|
||||
# libsForQt5 # if we emulate qt5, we're better off emulating libsForQt5 else qt complains about multiple versions of qtbase
|
||||
mepo # /build/source/src/sdlshim.zig:1:20: error: C import failed
|
||||
perlInterpreters # perl5.36.0-Module-Build perl5.36.0-Test-utf8 (see tracking issues ^)
|
||||
# qgnomeplatform
|
||||
# qtbase
|
||||
qt5 # qt5.qtx11extras fails, but we can't selectively emulate it
|
||||
# qt5 # qt5.qtbase, qt5.qtx11extras fails, but we can't selectively emulate them.
|
||||
# qt6 # "You need to set QT_HOST_PATH to cross compile Qt."
|
||||
# sequoia # "/nix/store/q8hg17w47f9xr014g36rdc2gi8fv02qc-clang-aarch64-unknown-linux-gnu-12.0.1-lib/lib/libclang.so.12: cannot open shared object file: No such file or directory"', /build/sequoia-0.27.0-vendor.tar.gz/bindgen/src/lib.rs:1975:31"
|
||||
# splatmoji
|
||||
@@ -247,6 +248,14 @@ in {
|
||||
nativeBuildInputs = upstream.nativeBuildInputs ++ [ final.git ];
|
||||
});
|
||||
|
||||
cozy = prev.cozy.override {
|
||||
cozy = prev.cozy.upstream.cozy.override {
|
||||
# fixes runtime error: "Settings schema 'org.gtk.Settings.FileChooser' is not installed"
|
||||
# otherwise gtk3+ schemas aren't added to XDG_DATA_DIRS
|
||||
inherit (emulated) wrapGAppsHook;
|
||||
};
|
||||
};
|
||||
|
||||
dante = prev.dante.override {
|
||||
# fixes: "configure: error: error: getaddrinfo() error value count too low"
|
||||
inherit (emulated) stdenv;
|
||||
@@ -508,6 +517,13 @@ in {
|
||||
}
|
||||
super.nautilus
|
||||
).override {
|
||||
# fixes -msse2, -mfpmath=sse flags
|
||||
# wrapGAppsHook4 = final.wrapGAppsHook;
|
||||
# fixes -msse2, -mfpmath=ssh flags AND "Settings schema 'org.gtk.gtk4.Settings.FileChooser' is not installed"
|
||||
wrapGAppsHook4 = emulated.wrapGAppsHook4;
|
||||
};
|
||||
|
||||
zenity = super.zenity.override {
|
||||
# fixes -msse2, -mfpmath=sse flags
|
||||
wrapGAppsHook4 = final.wrapGAppsHook;
|
||||
};
|
||||
@@ -647,12 +663,21 @@ in {
|
||||
};
|
||||
};
|
||||
|
||||
jellyfin-media-player = prev.jellyfin-media-player.overrideAttrs (upstream: {
|
||||
meta = upstream.meta // {
|
||||
platforms = upstream.meta.platforms ++ [
|
||||
"aarch64-linux"
|
||||
];
|
||||
};
|
||||
jellyfin-media-player = mvToBuildInputs
|
||||
[ final.libsForQt5.wrapQtAppsHook ] # this shouldn't be: but otherwise we get mixed qtbase deps
|
||||
(prev.jellyfin-media-player.overrideAttrs (upstream: {
|
||||
meta = upstream.meta // {
|
||||
platforms = upstream.meta.platforms ++ [
|
||||
"aarch64-linux"
|
||||
];
|
||||
};
|
||||
}));
|
||||
jellyfin-media-player-qt6 = prev.jellyfin-media-player-qt6.overrideAttrs (upstream: {
|
||||
# nativeBuildInputs => result targets x86.
|
||||
# buildInputs => result targets correct platform, but doesn't wrap the runtime deps
|
||||
# TODO: fix the hook in qt6 itself?
|
||||
depsHostHost = upstream.depsHostHost or [] ++ [ final.qt6.wrapQtAppsHook ];
|
||||
nativeBuildInputs = lib.remove [ final.qt6.wrapQtAppsHook ] upstream.nativeBuildInputs;
|
||||
});
|
||||
# jellyfin-web = prev.jellyfin-web.override {
|
||||
# # in node-dependencies-jellyfin-web: "node: command not found"
|
||||
@@ -670,6 +695,18 @@ in {
|
||||
./kitty-no-docs.patch
|
||||
];
|
||||
});
|
||||
komikku = prev.komikku.override {
|
||||
# GI_TYPELIB_PATH points to x86_64 types in the default build, only when using wrapGAppsHook4
|
||||
wrapGAppsHook4 = final.wrapGAppsHook;
|
||||
};
|
||||
koreader = (prev.koreader.override {
|
||||
# fixes runtime error: luajit: ./ffi/util.lua:757: attempt to call field 'pack' (a nil value)
|
||||
inherit (emulated) luajit;
|
||||
}).overrideAttrs (upstream: {
|
||||
nativeBuildInputs = upstream.nativeBuildInputs ++ [
|
||||
final.autoPatchelfHook
|
||||
];
|
||||
});
|
||||
libgweather = rmNativeBuildInputs [ final.glib ] (prev.libgweather.override {
|
||||
# alternative to emulating python3 is to specify it in `buildInputs` instead of `nativeBuildInputs` (upstream),
|
||||
# but presumably that's just a different way to emulate it.
|
||||
@@ -689,18 +726,51 @@ in {
|
||||
# buildInputs = upstream.buildInputs ++ [ final.vala ];
|
||||
# });
|
||||
|
||||
libsForQt5 = prev.libsForQt5.overrideScope' (self: super: {
|
||||
qgpgme = super.qgpgme.overrideAttrs (orig: {
|
||||
# fix so it can find the MOC compiler
|
||||
# it looks like it might not *need* to propagate qtbase, but so far unclear
|
||||
nativeBuildInputs = orig.nativeBuildInputs ++ [ self.qtbase ];
|
||||
propagatedBuildInputs = lib.remove self.qtbase orig.propagatedBuildInputs;
|
||||
});
|
||||
phonon = super.phonon.overrideAttrs (orig: {
|
||||
# fixes "ECM (required version >= 5.60), Extra CMake Modules"
|
||||
buildInputs = orig.buildInputs ++ [ final.extra-cmake-modules ];
|
||||
});
|
||||
});
|
||||
# libsForQt5 = prev.libsForQt5.overrideScope' (self: super: {
|
||||
# qgpgme = super.qgpgme.overrideAttrs (orig: {
|
||||
# # fix so it can find the MOC compiler
|
||||
# # it looks like it might not *need* to propagate qtbase, but so far unclear
|
||||
# nativeBuildInputs = orig.nativeBuildInputs ++ [ self.qtbase ];
|
||||
# propagatedBuildInputs = lib.remove self.qtbase orig.propagatedBuildInputs;
|
||||
# });
|
||||
# phonon = super.phonon.overrideAttrs (orig: {
|
||||
# # fixes "ECM (required version >= 5.60), Extra CMake Modules"
|
||||
# buildInputs = orig.buildInputs ++ [ final.extra-cmake-modules ];
|
||||
# });
|
||||
# });
|
||||
# libsForQt5 = prev.libsForQt5.overrideScope' (self: super: {
|
||||
# # emulate all the qt5 packages, but rework `libsForQt5.callPackage` and `mkDerivation`
|
||||
# # to use non-emulated stdenv by default.
|
||||
# mkDerivation = self.mkDerivationWith final.stdenv.mkDerivation;
|
||||
# callPackage = self.newScope { inherit (self) qtCompatVersion qtModule srcs; inherit (final) stdenv; };
|
||||
# });
|
||||
|
||||
# mepo = (prev.mepo.override {
|
||||
# inherit (emulated)
|
||||
# stdenv
|
||||
# SDL2
|
||||
# SDL2_gfx
|
||||
# SDL2_image
|
||||
# SDL2_ttf
|
||||
# zig
|
||||
# ;
|
||||
# }).overrideAttrs (_upstream: {
|
||||
# doCheck = false;
|
||||
# # dontConfigure = true;
|
||||
# # dontBuild = true;
|
||||
# # preInstall = ''
|
||||
# # export HOME=$TMPDIR
|
||||
# # '';
|
||||
# # installPhase = ''
|
||||
# # runHook preInstall
|
||||
|
||||
# # zig build -Drelease-safe=true -Dtarget=aarch64-linux-gnu -Dcpu=baseline --prefix $out
|
||||
# # install -d $out/share/man/man1
|
||||
# # $out/bin/mepo -docman > $out/share/man/man1/mepo.1
|
||||
|
||||
# # runHook postInstall
|
||||
# # '';
|
||||
# });
|
||||
|
||||
# fixes: "ar: command not found"
|
||||
# `ar` is provided by bintools
|
||||
@@ -971,34 +1041,106 @@ in {
|
||||
# inherit (emulated.qt5) qtModule;
|
||||
# };
|
||||
# });
|
||||
# qt6 = prev.qt6.overrideScope' (self: super: {
|
||||
# # inherit (emulated.qt6) qtModule;
|
||||
# qtbase = super.qtbase.overrideAttrs (upstream: {
|
||||
# # cmakeFlags = upstream.cmakeFlags ++ lib.optionals (final.stdenv.buildPlatform != final.stdenv.hostPlatform) [
|
||||
# cmakeFlags = upstream.cmakeFlags ++ lib.optionals (final.stdenv.buildPlatform != final.stdenv.hostPlatform) [
|
||||
# # "-DCMAKE_CROSSCOMPILING=True" # fails to solve QT_HOST_PATH error
|
||||
# "-DQT_HOST_PATH=${final.buildPackages.qt6.full}"
|
||||
# ];
|
||||
# });
|
||||
# qtModule = args: (super.qtModule args).overrideAttrs (upstream: {
|
||||
# # the nixpkgs comment about libexec seems to be outdated:
|
||||
# # it's just that cross-compiled syncqt.pl doesn't get its #!/usr/bin/env shebang replaced.
|
||||
# preConfigure = lib.replaceStrings
|
||||
# ["${lib.getDev self.qtbase}/libexec/syncqt.pl"]
|
||||
# ["perl ${lib.getDev self.qtbase}/libexec/syncqt.pl"]
|
||||
# upstream.preConfigure;
|
||||
# });
|
||||
# # qtwayland = super.qtwayland.overrideAttrs (upstream: {
|
||||
# # preConfigure = "fixQtBuiltinPaths . '*.pr?'";
|
||||
# # });
|
||||
# # qtwayland = super.qtwayland.override {
|
||||
# # inherit (self) qtbase;
|
||||
# # };
|
||||
# # qtbase = super.qtbase.override {
|
||||
# # # fixes: "You need to set QT_HOST_PATH to cross compile Qt."
|
||||
# # inherit (emulated) stdenv;
|
||||
# # };
|
||||
# });
|
||||
qt5 = emulated.qt5.overrideScope' (self: super: {
|
||||
# emulate all the qt5 packages, but rework `libsForQt5.callPackage` and `mkDerivation`
|
||||
# to use non-emulated stdenv by default.
|
||||
mkDerivation = self.mkDerivationWith final.stdenv.mkDerivation;
|
||||
callPackage = self.newScope { inherit (self) qtCompatVersion qtModule srcs; inherit (final) stdenv; };
|
||||
});
|
||||
qt6 = prev.qt6.overrideScope' (self: super: {
|
||||
# # inherit (emulated.qt6) qtModule;
|
||||
# qtbase = super.qtbase.overrideAttrs (upstream: {
|
||||
# # cmakeFlags = upstream.cmakeFlags ++ lib.optionals (final.stdenv.buildPlatform != final.stdenv.hostPlatform) [
|
||||
# cmakeFlags = upstream.cmakeFlags ++ lib.optionals (final.stdenv.buildPlatform != final.stdenv.hostPlatform) [
|
||||
# # "-DCMAKE_CROSSCOMPILING=True" # fails to solve QT_HOST_PATH error
|
||||
# "-DQT_HOST_PATH=${final.buildPackages.qt6.full}"
|
||||
# ];
|
||||
# });
|
||||
# qtModule = args: (super.qtModule args).overrideAttrs (upstream: {
|
||||
# # the nixpkgs comment about libexec seems to be outdated:
|
||||
# # it's just that cross-compiled syncqt.pl doesn't get its #!/usr/bin/env shebang replaced.
|
||||
# preConfigure = lib.replaceStrings
|
||||
# ["${lib.getDev self.qtbase}/libexec/syncqt.pl"]
|
||||
# ["perl ${lib.getDev self.qtbase}/libexec/syncqt.pl"]
|
||||
# upstream.preConfigure;
|
||||
# });
|
||||
# # qtwayland = super.qtwayland.overrideAttrs (upstream: {
|
||||
# # preConfigure = "fixQtBuiltinPaths . '*.pr?'";
|
||||
# # });
|
||||
# # qtwayland = super.qtwayland.override {
|
||||
# # inherit (self) qtbase;
|
||||
# # };
|
||||
# # qtbase = super.qtbase.override {
|
||||
# # # fixes: "You need to set QT_HOST_PATH to cross compile Qt."
|
||||
# # inherit (emulated) stdenv;
|
||||
# # };
|
||||
|
||||
qtwebengine = super.qtwebengine.overrideAttrs (upstream: {
|
||||
# depsBuildBuild = upstream.depsBuildBuild or [] ++ [ final.pkg-config ];
|
||||
# XXX: qt seems to use its own terminology for "host" and "target":
|
||||
# - <https://www.qt.io/blog/qt6-development-hosts-and-targets>
|
||||
# - "host" = machine invoking the compiler
|
||||
# - "target" = machine on which the resulting qtwebengine.so binaries will run
|
||||
# XXX: NIX_CFLAGS_COMPILE_<machine> is how we get the `-isystem <dir>` flags.
|
||||
# probably we shouldn't blindly copy these from host machine to build machine,
|
||||
# as the headers could reasonably make different assumptions.
|
||||
preConfigure = upstream.preConfigure + ''
|
||||
# export PKG_CONFIG_HOST="$PKG_CONFIG"
|
||||
export PKG_CONFIG_HOST="$PKG_CONFIG_FOR_BUILD"
|
||||
# expose -isystem <zlib> to x86 builds
|
||||
export NIX_CFLAGS_COMPILE_x86_64_unknown_linux_gnu="$NIX_CFLAGS_COMPILE"
|
||||
export NIX_LDFLAGS_x86_64_unknown_linux_gnu="-L${final.buildPackages.zlib}/lib"
|
||||
'';
|
||||
patches = upstream.patches or [] ++ [
|
||||
# ./qtwebengine-host-pkg-config.patch
|
||||
# alternatively, look at dlopenBuildInputs
|
||||
./qtwebengine-host-cc.patch
|
||||
];
|
||||
# patch the qt pkg-config script to show us more debug info
|
||||
postPatch = upstream.postPatch or "" + ''
|
||||
sed -i s/options.debug/True/g src/3rdparty/chromium/build/config/linux/pkg-config.py
|
||||
'';
|
||||
nativeBuildInputs = upstream.nativeBuildInputs ++ [
|
||||
final.bintools-unwrapped # for readelf
|
||||
final.buildPackages.cups # for cups-config
|
||||
final.buildPackages.fontconfig
|
||||
final.buildPackages.glib
|
||||
final.buildPackages.harfbuzz
|
||||
final.buildPackages.icu
|
||||
final.buildPackages.libjpeg
|
||||
final.buildPackages.libpng
|
||||
final.buildPackages.libwebp
|
||||
final.buildPackages.nss
|
||||
# final.gcc-unwrapped.libgcc # for libgcc_s.so
|
||||
final.buildPackages.zlib
|
||||
];
|
||||
depsBuildBuild = upstream.depsBuildBuild or [] ++ [ final.pkg-config ];
|
||||
# buildInputs = upstream.buildInputs ++ [
|
||||
# final.gcc-unwrapped.libgcc # for libgcc_s.so. this gets loaded during build, suggesting i surely messed something up
|
||||
# ];
|
||||
# buildInputs = upstream.buildInputs ++ [
|
||||
# final.gcc-unwrapped.libgcc
|
||||
# ];
|
||||
# nativeBuildInputs = upstream.nativeBuildInputs ++ [
|
||||
# final.icu
|
||||
# ];
|
||||
# buildInputs = upstream.buildInputs ++ [
|
||||
# final.icu
|
||||
# ];
|
||||
# env.NIX_DEBUG="1";
|
||||
# env.NIX_DEBUG="7";
|
||||
# cmakeFlags = lib.remove "-DQT_FEATURE_webengine_system_icu=ON" upstream.cmakeFlags;
|
||||
cmakeFlags = upstream.cmakeFlags ++ lib.optionals (final.stdenv.hostPlatform != final.stdenv.buildPlatform) [
|
||||
# "--host-cc=${final.buildPackages.stdenv.cc}/bin/cc"
|
||||
# "--host-cxx=${final.buildPackages.stdenv.cc}/bin/c++"
|
||||
# these are my own vars, used by my own patch
|
||||
"-DCMAKE_HOST_C_COMPILER=${final.buildPackages.stdenv.cc}/bin/gcc"
|
||||
"-DCMAKE_HOST_CXX_COMPILER=${final.buildPackages.stdenv.cc}/bin/g++"
|
||||
"-DCMAKE_HOST_AR=${final.buildPackages.stdenv.cc}/bin/ar"
|
||||
"-DCMAKE_HOST_NM=${final.buildPackages.stdenv.cc}/bin/nm"
|
||||
];
|
||||
});
|
||||
});
|
||||
|
||||
rmlint = prev.rmlint.override {
|
||||
# fixes "Checking whether the C compiler works... no"
|
||||
@@ -1094,6 +1236,13 @@ in {
|
||||
# fixes "meson.build:183:0: ERROR: Can not run test applications in this cross environment."
|
||||
inherit (emulated) stdenv;
|
||||
};
|
||||
tuba = (prev.tuba.override {
|
||||
# fixes -msse2, -mfpmath=sse flags
|
||||
wrapGAppsHook4 = final.wrapGAppsHook;
|
||||
}).overrideAttrs (upstream: {
|
||||
# error: Package `{libadwaita-1,gtksourceview-5,libsecret-1,gee-0.8}' not found in specified Vala API directories or GObject-Introspection GIR directories
|
||||
buildInputs = upstream.buildInputs ++ [ final.vala ];
|
||||
});
|
||||
# twitter-color-emoji = prev.twitter-color-emoji.override {
|
||||
# # fails to fix original error
|
||||
# inherit (emulated) stdenv;
|
||||
|
35
overlays/qtwebengine-host-cc.patch
Normal file
35
overlays/qtwebengine-host-cc.patch
Normal file
@@ -0,0 +1,35 @@
|
||||
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
|
||||
index 771446ece..c20da0d56 100644
|
||||
--- a/src/CMakeLists.txt
|
||||
+++ b/src/CMakeLists.txt
|
||||
@@ -172,7 +172,11 @@ if(CMAKE_CROSSCOMPILING AND NOT IOS AND NOT MACOS)
|
||||
CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${QT_HOST_PATH}/lib/cmake/Qt6/qt.toolchain.cmake
|
||||
-DWEBENGINE_ROOT_BUILD_DIR=${PROJECT_BINARY_DIR}
|
||||
-DWEBENGINE_ROOT_SOURCE_DIR=${WEBENGINE_ROOT_SOURCE_DIR}
|
||||
- -DGN_TARGET_CPU=${TEST_architecture_arch}
|
||||
+ -DGN_TARGET_CPU=${CMAKE_HOST_SYSTEM_PROCESSOR}
|
||||
+ -DCMAKE_C_COMPILER=${CMAKE_HOST_C_COMPILER}
|
||||
+ -DCMAKE_CXX_COMPILER=${CMAKE_HOST_CXX_COMPILER}
|
||||
+ -DCMAKE_AR=${CMAKE_HOST_AR}
|
||||
+ -DCMAKE_NM=${CMAKE_HOST_NM}
|
||||
-DCMAKE_C_FLAGS=
|
||||
-DCMAKE_CXX_FLAGS=
|
||||
-DQT_FEATURE_qtwebengine_build=${QT_FEATURE_qtwebengine_build}
|
||||
diff --git a/src/host/CMakeLists.txt b/src/host/CMakeLists.txt
|
||||
index 2b92ebe85..e2ff58b35 100644
|
||||
--- a/src/host/CMakeLists.txt
|
||||
+++ b/src/host/CMakeLists.txt
|
||||
@@ -22,11 +22,11 @@ project(QtWebEngineConfigure
|
||||
find_package(Qt6 ${PROJECT_VERSION} CONFIG REQUIRED COMPONENTS BuildInternals Core)
|
||||
|
||||
set(buildDir ${CMAKE_CURRENT_BINARY_DIR})
|
||||
-configure_gn_toolchain(host ${TEST_architecture_arch} ${TEST_architecture_arch}
|
||||
+configure_gn_toolchain(host ${CMAKE_HOST_SYSTEM_PROCESSOR} ${CMAKE_HOST_SYSTEM_PROCESSOR}
|
||||
${WEBENGINE_ROOT_SOURCE_DIR}/src/host/BUILD.toolchain.gn.in
|
||||
${buildDir}/host_toolchain
|
||||
)
|
||||
-get_v8_arch(GN_V8_HOST_CPU ${GN_TARGET_CPU} ${TEST_architecture_arch})
|
||||
+get_v8_arch(GN_V8_HOST_CPU ${GN_TARGET_CPU} ${CMAKE_HOST_SYSTEM_PROCESSOR})
|
||||
configure_gn_toolchain(v8 ${GN_V8_HOST_CPU} ${GN_TARGET_CPU}
|
||||
${WEBENGINE_ROOT_SOURCE_DIR}/src/host/BUILD.toolchain.gn.in
|
||||
${buildDir}/v8_toolchain)
|
14
overlays/qtwebengine-host-pkg-config.patch
Normal file
14
overlays/qtwebengine-host-pkg-config.patch
Normal file
@@ -0,0 +1,14 @@
|
||||
diff --git a/cmake/Functions.cmake b/cmake/Functions.cmake
|
||||
index 03d19992f..5ce54ca9d 100644
|
||||
--- a/cmake/Functions.cmake
|
||||
+++ b/cmake/Functions.cmake
|
||||
@@ -720,9 +720,6 @@ endfunction()
|
||||
function(create_pkg_config_wrapper wrapperName wrapperCmd)
|
||||
file(WRITE ${wrapperName}
|
||||
"#!/bin/sh\n"
|
||||
- "unset PKG_CONFIG_LIBDIR\n"
|
||||
- "unset PKG_CONFIG_PATH\n"
|
||||
- "unset PKG_CONFIG_SYSROOT_DIR\n"
|
||||
"exec ${wrapperCmd} \"$@\""
|
||||
)
|
||||
file(CHMOD ${wrapperName} PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE)
|
18
pkgs/additional/gpodder-adaptive/default.nix
Normal file
18
pkgs/additional/gpodder-adaptive/default.nix
Normal file
@@ -0,0 +1,18 @@
|
||||
{ gpodder
|
||||
, fetchFromGitHub
|
||||
, libhandy
|
||||
}:
|
||||
gpodder.overrideAttrs (upstream: rec {
|
||||
pname = "gpodder-adaptive";
|
||||
version = "3.11.1+1";
|
||||
src = fetchFromGitHub {
|
||||
owner = "gpodder";
|
||||
repo = "gpodder";
|
||||
rev = "adaptive/${version}";
|
||||
hash = "sha256-pn5sh8CLV2Civ26PL3rrkkUdoobu7SIHXmWKCZucBhw=";
|
||||
};
|
||||
|
||||
buildInputs = upstream.buildInputs ++ [
|
||||
libhandy
|
||||
];
|
||||
})
|
@@ -0,0 +1,14 @@
|
||||
diff --git a/CMakeModules/QtConfiguration.cmake b/CMakeModules/QtConfiguration.cmake
|
||||
index d74a484..fb678ad 100644
|
||||
--- a/CMakeModules/QtConfiguration.cmake
|
||||
+++ b/CMakeModules/QtConfiguration.cmake
|
||||
@@ -53,8 +53,7 @@ foreach(COMP ${components})
|
||||
find_package(Qt6 REQUIRED COMPONENTS Gui)
|
||||
find_package(Qt6 REQUIRED COMPONENTS Quick)
|
||||
find_package(Qt6 REQUIRED COMPONENTS Widgets)
|
||||
- find_package(Qt6 REQUIRED COMPONENTS WebEngineQuick)
|
||||
- find_package(Qt6 REQUIRED COMPONENTS WebEngineCore)
|
||||
+ find_package(Qt6 REQUIRED COMPONENTS WebEngine)
|
||||
find_package(Qt6 REQUIRED COMPONENTS OpenGL)
|
||||
find_package(Qt6 REQUIRED COMPONENTS DBus)
|
||||
|
@@ -1,4 +1,5 @@
|
||||
{ lib
|
||||
, buildPackages
|
||||
, cmake
|
||||
, fetchFromGitHub
|
||||
, jellyfin-media-player
|
||||
@@ -19,7 +20,7 @@
|
||||
owner = "jellyfin";
|
||||
repo = "jellyfin-media-player";
|
||||
rev = "qt6";
|
||||
hash = "sha256-saR/P2daqjF0G8N7BX6Rtsb1dWGjdf5MPDx1lhoioEw=";
|
||||
hash = "sha256-CXuK6PLGOiBDbnLqXcr5sUtQmXksMc6X6GKVMEzmu30=";
|
||||
};
|
||||
# nixos ships two patches:
|
||||
# - the first fixes "web paths" and has *mostly* been upstreamed (so skip and manually tweak a bit)
|
||||
@@ -27,6 +28,7 @@
|
||||
patches = (builtins.tail upstream.patches) ++ [
|
||||
./0001-fix-web-path.patch
|
||||
./0002-qt6-build-fixes.patch
|
||||
# ./0003-qt6-components-webengine.patch
|
||||
];
|
||||
buildInputs = [
|
||||
SDL2
|
||||
@@ -39,6 +41,7 @@
|
||||
qt6.qtwebchannel
|
||||
qt6.qtwebengine
|
||||
# qtx11extras
|
||||
qt6.qt5compat #< new
|
||||
] ++ lib.optionals stdenv.isLinux [
|
||||
qt6.qtwayland
|
||||
];
|
||||
@@ -48,16 +51,15 @@
|
||||
ninja
|
||||
pkg-config
|
||||
python3
|
||||
|
||||
# new packages which weren't needed before
|
||||
qt6.wrapQtAppsHook # replaces the implicit qt5 version
|
||||
qt6.qt5compat
|
||||
qt6.wrapQtAppsHook #< new: libsForQt5.callPackage implicitly adds the qt5 wrapQtAppsHook
|
||||
];
|
||||
|
||||
cmakeFlags = [
|
||||
"-DCMAKE_BUILD_TYPE=Release"
|
||||
"-DQTROOT=${qt6.qtbase}"
|
||||
"-GNinja"
|
||||
# "-DQT_DEBUG_FIND_PACKAGE=ON"
|
||||
# "--debug-find-pkg=Qt6WebEngineQuick"
|
||||
];
|
||||
|
||||
meta = upstream.meta // {
|
||||
|
@@ -19,11 +19,11 @@ let
|
||||
# - megi publishes release notes as the most recent commit on any stable branch, so just `git log`.
|
||||
# - orange-pi is listed as the "main integration branch".
|
||||
# - specific branches like `pp` (pinephone) are dev branches, and probably less stable.
|
||||
rev = "orange-pi-6.3-20230426-1041";
|
||||
hash = "sha256-hfnBVtWyn6FAAOXnizE4jRaf6b9KYEwlJu3NOD7DMGM=";
|
||||
base = "6.3.0";
|
||||
rev = "orange-pi-6.4-20230619-0323";
|
||||
hash = "sha256-il32UQM/8Fc7VHft3+M4TLMxk5+h28C9Suu1kRdZj2M=";
|
||||
base = "6.4.0";
|
||||
# set to empty if not a release candidate, else `-rc<N>`
|
||||
rc = "";
|
||||
rc = "-rc7";
|
||||
|
||||
# pinephone uses the linux dtb at arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||
# - this includes sun50i-a64.dtsi
|
||||
|
@@ -1,10 +1,35 @@
|
||||
{ lib
|
||||
, pkgs
|
||||
, python3Packages
|
||||
, static-nix-shell
|
||||
, symlinkJoin
|
||||
, transmission
|
||||
}:
|
||||
|
||||
let
|
||||
sane-lib = {
|
||||
# TODO: we could simplify the lib/ folder structure
|
||||
# by auto-generating the setup.py files in `postPatch`, below
|
||||
bt = python3Packages.buildPythonPackage {
|
||||
pname = "sane-lib-bt";
|
||||
version = "0.1.0";
|
||||
format = "setuptools";
|
||||
src = ./src/lib/bt;
|
||||
propagatedBuildInputs = [ transmission ];
|
||||
pythonImportChecks = [
|
||||
"sane_bt"
|
||||
];
|
||||
};
|
||||
ssdp = python3Packages.buildPythonPackage {
|
||||
pname = "sane-lib-ssdp";
|
||||
version = "0.1.0";
|
||||
format = "setuptools";
|
||||
src = ./src/lib/ssdp;
|
||||
pythonImportChecks = [
|
||||
"sane_ssdp"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
nix-shell-scripts = {
|
||||
# anything added to this attrset gets symlink-joined into `sane-scripts`
|
||||
# and is made available through `sane-scripts.passthru`
|
||||
@@ -18,25 +43,28 @@ let
|
||||
src = ./src;
|
||||
pkgs = [ "duplicity" ];
|
||||
};
|
||||
bt-add = static-nix-shell.mkBash {
|
||||
bt-add = static-nix-shell.mkPython3Bin {
|
||||
pname = "sane-bt-add";
|
||||
src = ./src;
|
||||
pkgs = [ "transmission" ];
|
||||
pyPkgs = [ "sane-lib.bt" ];
|
||||
pkgs = [ "sane-scripts.lib.bt.propagatedBuildInputs" ];
|
||||
};
|
||||
bt-rm = static-nix-shell.mkBash {
|
||||
bt-rm = static-nix-shell.mkPython3Bin {
|
||||
pname = "sane-bt-rm";
|
||||
src = ./src;
|
||||
pkgs = [ "transmission" ];
|
||||
pyPkgs = [ "sane-lib.bt" ];
|
||||
pkgs = [ "sane-scripts.lib.bt.propagatedBuildInputs" ];
|
||||
};
|
||||
bt-search = static-nix-shell.mkPython3Bin {
|
||||
pname = "sane-bt-search";
|
||||
src = ./src;
|
||||
pyPkgs = [ "natsort" "requests" ];
|
||||
};
|
||||
bt-show = static-nix-shell.mkBash {
|
||||
bt-show = static-nix-shell.mkPython3Bin {
|
||||
pname = "sane-bt-show";
|
||||
src = ./src;
|
||||
pkgs = [ "transmission" ];
|
||||
pyPkgs = [ "sane-lib.bt" ];
|
||||
pkgs = [ "sane-scripts.lib.bt.propagatedBuildInputs" ];
|
||||
};
|
||||
deadlines = static-nix-shell.mkBash {
|
||||
pname = "sane-deadlines";
|
||||
@@ -67,19 +95,13 @@ let
|
||||
pname = "sane-ip-check-upnp";
|
||||
src = ./src;
|
||||
pkgs = [ "miniupnpc" ];
|
||||
postInstall = ''
|
||||
mkdir -p $out/bin/lib
|
||||
cp -R lib/* $out/bin/lib/
|
||||
'';
|
||||
pyPkgs = [ "sane-lib.ssdp" ];
|
||||
};
|
||||
ip-port-forward = static-nix-shell.mkPython3Bin {
|
||||
pname = "sane-ip-port-forward";
|
||||
src = ./src;
|
||||
pkgs = [ "inetutils" "miniupnpc" ];
|
||||
postInstall = ''
|
||||
mkdir -p $out/bin/lib
|
||||
cp -R lib/* $out/bin/lib/
|
||||
'';
|
||||
pyPkgs = [ "sane-lib.ssdp" ];
|
||||
};
|
||||
ip-reconnect = static-nix-shell.mkPython3Bin {
|
||||
pname = "sane-ip-reconnect";
|
||||
@@ -207,7 +229,9 @@ in
|
||||
symlinkJoin {
|
||||
name = "sane-scripts";
|
||||
paths = lib.attrValues nix-shell-scripts;
|
||||
passthru = nix-shell-scripts;
|
||||
passthru = nix-shell-scripts // {
|
||||
lib = sane-lib;
|
||||
};
|
||||
meta = {
|
||||
description = "collection of scripts associated with sane systems";
|
||||
homepage = "https://git.uninsane.org";
|
||||
|
@@ -1,3 +0,0 @@
|
||||
# sudo, umount, others, are located here.
|
||||
# resholve can't inline their path, since it's not a store path
|
||||
PATH=$PATH:/run/wrappers/bin
|
163
pkgs/additional/sane-scripts/src/lib/bt/sane_bt.py
Normal file
163
pkgs/additional/sane-scripts/src/lib/bt/sane_bt.py
Normal file
@@ -0,0 +1,163 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from argparse import ArgumentParser, Namespace
|
||||
from dataclasses import dataclass
|
||||
|
||||
import logging
|
||||
import os.path
|
||||
import subprocess
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@dataclass
|
||||
class MediaMeta:
|
||||
title: str | None
|
||||
prefix: str | None
|
||||
author: str | None
|
||||
type_: "film" | "show" | "book" | "audiobook" | "vn" # TODO: use enumeration
|
||||
freeleech: bool
|
||||
archive: bool
|
||||
|
||||
@classmethod
|
||||
def add_arguments(self, parser: ArgumentParser):
|
||||
parser.add_argument("--prefix", help="additional path component before anything implied by the other options (but after the base media dir")
|
||||
parser.add_argument("--film", action="store_true")
|
||||
parser.add_argument("--show", help="ShowTitle")
|
||||
parser.add_argument("--book", help="BookTitle")
|
||||
parser.add_argument("--audiobook", help="AudiobookTitle")
|
||||
parser.add_argument("--vn", help="VisualNovelTitle (for comics/manga)")
|
||||
parser.add_argument("--author", help="FirstnameLastname")
|
||||
parser.add_argument("--freeleech", action="store_true", help="not interested in the data, only in seeding")
|
||||
parser.add_argument("--archive", action="store_true", help="not interested in the data, except for archival")
|
||||
|
||||
@classmethod
|
||||
def from_arguments(self, args: Namespace) -> Self:
|
||||
title = None
|
||||
type_ = None
|
||||
if args.film:
|
||||
type_ = "film"
|
||||
if args.show != None:
|
||||
type_ = "show"
|
||||
title = args.show
|
||||
if args.book != None:
|
||||
type_ = "book"
|
||||
title = args.book
|
||||
if args.audiobook != None:
|
||||
type_ = "audiobook"
|
||||
title = args.audiobook
|
||||
if args.vn != None:
|
||||
type_ = "vn"
|
||||
title = args.vn
|
||||
assert type_ is not None, "no torrent type specified!"
|
||||
assert not (args.freeleech and args.archive), "--freeleech and --archive are mutually exclusive"
|
||||
return MediaMeta(
|
||||
title=title,
|
||||
prefix=args.prefix,
|
||||
author=args.author,
|
||||
type_=type_,
|
||||
freeleech=args.freeleech,
|
||||
archive=args.archive,
|
||||
)
|
||||
|
||||
@property
|
||||
def type_path(self) -> str:
|
||||
return dict(
|
||||
film="Videos/Film/",
|
||||
show="Videos/Shows/",
|
||||
book="Books/Books/",
|
||||
audiobook="Books/Audiobooks/",
|
||||
vn="Books/Visual/",
|
||||
)[self.type_]
|
||||
|
||||
def fs_path(self, base: str="/var/lib/uninsane/media/"):
|
||||
return os.path.join(
|
||||
base,
|
||||
self.prefix or "",
|
||||
"archive" if self.archive else "",
|
||||
"freeleech" if self.freeleech else "",
|
||||
self.type_path,
|
||||
self.author or "",
|
||||
self.title or "",
|
||||
)
|
||||
|
||||
|
||||
def dry_check_output(args: list[str]) -> bytes:
|
||||
print("not invoking because dry run: " + ' '.join(args))
|
||||
return b""
|
||||
|
||||
class TransmissionApi:
|
||||
ENDPOINT="https://bt.uninsane.org/transmission/rpc"
|
||||
PASSFILE="/run/secrets/transmission_passwd"
|
||||
|
||||
def __init__(self, check_output = subprocess.check_output):
|
||||
self.check_output = check_output
|
||||
|
||||
@staticmethod
|
||||
def add_arguments(parser: ArgumentParser):
|
||||
parser.add_argument("--dry-run", action="store_true", help="only show what would be done; don't invoke transmission")
|
||||
|
||||
@staticmethod
|
||||
def from_arguments(args: Namespace) -> Self:
|
||||
return TransmissionApi(check_output = dry_check_output if args.dry_run else subprocess.check_output)
|
||||
|
||||
@property
|
||||
def auth(self) -> str:
|
||||
return open(self.PASSFILE, "r").read().strip()
|
||||
|
||||
def add_torrent(self, meta: MediaMeta, torrent: str):
|
||||
self.call_transmission(
|
||||
description=f"saving to {meta.fs_path()}",
|
||||
args=[
|
||||
"--download-dir", meta.fs_path(),
|
||||
"--add", torrent,
|
||||
]
|
||||
)
|
||||
|
||||
def move_torrent(self, meta: MediaMeta, torrent: str):
|
||||
self.call_transmission(
|
||||
description=f"moving {torrent} to {meta.fs_path()}",
|
||||
args=[
|
||||
"--torrent", torrent,
|
||||
"--move", meta.fs_path()
|
||||
]
|
||||
)
|
||||
|
||||
def add_or_move_torrent(self, meta: MediaMeta, torrent: str):
|
||||
"""
|
||||
if "torrent" represents a magnet or file URI, then add else
|
||||
else assume it's a transmission identifier and move it to the location specified by @p meta.
|
||||
"""
|
||||
if torrent.isdigit():
|
||||
self.move_torrent(meta, torrent)
|
||||
else:
|
||||
self.add_torrent(meta, torrent)
|
||||
|
||||
def rm_torrent(self, torrent: str | int):
|
||||
self.call_transmission(
|
||||
description=f"deleting {torrent}",
|
||||
args=[
|
||||
"--torrent", torrent,
|
||||
"--remove-and-delete"
|
||||
]
|
||||
)
|
||||
|
||||
def list_(self) -> str:
|
||||
return self.call_transmission([
|
||||
"--list"
|
||||
])
|
||||
|
||||
def info(self, torrent: str) -> str:
|
||||
return self.call_transmission([
|
||||
"--torrent", torrent,
|
||||
"--info"
|
||||
])
|
||||
|
||||
def call_transmission(self, args: list[str], description: str | None = None) -> str:
|
||||
if description is not None:
|
||||
logger.info(description)
|
||||
|
||||
return self.check_output([
|
||||
"transmission-remote",
|
||||
self.ENDPOINT,
|
||||
"--auth", f"colin:{self.auth}",
|
||||
] + args).decode("utf-8")
|
9
pkgs/additional/sane-scripts/src/lib/bt/setup.py
Normal file
9
pkgs/additional/sane-scripts/src/lib/bt/setup.py
Normal file
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from distutils.core import setup
|
||||
|
||||
setup(
|
||||
name='sane-lib-bt',
|
||||
version='0.1.0',
|
||||
description='utilities for sane-scripts',
|
||||
)
|
@@ -73,7 +73,7 @@ def get_ips_from_location(location: str):
|
||||
res = subprocess.run(cmd, capture_output=True)
|
||||
if res.returncode != 0:
|
||||
logger.info(f"get_wan_from_location failed: {cmd!r}\n{res.stderr}")
|
||||
return None
|
||||
return None, None
|
||||
|
||||
status = res.stdout.decode("utf-8")
|
||||
logger.debug(f"got status: {status}")
|
9
pkgs/additional/sane-scripts/src/lib/ssdp/setup.py
Normal file
9
pkgs/additional/sane-scripts/src/lib/ssdp/setup.py
Normal file
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from distutils.core import setup
|
||||
|
||||
setup(
|
||||
name='sane-lib-ssdp',
|
||||
version='0.1.0',
|
||||
description='utilities for sane-scripts',
|
||||
)
|
@@ -1,94 +1,28 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p transmission
|
||||
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ps.sane-lib.bt ])" -p sane-scripts.lib.bt.propagatedBuildInputs
|
||||
# vim: set filetype=python :
|
||||
|
||||
set -e
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
endpoint=https://bt.uninsane.org/transmission/rpc
|
||||
PASS=$(sudo cat /run/secrets/transmission_passwd)
|
||||
from sane_bt import MediaMeta, TransmissionApi
|
||||
|
||||
options=$(getopt -l help,prefix:,film,show:,book:,audiobook:,vn:,author: -- "" "${@}")
|
||||
eval "set -- ${options}"
|
||||
|
||||
type=
|
||||
title=
|
||||
author=
|
||||
prefix=
|
||||
while true; do
|
||||
case "$1" in
|
||||
(--help)
|
||||
echo "add a .torrent or magnet:// file to be downloaded by and stored on my server"
|
||||
echo "usage: sane-bt-add [options] <magnet:// URI or path/to.torrent>"
|
||||
echo "options:"
|
||||
echo " --prefix <PathString>"
|
||||
echo " --film"
|
||||
echo " --show <ShowTitle>"
|
||||
echo " --book <BookTitle>"
|
||||
echo " --audiobook <BookTitle>"
|
||||
echo " --vn <VisualNovelTitle>"
|
||||
echo " --author <Author>"
|
||||
echo ""
|
||||
echo "the above options are used to construct the filesystem path where the torrent data will live"
|
||||
echo "everything is relative to the root media directory (not /)"
|
||||
exit
|
||||
;;
|
||||
(--prefix)
|
||||
shift
|
||||
prefix="$1"
|
||||
shift
|
||||
;;
|
||||
(--film)
|
||||
type=Videos/Film/
|
||||
shift
|
||||
;;
|
||||
(--show)
|
||||
type=Videos/Shows/
|
||||
shift
|
||||
title="$1"/
|
||||
shift
|
||||
;;
|
||||
(--book)
|
||||
type=Books/Books/
|
||||
shift
|
||||
title="$1"/
|
||||
shift
|
||||
;;
|
||||
(--audiobook)
|
||||
type=Books/Audiobooks/
|
||||
shift
|
||||
title="$1"/
|
||||
shift
|
||||
;;
|
||||
(--vn)
|
||||
type=Books/Visual/
|
||||
shift
|
||||
title="$1"/
|
||||
shift
|
||||
;;
|
||||
(--author)
|
||||
shift
|
||||
author="$1"/
|
||||
shift
|
||||
;;
|
||||
(--)
|
||||
shift
|
||||
if [ $# -eq 1 ]; then
|
||||
break
|
||||
fi
|
||||
;;
|
||||
(*)
|
||||
echo "invalid arguments"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
def main():
|
||||
logging.basicConfig()
|
||||
logging.getLogger().setLevel(logging.INFO)
|
||||
|
||||
prefix=$prefix$type$author$title
|
||||
# positional ("non-option") parameters
|
||||
torrent="$1"
|
||||
parser = argparse.ArgumentParser(description="instruct servo to download some torrent")
|
||||
TransmissionApi.add_arguments(parser)
|
||||
MediaMeta.add_arguments(parser)
|
||||
parser.add_argument("torrent", help="magnet: URI or file path to torrent")
|
||||
|
||||
echo "saving to $prefix"
|
||||
args = parser.parse_args()
|
||||
meta = MediaMeta.from_arguments(args)
|
||||
bt_api = TransmissionApi.from_arguments(args)
|
||||
torrent = args.torrent
|
||||
|
||||
transmission-remote "$endpoint" \
|
||||
--auth "colin:$PASS" \
|
||||
--download-dir "/var/lib/uninsane/media/$prefix" \
|
||||
--add "$torrent"
|
||||
bt_api.add_or_move_torrent(meta, torrent)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
@@ -1,11 +1,26 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p transmission
|
||||
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ps.sane-lib.bt ])" -p sane-scripts.lib.bt.propagatedBuildInputs
|
||||
# vim: set filetype=python :
|
||||
|
||||
# removes a torrent and trashes its data
|
||||
# usage: sane-bt-rm <torrent>
|
||||
# where <torrent> is a magnet URL, or an identifier from sane-bt-show (e.g. 132)
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
endpoint=https://bt.uninsane.org/transmission/rpc
|
||||
PASS=$(sudo cat /run/secrets/transmission_passwd)
|
||||
from sane_bt import TransmissionApi
|
||||
|
||||
transmission-remote "$endpoint" --auth "colin:$PASS" --torrent "$1" --remove-and-delete
|
||||
|
||||
def main():
|
||||
logging.basicConfig()
|
||||
logging.getLogger().setLevel(logging.INFO)
|
||||
|
||||
parser = argparse.ArgumentParser(description="remove a torrent and trash its data")
|
||||
TransmissionApi.add_arguments(parser)
|
||||
parser.add_argument("torrent", help="numerical ID of the torrent in the transmission list (see sane-bt-show)")
|
||||
|
||||
args = parser.parse_args()
|
||||
bt_api = TransmissionApi.from_arguments(args)
|
||||
torrent = args.torrent
|
||||
|
||||
bt_api.rm_torrent(torrent)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
@@ -2,14 +2,29 @@
|
||||
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ps.natsort ps.requests ])"
|
||||
# vim: set filetype=python :
|
||||
"""
|
||||
usage: sane-bt-search <query_string>
|
||||
usage: sane-bt-search [options] <query_string>
|
||||
|
||||
searches Jackett for torrent files matching the title.
|
||||
returns select results and magnet links
|
||||
returns select results and magnet links.
|
||||
|
||||
options:
|
||||
--full display all results
|
||||
--help show this help message and exit
|
||||
--json output one json document instead of a human-readable table
|
||||
--top <n> show the <n> top rated torrents (default: 5)
|
||||
--verbose show more information, useful for debugging/development
|
||||
"""
|
||||
|
||||
# about Jackett
|
||||
# - source: <https://github.com/Jackett/Jackett>
|
||||
# - can be queried via APIs:
|
||||
# - Torznab: <https://torznab.github.io/spec-1.3-draft/index.html>
|
||||
# - TorrentPotato: <https://github.com/RuudBurger/CouchPotatoServer/wiki/Couchpotato-torrent-provider>
|
||||
# - its own JSON-based API
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
import logging
|
||||
import json
|
||||
import natsort
|
||||
import requests
|
||||
@@ -19,10 +34,22 @@ import time
|
||||
SERVICE = "https://jackett.uninsane.org"
|
||||
ENDPOINTS = dict(
|
||||
results="api/v2.0/indexers/all/results"
|
||||
# results_torznab="api/v2.0/indexers/all/results/torznab"
|
||||
)
|
||||
|
||||
epoch = datetime(1970, 1, 1)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class BadCliArgs(Exception):
|
||||
def __init__(self, msg: str = None):
|
||||
helpstr = __doc__
|
||||
if msg:
|
||||
super().__init__(f"{msg}\n\n{helpstr}")
|
||||
else:
|
||||
super().__init__(helpstr)
|
||||
|
||||
|
||||
def try_parse_time(t: str):
|
||||
try:
|
||||
return datetime.fromisoformat(t)
|
||||
@@ -44,10 +71,21 @@ class Torrent:
|
||||
size: int
|
||||
tracker: str
|
||||
title: str
|
||||
magnet: str
|
||||
magnet: "Optional[str]"
|
||||
http_dl_uri: "Optional[str]" # probably a .torrent file but it COULD be a referral to a magnet:// URI
|
||||
tracker_uri: "Optional[str]"
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"{self.seeders}[S]\t{self.pub_date}\t{self.mib}M\t{self.tracker}\t{self.title}\t{self.magnet}"
|
||||
rows = []
|
||||
rows.append(f"{self.seeders}[S]\t{self.pub_date}\t{self.mib}M\t{self.tracker}\t{self.title}")
|
||||
if self.tracker_uri:
|
||||
rows.append(f"\t{self.tracker_uri}")
|
||||
rows.append(f"\t{self.dl_uri}")
|
||||
return "\n".join(rows)
|
||||
|
||||
@property
|
||||
def dl_uri(self) -> str:
|
||||
return self.magnet or self.http_dl_uri
|
||||
|
||||
@property
|
||||
def mib(self) -> int:
|
||||
@@ -55,17 +93,31 @@ class Torrent:
|
||||
|
||||
@staticmethod
|
||||
def from_dict(d: dict) -> 'Torrent':
|
||||
logger.debug(f"Torrent.from_dict: fields: { ' '.join(d.keys()) }")
|
||||
for k, v in d.items():
|
||||
if k not in ("Seeders", "PublishDate", "Size", "Tracker", "Title", "MagnetUri", "Guid", "Link") and \
|
||||
v != None and v != "" and v != [] and v != {}:
|
||||
logger.debug(f" {k} = {v}")
|
||||
|
||||
seeders = d.get("Seeders")
|
||||
pub_date = d.get("PublishDate")
|
||||
size = d.get("Size")
|
||||
tracker = d.get("Tracker")
|
||||
title = d.get("Title")
|
||||
magnet = d.get("MagnetUri")
|
||||
if seeders is not None and pub_date is not None and title is not None and magnet is not None:
|
||||
magnet = d.get("MagnetUri") or d.get("Guid")
|
||||
http_dl_uri = d.get("Link")
|
||||
tracker_uri = d.get("Details")
|
||||
|
||||
if magnet and not magnet.startswith("magnet:"):
|
||||
logger.info(f"invalid magnet: {magnet}")
|
||||
magnet = None
|
||||
|
||||
if seeders is not None and pub_date is not None and title is not None and (magnet is not None or http_dl_uri is not None):
|
||||
pub_date = parse_time(pub_date)
|
||||
return Torrent(seeders, pub_date, size, tracker, title, magnet)
|
||||
return Torrent(seeders, pub_date, size, tracker, title, magnet, http_dl_uri, tracker_uri)
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
# N.B.: not all fields: needs to be kept in sync with consumers like mx-sanebot
|
||||
return dict(
|
||||
seeders=self.seeders,
|
||||
pub_date=self.pub_date.strftime("%Y-%m-%d"),
|
||||
@@ -100,8 +152,11 @@ class Client:
|
||||
def parse_args(args: list) -> dict:
|
||||
options = dict(
|
||||
full=False,
|
||||
query="",
|
||||
help=False,
|
||||
json=False,
|
||||
query="",
|
||||
top="5",
|
||||
verbose=False,
|
||||
)
|
||||
while args:
|
||||
arg = args[0]
|
||||
@@ -119,12 +174,27 @@ def parse_args(args: list) -> dict:
|
||||
return options
|
||||
|
||||
def main(args: list):
|
||||
logging.basicConfig()
|
||||
options = parse_args(args)
|
||||
query = options["query"]
|
||||
num_listings = 100 if options["full"] else 5
|
||||
full = options.pop("full")
|
||||
help = options.pop("help")
|
||||
json = options.pop("json")
|
||||
query = options.pop("query")
|
||||
top = options.pop("top")
|
||||
verbose = options.pop("verbose")
|
||||
|
||||
if options != {}:
|
||||
raise BadCliArgs(f"unexpected options: {options}")
|
||||
if help:
|
||||
raise BadCliArgs()
|
||||
|
||||
if verbose:
|
||||
logging.getLogger().setLevel(logging.DEBUG)
|
||||
|
||||
num_listings = 1000 if full else int(top)
|
||||
client = Client()
|
||||
res = client.query(query)
|
||||
if options["json"]:
|
||||
if json:
|
||||
dumpable = [t.to_dict() for t in res[:num_listings]]
|
||||
print(json.dumps(dumpable))
|
||||
else:
|
||||
|
@@ -1,16 +1,29 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p transmission
|
||||
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ps.sane-lib.bt ])" -p sane-scripts.lib.bt.propagatedBuildInputs
|
||||
# vim: set filetype=python :
|
||||
|
||||
endpoint=https://bt.uninsane.org/transmission/rpc
|
||||
PASS=$(sudo cat /run/secrets/transmission_passwd)
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from sane_bt import MediaMeta, TransmissionApi
|
||||
|
||||
if [ "$#" -eq 0 ]; then
|
||||
# no specific torrents we want to show, so show all of them.
|
||||
# to query specific torrents, note the index and re-invoke this script with that.
|
||||
transmission-remote "$endpoint" --auth "colin:$PASS" --list
|
||||
else
|
||||
for id in $@; do
|
||||
transmission-remote "$endpoint" --auth "colin:$PASS" -t "$id" -i
|
||||
done
|
||||
fi
|
||||
def main():
|
||||
logging.basicConfig()
|
||||
logging.getLogger().setLevel(logging.INFO)
|
||||
|
||||
parser = argparse.ArgumentParser(description="show information about one or more torrents on servo")
|
||||
TransmissionApi.add_arguments(parser)
|
||||
parser.add_argument("torrents", nargs="*", help="torrent id to show (acquire by first calling with no args)")
|
||||
|
||||
args = parser.parse_args()
|
||||
bt_api = TransmissionApi.from_arguments(args)
|
||||
torrents = args.torrents
|
||||
|
||||
if torrents:
|
||||
for t in torrents:
|
||||
print(bt_api.info(t))
|
||||
else:
|
||||
print(bt_api.list_())
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ])" -p miniupnpc
|
||||
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ps.sane-lib.ssdp ])" -p miniupnpc
|
||||
|
||||
# best to run this with an external timeout. e.g.
|
||||
# - `timeout 60 sane-ip-check-upnp`
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ])" -p inetutils -p miniupnpc
|
||||
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ps.sane-lib.ssdp ])" -p inetutils -p miniupnpc
|
||||
|
||||
'''
|
||||
USAGE: sane-ip-port-forward [options] [proto:port[:desc]]*
|
||||
@@ -22,9 +22,7 @@ import logging
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, ".")
|
||||
|
||||
from lib.sane_ssdp import get_any_wan, forward_port
|
||||
from sane_ssdp import get_any_wan, forward_port
|
||||
|
||||
class BadCliArgs(Exception):
|
||||
def __init__(self, msg: str = None):
|
||||
|
@@ -1,10 +1,17 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ])"
|
||||
# vim: set filetype=python :
|
||||
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
import logging
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def rm_color(stdout: str) -> str:
|
||||
" remove terminal control codes -- used by iwctl to colorize the output "
|
||||
return re.sub("\\[[0-9;]*m", "", stdout)
|
||||
@@ -27,6 +34,8 @@ def extract_columns(stdout: str) -> list:
|
||||
# the `>` is formatting, indicating that it's the active network
|
||||
first = first[2:].strip()
|
||||
items.append((first, second))
|
||||
|
||||
logger.debug(f"parsed iwctl output: {items!r}")
|
||||
return items
|
||||
|
||||
def iwctl(args: list, sudo: bool = False) -> str:
|
||||
@@ -47,12 +56,14 @@ def get_known() -> list:
|
||||
stdout = iwctl(["known-networks", "list"])
|
||||
stdout = rm_color(stdout)
|
||||
stdout = rm_heading(stdout)
|
||||
logging.debug(f"iwctl known-networks list: got: {stdout}")
|
||||
return [name for (name, date) in extract_columns(stdout)]
|
||||
|
||||
def get_visible() -> list:
|
||||
stdout = iwctl(["station", "wlan0", "get-networks", "rssi-dbms"])
|
||||
stdout = rm_color(stdout)
|
||||
stdout = rm_heading(stdout)
|
||||
logging.debug(f"iwctl station wlan0 get-networks rssi-dbms: got: {stdout}")
|
||||
return [(name, int(strength)) for (name, strength) in extract_columns(stdout)]
|
||||
|
||||
def choose_best(visible: list, known: list) -> str:
|
||||
@@ -71,26 +82,40 @@ def restart() -> str:
|
||||
"iwd",
|
||||
])
|
||||
|
||||
print("scanning for networks... ", end="", flush=True)
|
||||
scan()
|
||||
print("done")
|
||||
print()
|
||||
def main():
|
||||
print("scanning for networks... ", end="", flush=True)
|
||||
scan()
|
||||
print("done")
|
||||
print()
|
||||
|
||||
known = get_known()
|
||||
print("known networks:", "".join(f"\n\t{name}" for name in known))
|
||||
print()
|
||||
known = get_known()
|
||||
print("known networks:", "".join(f"\n\t{name}" for name in known))
|
||||
print()
|
||||
|
||||
visible = get_visible()
|
||||
print("visible networks:", "".join(f"\n\t{name}: {rss}" for (name, rss) in visible))
|
||||
print()
|
||||
visible = get_visible()
|
||||
print("visible networks:", "".join(f"\n\t{name}: {rss}" for (name, rss) in visible))
|
||||
print()
|
||||
|
||||
best = choose_best(visible, known)
|
||||
best = choose_best(visible, known)
|
||||
|
||||
try:
|
||||
print(f"connecting to {best}")
|
||||
result = connect(best)
|
||||
except subprocess.CalledProcessError as e:
|
||||
print("restarting iwd daemon")
|
||||
restart()
|
||||
else:
|
||||
print("success", result)
|
||||
try:
|
||||
print(f"connecting to {best}")
|
||||
result = connect(best)
|
||||
except subprocess.CalledProcessError as e:
|
||||
print("restarting iwd daemon")
|
||||
restart()
|
||||
else:
|
||||
print("success", result)
|
||||
|
||||
def parse_args(args: list):
|
||||
for a in args:
|
||||
if a in ("-v", "--verbose"):
|
||||
logging.getLogger().setLevel(logging.DEBUG)
|
||||
else:
|
||||
raise ValueError(f"unexpected arg: {a}")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig()
|
||||
parse_args(sys.argv[1:])
|
||||
main()
|
||||
|
@@ -42,6 +42,9 @@ in rec {
|
||||
(pname: " -p ${pname}")
|
||||
pkgExprs
|
||||
);
|
||||
# allow any package to be a list of packages, to support things like
|
||||
# -p python3Packages.foo.propagatedBuildInputs
|
||||
pkgsEnv' = lib.flatten pkgsEnv;
|
||||
in
|
||||
stdenv.mkDerivation ({
|
||||
version = "0.1.0"; # default version
|
||||
@@ -63,7 +66,7 @@ in rec {
|
||||
|
||||
# add runtime dependencies to PATH
|
||||
wrapProgram $out/bin/${srcPath} \
|
||||
--suffix PATH : ${lib.makeBinPath pkgsEnv }
|
||||
--suffix PATH : ${lib.makeBinPath pkgsEnv' }
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
21
pkgs/additional/sxmo-utils/0005-system-audio.patch
Normal file
21
pkgs/additional/sxmo-utils/0005-system-audio.patch
Normal file
@@ -0,0 +1,21 @@
|
||||
diff --git a/configs/default_hooks/sxmo_hook_start.sh b/configs/default_hooks/sxmo_hook_start.sh
|
||||
index 194814d..beb9232 100755
|
||||
--- a/configs/default_hooks/sxmo_hook_start.sh
|
||||
+++ b/configs/default_hooks/sxmo_hook_start.sh
|
||||
@@ -16,16 +16,6 @@ while ! superctl status > /dev/null 2>&1; do
|
||||
sleep 0.5
|
||||
done
|
||||
|
||||
-# Load our sound daemons
|
||||
-
|
||||
-if [ "$(command -v pulseaudio)" ]; then
|
||||
- superctl start pulseaudio
|
||||
-elif [ "$(command -v pipewire)" ]; then
|
||||
- # pipewire-pulse will start pipewire
|
||||
- superctl start pipewire-pulse
|
||||
- superctl start wireplumber
|
||||
-fi
|
||||
-
|
||||
# Periodically update some status bar components
|
||||
sxmo_hook_statusbar.sh all
|
||||
sxmo_daemons.sh start statusbar_periodics sxmo_run_aligned.sh 60 \
|
@@ -0,0 +1,13 @@
|
||||
diff --git a/configs/default_hooks/sxmo_hook_block_suspend.sh b/configs/default_hooks/sxmo_hook_block_suspend.sh
|
||||
index f394575..873b7b2 100755
|
||||
--- a/configs/default_hooks/sxmo_hook_block_suspend.sh
|
||||
+++ b/configs/default_hooks/sxmo_hook_block_suspend.sh
|
||||
@@ -68,7 +68,7 @@ playing_mpc() {
|
||||
}
|
||||
|
||||
playing_mpris() {
|
||||
- command -v playerctl && [ "$(playerctl status)" = "Playing" ]
|
||||
+ command -v playerctl && playerctl --all-players status | grep -q "Playing"
|
||||
}
|
||||
|
||||
photos_processing() {
|
46
pkgs/additional/sxmo-utils/0105-more-apps.patch
Normal file
46
pkgs/additional/sxmo-utils/0105-more-apps.patch
Normal file
@@ -0,0 +1,46 @@
|
||||
diff --git a/configs/default_hooks/sxmo_hook_apps.sh b/configs/default_hooks/sxmo_hook_apps.sh
|
||||
index ba70a31..085ef7d 100755
|
||||
--- a/configs/default_hooks/sxmo_hook_apps.sh
|
||||
+++ b/configs/default_hooks/sxmo_hook_apps.sh
|
||||
@@ -31,6 +31,7 @@ write_line_app audacity "$icon_mic Audacity" "audacity"
|
||||
write_line_app gnome-calculator "$icon_clc Calculator" "gnome-calculator"
|
||||
write_line_app calcurse "$icon_clk Calcurse" "sxmo_terminal.sh calcurse"
|
||||
write_line_app cmus "$icon_mus Cmus" "sxmo_terminal.sh cmus"
|
||||
+write_line_app cozy "$icon_mus Cozy" "cozy"
|
||||
write_line_app dino "$icon_msg Dino" "GDK_SCALE=1 dino"
|
||||
write_line_app dolphin "$icon_dir Dolphin" "dolphin"
|
||||
write_line_app emacs "$icon_edt Emacs (Terminal)" "sxmo_terminal.sh emacs -nw"
|
||||
@@ -60,13 +61,17 @@ write_line_app htop "$icon_cfg Htop" "sxmo_terminal.sh htop"
|
||||
write_line_app irssi "$icon_msg Irssi" "sxmo_terminal.sh irssi"
|
||||
write_line_app ii "$icon_msg Ii" "sxmo_terminal.sh ii"
|
||||
write_line_app ipython "$icon_trm IPython" "sxmo_terminal.sh ipython"
|
||||
+write_line_app jellyfinmediaplayer "$icon_mvi Jellyfin" "jellyfinmediaplayer"
|
||||
write_line_app kasts "$icon_rss Kasts" "kasts"
|
||||
write_line_app kmail "$icon_eml KMail" "kmail"
|
||||
+write_line_app komikku "$icon_bok Komikku" "komikku"
|
||||
write_line_app kontact "$icon_msg Kontact" "kontact"
|
||||
write_line_app konversation "$icon_msg Konversation" "konversation"
|
||||
+write_line_app koreader "$icon_bok KOReader" "koreader"
|
||||
write_line_app kwrite "$icon_edt Kwrite" "kwrite"
|
||||
write_line_app lagrange "$icon_glb Lagrange" "lagrange"
|
||||
write_line_app lf "$icon_dir Lf" "sxmo_terminal.sh lf"
|
||||
+write_line_app librewolf "$icon_glb Librewolf" "librewolf"
|
||||
write_line_app lollypop "$icon_mus Lollypop" "lollypop"
|
||||
write_line_app luakit "$icon_glb Luakit" "luakit"
|
||||
write_line_app marble "$icon_map Marble" "marble"
|
||||
@@ -97,6 +102,7 @@ write_line_app senpai "$icon_msg Senpai" "sxmo_terminal.sh senpai"
|
||||
write_line_app sic "$icon_msg Sic" "sxmo_terminal.sh sic"
|
||||
([ "$SXMO_WM" = dwm ] && command -v st >/dev/null) && \
|
||||
write_line "$icon_trm St" "st -e $SHELL"
|
||||
+write_line_app sublime-music "$icon_mus Sublime Music" "sublime-music"
|
||||
write_line_app surf "$icon_glb Surf" "surf"
|
||||
write_line_app syncthing "$icon_rld Syncthing" "syncthing"
|
||||
write_line_app telegram-desktop "$icon_tgm Telegram" "telegram-desktop"
|
||||
@@ -105,6 +111,7 @@ write_line_app thunar "$icon_dir Thunar" "sxmo_terminal.sh thunar"
|
||||
write_line_app thunderbird "$icon_eml Thunderbird" "thunderbird"
|
||||
write_line_app com.github.bleakgrey.tootle "$icon_msg Tootle" "com.github.bleakgrey.tootle"
|
||||
write_line_app totem "$icon_mvi Totem" "totem"
|
||||
+write_line_app dev.geopjr.Tuba "$icon_msg Tuba" "dev.geopjr.Tuba"
|
||||
write_line_app tuir "$icon_red Tuir" "sxmo_terminal.sh tuir"
|
||||
write_line_app tut "$icon_msg Tut" "sxmo_terminal.sh tut"
|
||||
write_line_app waydroid "$icon_and Waydroid" "waydroid show-full-ui"
|
@@ -1,54 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# include common definitions
|
||||
# shellcheck source=scripts/core/sxmo_common.sh
|
||||
. sxmo_common.sh
|
||||
|
||||
# Create xdg user directories, such as ~/Pictures
|
||||
xdg-user-dirs-update
|
||||
|
||||
sxmo_daemons.sh start daemon_manager superd -v
|
||||
|
||||
# let time to superd to start correctly
|
||||
while ! superctl status > /dev/null 2>&1; do
|
||||
sleep 0.5
|
||||
done
|
||||
|
||||
# Periodically update some status bar components
|
||||
sxmo_hook_statusbar.sh all
|
||||
sxmo_daemons.sh start statusbar_periodics sxmo_run_aligned.sh 60 \
|
||||
sxmo_hook_statusbar.sh periodics
|
||||
|
||||
# mako/dunst are required for warnings.
|
||||
# load some other little things here too.
|
||||
superctl start mako
|
||||
superctl start sxmo_wob
|
||||
superctl start sxmo_menumode_toggler
|
||||
superctl start bonsaid
|
||||
swaymsg output '*' bg "$SXMO_BG_IMG" fill
|
||||
|
||||
# To setup initial lock state
|
||||
sxmo_hook_unlock.sh
|
||||
|
||||
# Turn on auto-suspend
|
||||
if [ -w "/sys/power/wakeup_count" ] && [ -f "/sys/power/wake_lock" ]; then
|
||||
superctl start sxmo_autosuspend
|
||||
fi
|
||||
|
||||
# Turn on lisgd
|
||||
superctl start sxmo_hook_lisgd
|
||||
|
||||
# Start the desktop widget (e.g. clock)
|
||||
superctl start sxmo_conky
|
||||
|
||||
# Monitor the battery
|
||||
superctl start sxmo_battery_monitor
|
||||
|
||||
# It watch network changes and update the status bar icon by example
|
||||
superctl start sxmo_networkmonitor
|
||||
|
||||
# The daemon that display notifications popup messages
|
||||
superctl start sxmo_notificationmonitor
|
||||
|
||||
# monitor for headphone for statusbar
|
||||
superctl start sxmo_soundmonitor
|
@@ -1,18 +1,82 @@
|
||||
{ stdenv
|
||||
, bc
|
||||
, bemenu
|
||||
, bonsai
|
||||
, conky
|
||||
, dbus
|
||||
, fetchgit
|
||||
, gitUpdater
|
||||
, gnugrep
|
||||
, gojq
|
||||
, inotify-tools
|
||||
, j4-dmenu-desktop
|
||||
, jq
|
||||
, lib
|
||||
, libnotify
|
||||
, lisgd
|
||||
, makeWrapper
|
||||
, mako
|
||||
, mepo
|
||||
, modemmanager
|
||||
, nettools
|
||||
, playerctl
|
||||
, procps
|
||||
, pulseaudio
|
||||
, rsync
|
||||
, scdoc
|
||||
, sfeed
|
||||
, superd
|
||||
, sway
|
||||
, swayidle
|
||||
, wob
|
||||
, wvkbd
|
||||
, xdg-user-dirs
|
||||
, xdotool
|
||||
}:
|
||||
|
||||
let
|
||||
# anything which any sxmo script or default hook in this package might invoke
|
||||
runtimeDeps = [
|
||||
bc
|
||||
bemenu
|
||||
bonsai
|
||||
conky
|
||||
dbus
|
||||
# dmenu # or dmenu-wayland? only used on x11?
|
||||
gnugrep
|
||||
gojq
|
||||
inotify-tools
|
||||
j4-dmenu-desktop
|
||||
jq
|
||||
libnotify
|
||||
lisgd
|
||||
mako
|
||||
mepo # mepo_ui_central_menu.sh
|
||||
modemmanager # mmcli
|
||||
nettools # netstat
|
||||
playerctl
|
||||
procps # pgrep
|
||||
pulseaudio # pactl
|
||||
sfeed
|
||||
superd
|
||||
sway
|
||||
swayidle
|
||||
wob
|
||||
wvkbd
|
||||
xdg-user-dirs
|
||||
|
||||
# X11 only?
|
||||
xdotool
|
||||
];
|
||||
in
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "sxmo-utils";
|
||||
version = "1.14.1";
|
||||
version = "1.14.2";
|
||||
|
||||
src = fetchgit {
|
||||
url = "https://git.sr.ht/~mil/sxmo-utils";
|
||||
rev = version;
|
||||
hash = "sha256-UcJid1fi3Mgu32dCqlI9RQYnu5d07MMwW3eEYuYVBw4=";
|
||||
hash = "sha256-1bGCUhf/bt9I8BjG/G7sjYBzLh28iZSC20ml647a3J4=";
|
||||
};
|
||||
|
||||
patches = [
|
||||
@@ -21,9 +85,13 @@ stdenv.mkDerivation rec {
|
||||
./0002-ensure-log-dir.patch
|
||||
./0003-fix-xkb-paths.patch
|
||||
./0004-no-busybox.patch
|
||||
# wanted to fix/silence some non-fatal errors
|
||||
./0005-system-audio.patch
|
||||
./0006-block-suspend-any-mpris.patch
|
||||
|
||||
# personal preferences:
|
||||
# personal (but upstreamable) preferences:
|
||||
./0104-full-auto-rotate.patch
|
||||
./0105-more-apps.patch
|
||||
];
|
||||
|
||||
postPatch = ''
|
||||
@@ -31,20 +99,42 @@ stdenv.mkDerivation rec {
|
||||
sed -i "s@/etc/profile\.d/sxmo_init.sh@$out/etc/profile.d/sxmo_init.sh@" scripts/core/*.sh
|
||||
sed -i "s@/usr/bin/@@g" scripts/core/sxmo_version.sh
|
||||
sed -i 's:ExecStart=/usr/bin/:ExecStart=/usr/bin/env :' configs/superd/services/*.service
|
||||
|
||||
# apply customizations
|
||||
# - xkb_mobile_normal_buttons:
|
||||
# - on devices where volume is part of the primary keyboard (e.g. thinkpad), we want to avoid overwriting the default map
|
||||
# - this provided map is the en_US 105 key map
|
||||
${rsync}/bin/rsync -rlv ${./customization}/ ./
|
||||
'';
|
||||
|
||||
nativeBuildInputs = [
|
||||
makeWrapper
|
||||
scdoc
|
||||
];
|
||||
|
||||
installFlags = [
|
||||
"OPENRC=0"
|
||||
"DESTDIR=$(out)"
|
||||
"PREFIX="
|
||||
];
|
||||
|
||||
# we don't wrap sxmo_common.sh or sxmo_init.sh
|
||||
# which is unfortunate, for non-sxmo-utils files that might source though.
|
||||
# if that's a problem, could inject a PATH=... line into them with sed.
|
||||
postInstall = ''
|
||||
for f in \
|
||||
$out/bin/*.sh \
|
||||
$out/share/sxmo/default_hooks/desktop/sxmo_hook_*.sh \
|
||||
$out/share/sxmo/default_hooks/one_button_e_reader/sxmo_hook_*.sh \
|
||||
$out/share/sxmo/default_hooks/three_button_touchscreen/sxmo_hook_*.sh \
|
||||
$out/share/sxmo/default_hooks/sxmo_hook_*.sh \
|
||||
; do
|
||||
case $(basename $f) in
|
||||
(sxmo_common.sh|sxmo_deviceprofile_*.sh|sxmo_hook_icons.sh|sxmo_init.sh)
|
||||
# these are sourced by other scripts: don't wrap them else the `exec` in the wrapper breaks the outer script
|
||||
;;
|
||||
(*)
|
||||
wrapProgram "$f" \
|
||||
--prefix PATH : "${lib.makeBinPath runtimeDeps}"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
'';
|
||||
|
||||
passthru = {
|
||||
providedSessions = [ "sxmo" "swmo" ];
|
||||
updateScript = gitUpdater { };
|
||||
|
25
pkgs/additional/unftp/default.nix
Normal file
25
pkgs/additional/unftp/default.nix
Normal file
@@ -0,0 +1,25 @@
|
||||
{ lib
|
||||
, rustPlatform
|
||||
, fetchFromGitHub
|
||||
}:
|
||||
|
||||
rustPlatform.buildRustPackage rec {
|
||||
pname = "unftp";
|
||||
version = "0.14.3";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "bolcom";
|
||||
repo = pname;
|
||||
rev = "v${version}";
|
||||
hash = "sha256-+UL8xflnumOiWL5b9/azH9OW+X+6hRcxjiyWhCSWQRg=";
|
||||
};
|
||||
|
||||
cargoHash = "sha256-rXCDPVi3JZrC4iqgqAirigDa3fNIbkVgSo0qWHXEnvQ=";
|
||||
|
||||
meta = with lib; {
|
||||
description = "unFTP is an open-source FTP(S) (not SFTP) server aimed at the Cloud that allows bespoke extension through its pluggable authenticator, storage back-end and user detail store architectures.";
|
||||
homepage = "https://unftp.rs/";
|
||||
license = licenses.asl20;
|
||||
maintainers = with maintainers; [ colinsane ];
|
||||
};
|
||||
}
|
3303
pkgs/additional/zecwallet-light-cli/Cargo.lock
generated
Normal file
3303
pkgs/additional/zecwallet-light-cli/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
38
pkgs/additional/zecwallet-light-cli/default.nix
Normal file
38
pkgs/additional/zecwallet-light-cli/default.nix
Normal file
@@ -0,0 +1,38 @@
|
||||
{ lib
|
||||
, buildPackages
|
||||
, fetchFromGitHub
|
||||
, rustfmt
|
||||
, rustPlatform
|
||||
}:
|
||||
|
||||
rustPlatform.buildRustPackage rec {
|
||||
pname = "zecwallet-light-cli";
|
||||
version = "1.7.7";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "adityapk00";
|
||||
repo = pname;
|
||||
rev = "v${version}";
|
||||
hash = "sha256-8qr6GIldJcybQwXbdZxFVGvFPJErLpqCEIuGJw1z0qQ=";
|
||||
};
|
||||
|
||||
cargoLock = {
|
||||
lockFile = ./Cargo.lock;
|
||||
outputHashes = {
|
||||
"equihash-0.1.0" = "sha256-/QJoQKBJajNofD71e5rNVzYSw3WqXlIXPVE1BIaKGmE=";
|
||||
};
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
rustfmt
|
||||
];
|
||||
|
||||
env.PROTOC = lib.getExe buildPackages.protobuf;
|
||||
|
||||
meta = with lib; {
|
||||
description = "Zecwallet-Lite is z-Addr first lightwallet for Zcash";
|
||||
homepage = "https://github.com/adityapk00/zecwallet-light-cli";
|
||||
license = licenses.mit;
|
||||
maintainers = with maintainers; [ colinsane ];
|
||||
};
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user