Compare commits

...

72 Commits

Author SHA1 Message Date
926decbea5 persist ~/.cache/nix 2023-01-14 23:21:15 +00:00
c0f76ea8d8 flake: add flake feedback info for nix devs/readers 2023-01-14 23:20:38 +00:00
40fc37930f flake update: nixpkgs 2023-01-11 -> 2023-01-12
```
• Updated input 'nixpkgs-stable':
    'github:NixOS/nixpkgs/6a3f9996408c970b99b8b992b11bb249d1455b62' (2023-01-12)
  → 'github:NixOS/nixpkgs/e285dd0ca97c264003867c7329f0d1f4f028739c' (2023-01-13)
• Updated input 'nixpkgs-unpatched':
    'github:NixOS/nixpkgs/6c8644fc37b6e141cbfa6c7dc8d98846c4ff0c2e' (2023-01-11)
  → 'github:NixOS/nixpkgs/0f213d0fee84280d8c3a97f7469b988d6fe5fcdf' (2023-01-12)
```
2023-01-14 18:37:57 +00:00
30e7eb9ab6 sane-bt-search: convert to nix-shell and increase verbosity 2023-01-14 10:23:50 +00:00
2e03f47edc gPodder: persist the whole gPodder directory 2023-01-14 05:36:31 +00:00
4d552e3f0f gpodder-configured: remove the readFile business and use linkFarm instead 2023-01-14 05:29:38 +00:00
176a98879d gpodder: auto-unsubscribe from extra feeds at start 2023-01-14 05:25:16 +00:00
fc70889c34 Revert "import nix-script": it doesn't provide benefit over nix-shell
This reverts commit fe15cdd705.

although it *does* support generating derivation text,
import-from-derivation on the results is too clunky to actually be
usable in practice. it frequently mysteriously hangs instead.
2023-01-14 04:01:04 +00:00
49b4c57826 snippets: add nixos snippets 2023-01-14 03:38:51 +00:00
5111d095ac gpodder-configured: improve docs 2023-01-13 15:09:43 +00:00
fe15cdd705 import nix-script
this is a tool i can use like `nix-shell`, but it should be more
amenable to packaging. `nix-script --export --build-root .
./my-script.sh` gives a derivation which i should be able to
`callPackage` on.
2023-01-13 15:08:30 +00:00
638420ea0d whalebird: fix tray_icon oversight during last update 2023-01-13 10:09:07 +00:00
d55dd5ace6 whalebird: fix aarch64 build (hopefully) 2023-01-13 09:53:14 +00:00
45695aed6b whalebird: 4.6.5 -> 4.7.4 2023-01-13 09:41:05 +00:00
d6e79c4d07 feeds: remove the unused update.nix file 2023-01-13 09:41:05 +00:00
380ceaf625 mfeeds: rename update.sh -> update.py 2023-01-13 09:41:05 +00:00
942c581107 feeds: port the update.sh script to use our own feedsearch package instead of the deployed version 2023-01-13 09:41:05 +00:00
b6d94c2e08 feedsearch_crawler: add to all python3XXPackages 2023-01-13 09:41:05 +00:00
fd7acc8fc8 let host nix (i.e. nix-shell, nix-locate) know about our patched nixpkgs and overlays 2023-01-13 09:41:05 +00:00
db670fc172 package feedsearch-crawler 2023-01-13 09:41:05 +00:00
6438971c8c ssh keys: add github.com's pubkey 2023-01-13 09:41:05 +00:00
e439d398b6 flake: patch using the target system instead of the host 2023-01-13 09:05:00 +00:00
0f25cba331 moby kernel: disable config option that would break build 2023-01-13 04:40:34 +00:00
39959e912d cross: fix cross compilation by setting both local AND crossSystem 2023-01-13 04:40:34 +00:00
62e649743d moby: update megous kernel 6.1-20221128-1027 -> 6.1-20221211-1046 2023-01-13 04:40:34 +00:00
b1741a18e1 feeds: include "title" in the output OPML -- when it exists 2023-01-13 04:13:44 +00:00
a829a8e027 persist: fix permission mapping when acl is specified as toplevel attribute 2023-01-13 01:50:08 +00:00
d742ae83bd flake update: nixpkgs-unpatched: 2023-01-09 -> 2023-01-11
```
• Updated input 'nixpkgs-stable':
    'github:NixOS/nixpkgs/8c54d842d9544361aac5f5b212ba04e4089e8efe' (2023-01-08)
  → 'github:NixOS/nixpkgs/6a3f9996408c970b99b8b992b11bb249d1455b62' (2023-01-12)
• Updated input 'nixpkgs-unpatched':
    'github:NixOS/nixpkgs/aa1d74709f5dac623adb4d48fdfb27cc2c92a4d4' (2023-01-09)
  → 'github:NixOS/nixpkgs/6c8644fc37b6e141cbfa6c7dc8d98846c4ff0c2e' (2023-01-11)
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/2253120d2a6147e57bafb5c689e086221df8032f' (2023-01-08)
  → 'github:Mic92/sops-nix/32187b33ac6ec9b628dcd08dd941a715e6241dda' (2023-01-12)
```
2023-01-13 00:02:32 +00:00
110ab1a794 feeds: fix snowden to not be a podcast 2023-01-11 16:20:53 +00:00
7d5a81e542 feeds: port Civboot 2023-01-11 16:11:46 +00:00
1af2a3f329 feeds: port Michael Malice 2023-01-11 16:05:25 +00:00
3fa9e910a9 feeds: port Matrix Live 2023-01-11 16:03:00 +00:00
6befc40700 feeds: migrate Decoder 2023-01-11 15:51:41 +00:00
29db2d8dc5 feeds: switch to working 60 minutes feed 2023-01-11 15:46:34 +00:00
36d8052982 feeds: disable 60 minutes 2023-01-11 15:41:25 +00:00
48115231a3 feeds: port acquired, FT 2023-01-11 15:32:42 +00:00
8b56ddd1ca feeds: port acquired 2023-01-11 15:27:28 +00:00
c1457f5bfb feeds: port 99% Invisible 2023-01-11 15:25:32 +00:00
7dfaf77a71 feeds: port Sam Harris / Waking Up 2023-01-11 15:15:03 +00:00
72dc7029e6 feeds: port Dan Carlin 2023-01-11 15:06:18 +00:00
95f3215b00 feeds: port darknet diaries and radiolab 2023-01-11 15:03:24 +00:00
baac8df8c2 feeds: fix Econtalk; port Doctorow, 80000hrs, deconstructed, intercepted, Post, The Portal 2023-01-11 14:51:17 +00:00
dc6a08a12b convert some of my feeds to db entries 2023-01-11 13:16:26 +00:00
2413e2eb5f feeds: update ACX feed to its non-forwarded origin 2023-01-11 10:59:35 +00:00
7327128493 feed-init: don't actually need to do the git actions 2023-01-11 10:52:10 +00:00
ed8059f4c4 feed init now also initializes the feed info 2023-01-11 10:49:56 +00:00
3a72295610 feeds: import xkcd, lesswrong, lexfridman 2023-01-11 10:42:05 +00:00
e6d9edf27d feeds: add a script to initialize a feed, as well 2023-01-11 10:41:39 +00:00
78782d5f7e flake: update-feeds now actually does update *all* feeds 2023-01-11 10:31:00 +00:00
91275f3723 flake: make an app which updates one feed 2023-01-11 10:22:25 +00:00
8115edea8d readme: fix some outdated info 2023-01-11 09:53:27 +00:00
4c475bbf9c flake: formatting nit 2023-01-11 09:33:59 +00:00
7040e1f07c flake: rename decl-host -> evalHost 2023-01-11 09:31:05 +00:00
aafa64942c flake: simplify the definition of packages 2023-01-11 09:29:49 +00:00
a44a99e371 flake: simplify the imgs/nixosConfigurations definition 2023-01-11 09:24:24 +00:00
a7ff90c843 flake: nixpkgs can now be built without specifying nixpkgs. as a prefix 2023-01-11 09:21:09 +00:00
d4996d6f31 flake: fix passthru overlays (fixes broken image building) 2023-01-11 09:08:46 +00:00
bd5209c655 move cross compilation out of the flake and into the host definitions 2023-01-11 08:56:06 +00:00
9588108fd5 restructure flake so that nixosConfigurations mostly just references the other flake outputs 2023-01-11 08:45:41 +00:00
942e302afb flake: fix crossFrom.aarch64-linux to actually be compiled from that system 2023-01-11 07:51:19 +00:00
2bd98e6764 flake: clean up nixpkgsFor-related functions 2023-01-11 07:50:32 +00:00
7b9910f287 reorder pkgs.cross definition for better readability 2023-01-11 07:37:01 +00:00
917afe209e try to do cross-compiling in a slightly less hacky way 2023-01-11 07:22:21 +00:00
cc5cf9b6f4 flake: format 2023-01-11 05:58:07 +00:00
57d95dd298 flake: document the weird importing 2023-01-10 17:51:04 +00:00
0b78df53be change the nixpkgs url type so that it hashes stably 2023-01-10 17:44:58 +00:00
c8dcb4ac59 flake: lift the nixpkgs patching out to its own flake
i hope it's a *little* cleaner this way, but tbh i'm not really sure.
2023-01-10 17:00:48 +00:00
241f4ae58f packages: add nano for when things go really wrong 2023-01-10 12:53:54 +00:00
965d7eedbb define a per-feed update script
it currently has to be run manually:
```
./pkgs/feeds/update.sh <...>
```

it looks like `nix-update` might not really support flakes
2023-01-10 10:53:59 +00:00
cdc881e887 feeds: write the basis for a module which reads feed metadata from disk and can (in the future) update it 2023-01-10 03:52:33 +00:00
33967554a5 servo: fix missing "lib" in nginx file 2023-01-09 13:25:56 +00:00
5af55ecdbf merge: cleanup/document 2023-01-09 11:47:39 +00:00
66 changed files with 1481 additions and 249 deletions

52
flake.lock generated
View File

@@ -53,27 +53,29 @@
}
},
"nixpkgs": {
"inputs": {
"nixpkgs": [
"nixpkgs-unpatched"
]
},
"locked": {
"lastModified": 1672953546,
"narHash": "sha256-oz757DnJ1ITvwyTovuwG3l9cX6j9j6/DH9eH+cXFJmc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a518c77148585023ff56022f09c4b2c418a51ef5",
"type": "github"
"lastModified": 1,
"narHash": "sha256-FaeqnQPm3MIXkQsNsGTB4A9lN82YKpLkmVHgdJyJNGg=",
"path": "nixpatches",
"type": "path"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-unstable",
"type": "indirect"
"path": "nixpatches",
"type": "path"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1673163619,
"narHash": "sha256-B33PFBL64ZgTWgMnhFL3jgheAN/DjHPsZ1Ih3z0VE5I=",
"lastModified": 1673612960,
"narHash": "sha256-DWR7hrbecJKmUJCswk9MXZta710mq+3jZwTvHU/UfyY=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "8c54d842d9544361aac5f5b212ba04e4089e8efe",
"rev": "e285dd0ca97c264003867c7329f0d1f4f028739c",
"type": "github"
},
"original": {
@@ -98,14 +100,30 @@
"type": "github"
}
},
"nixpkgs-unpatched": {
"locked": {
"lastModified": 1673540789,
"narHash": "sha256-xqnxBOK3qctIeUVxecydrEDbEXjsvHCPGPbvsl63M/U=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "0f213d0fee84280d8c3a97f7469b988d6fe5fcdf",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-unstable",
"type": "indirect"
}
},
"root": {
"inputs": {
"home-manager": "home-manager",
"mobile-nixos": "mobile-nixos",
"nixpkgs": "nixpkgs",
"nixpkgs-stable": "nixpkgs-stable",
"nixpkgs-unpatched": "nixpkgs-unpatched",
"sops-nix": "sops-nix",
"uninsane": "uninsane"
"uninsane-dot-org": "uninsane-dot-org"
}
},
"sops-nix": {
@@ -116,11 +134,11 @@
"nixpkgs-stable": "nixpkgs-stable_2"
},
"locked": {
"lastModified": 1673147300,
"narHash": "sha256-gR9OEfTzWfL6vG0qkbn1TlBAOlg4LuW8xK/u0V41Ihc=",
"lastModified": 1673481602,
"narHash": "sha256-P80X38fOM2MtoYdgkyuksGOQPDhIhNJW2W2jMeMIZzE=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "2253120d2a6147e57bafb5c689e086221df8032f",
"rev": "32187b33ac6ec9b628dcd08dd941a715e6241dda",
"type": "github"
},
"original": {
@@ -129,7 +147,7 @@
"type": "github"
}
},
"uninsane": {
"uninsane-dot-org": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": [

208
flake.nix
View File

@@ -1,11 +1,24 @@
# docs:
# FLAKE FEEDBACK:
# - flake input url schemes (like `github:nixos/nixpkgs`, or `nixpkgs/nixos-22.11`) are confusing and opaque.
# - use established URI formats like https://github.com/<owner>/<repo>.
# - or reuse `fetchGit*` idioms from nixpkgs.
# - but please don't just invent something new.
# - need a way to apply local patches to inputs.
# - this could be part of the `inputs` proper, or something like `builtins.applyPatches`.
#
#
# DEVELOPMENT DOCS:
# - <https://nixos.wiki/wiki/Flakes>
# - <https://serokell.io/blog/practical-nix-flakes>
{
inputs = {
nixpkgs-stable.url = "nixpkgs/nixos-22.11";
nixpkgs.url = "nixpkgs/nixos-unstable";
nixpkgs-unpatched.url = "nixpkgs/nixos-unstable";
nixpkgs = {
url = "path:nixpatches";
inputs.nixpkgs.follows = "nixpkgs-unpatched";
};
mobile-nixos = {
url = "github:nixos/mobile-nixos";
flake = false;
@@ -18,7 +31,7 @@
url = "github:Mic92/sops-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
uninsane = {
uninsane-dot-org = {
url = "git+https://git.uninsane.org/colin/uninsane";
inputs.nixpkgs.follows = "nixpkgs";
};
@@ -28,59 +41,55 @@
self,
nixpkgs,
nixpkgs-stable,
nixpkgs-unpatched,
mobile-nixos,
home-manager,
sops-nix,
uninsane
}: let
patchedPkgs = system: nixpkgs.legacyPackages.${system}.applyPatches {
name = "nixpkgs-patched-uninsane";
src = nixpkgs;
patches = import ./nixpatches/list.nix {
inherit (nixpkgs.legacyPackages.${system}) fetchpatch;
inherit (nixpkgs.lib) fakeHash;
};
};
# return something which behaves like `pkgs`, for the provided system
# `local` = architecture of builder. `target` = architecture of the system beying deployed to
nixpkgsFor = local: target: import (patchedPkgs target) { crossSystem = target; localSystem = local; };
# evaluate ONLY our overlay, for the provided system
customPackagesFor = local: target: import ./pkgs/overlay.nix (nixpkgsFor local target) (nixpkgsFor local target);
decl-host = { name, local, target }:
uninsane-dot-org
}:
let
nixosSystem = import ((patchedPkgs target) + "/nixos/lib/eval-config.nix");
in (nixosSystem {
# by default the local system is the same as the target, employing emulation when they differ
system = target;
modules = [
./modules
(import ./hosts/instantiate.nix name)
home-manager.nixosModule
sops-nix.nixosModules.sops
{
nixpkgs.overlays = [
(import "${mobile-nixos}/overlay/overlay.nix")
uninsane.overlay
(import ./pkgs/overlay.nix)
(next: prev: rec {
# non-emulated packages build *from* local *for* target.
# for large packages like the linux kernel which are expensive to build under emulation,
# the config can explicitly pull such packages from `pkgs.cross` to do more efficient cross-compilation.
cross = (nixpkgsFor local target) // (customPackagesFor local target);
stable = import nixpkgs-stable { system = target; };
nixpkgsCompiledBy = local: nixpkgs.legacyPackages."${local}";
# cross-compatible packages
# gocryptfs = cross.gocryptfs;
evalHost = { name, local, target }:
let
# XXX: we'd prefer to use `nixosSystem = (nixpkgsCompiledBy target).nixos`
# but it doesn't propagate config to the underlying pkgs, meaning it doesn't let you use
# non-free packages even after setting nixpkgs.allowUnfree.
# XXX: patch using the target -- not local -- otherwise the target will
# need to emulate the host in order to rebuild!
nixosSystem = import ((nixpkgsCompiledBy target).path + "/nixos/lib/eval-config.nix");
in
(nixosSystem {
# we use pkgs built for and *by* the target, i.e. emulation, by default.
# cross compilation only happens on explicit access to `pkgs.cross`
system = target;
modules = [
(import ./hosts/instantiate.nix { localSystem = local; hostName = name; })
self.nixosModules.default
self.nixosModules.passthru
{
nixpkgs.overlays = [
self.overlays.default
self.overlays.passthru
];
}
];
});
in {
nixosConfigurations = {
servo = evalHost { name = "servo"; local = "x86_64-linux"; target = "x86_64-linux"; };
desko = evalHost { name = "desko"; local = "x86_64-linux"; target = "x86_64-linux"; };
lappy = evalHost { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; };
moby = evalHost { name = "moby"; local = "aarch64-linux"; target = "aarch64-linux"; };
# special cross-compiled variant, to speed up deploys from an x86 box to the arm target
# note that these *do* produce different store paths, because the closure for the tools used to cross compile
# v.s. emulate differ.
# so deploying foo-cross and then foo incurs some rebuilding.
moby-cross = evalHost { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; };
rescue = evalHost { name = "rescue"; local = "x86_64-linux"; target = "x86_64-linux"; };
};
# pinned packages:
})
];
}
];
});
decl-bootable-host = { name, local, target }: rec {
nixosConfiguration = decl-host { inherit name local target; };
# unofficial output
# this produces a EFI-bootable .img file (GPT with a /boot partition and a system (/ or /nix) partition).
# after building this:
# - flash it to a bootable medium (SD card, flash drive, HDD)
@@ -94,40 +103,75 @@
# - if fs wasn't resized automatically, then `sudo btrfs filesystem resize max /`
# - checkout this flake into /etc/nixos AND UPDATE THE FS UUIDS.
# - `nixos-rebuild --flake './#<host>' switch`
img = nixosConfiguration.config.system.build.img;
};
hosts.servo = decl-bootable-host { name = "servo"; local = "x86_64-linux"; target = "x86_64-linux"; };
hosts.desko = decl-bootable-host { name = "desko"; local = "x86_64-linux"; target = "x86_64-linux"; };
hosts.lappy = decl-bootable-host { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; };
hosts.moby = decl-bootable-host { name = "moby"; local = "aarch64-linux"; target = "aarch64-linux"; };
# special cross-compiled variant, to speed up deploys from an x86 box to the arm target
# note that these *do* produce different store paths, because the closure for the tools used to cross compile
# v.s. emulate differ.
# so deploying foo-cross and then foo incurs some rebuilding.
hosts.moby-cross = decl-bootable-host { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; };
hosts.rescue = decl-bootable-host { name = "rescue"; local = "x86_64-linux"; target = "x86_64-linux"; };
in {
nixosConfigurations = builtins.mapAttrs (name: value: value.nixosConfiguration) hosts;
imgs = builtins.mapAttrs (name: value: value.img) hosts;
packages = let
allPkgsFor = sys: (customPackagesFor sys sys) // {
nixpkgs = nixpkgsFor sys sys;
uninsane = uninsane.packages."${sys}";
imgs = builtins.mapAttrs (_: host-dfn: host-dfn.config.system.build.img) self.nixosConfigurations;
overlays = rec {
default = pkgs;
pkgs = import ./overlays/pkgs.nix;
passthru =
let
stable = next: prev: {
stable = nixpkgs-stable.legacyPackages."${prev.stdenv.hostPlatform}";
};
mobile = (import "${mobile-nixos}/overlay/overlay.nix");
uninsane = uninsane-dot-org.overlay;
in
next: prev:
(stable next prev) // (mobile next prev) // (uninsane next prev);
};
in {
x86_64-linux = allPkgsFor "x86_64-linux";
aarch64-linux = allPkgsFor "aarch64-linux";
};
templates = {
python-data = {
# initialize with:
# - `nix flake init -t '/home/colin/dev/nixos/#python-data'`
# then enter with:
# - `nix develop`
path = ./templates/python-data;
description = "python environment for data processing";
nixosModules = rec {
default = sane;
sane = import ./modules;
passthru = { ... }: {
imports = [
home-manager.nixosModule
sops-nix.nixosModules.sops
];
};
};
# this includes both our native packages and all the nixpkgs packages.
legacyPackages =
let
allPkgsFor = sys: (nixpkgsCompiledBy sys).appendOverlays [
self.overlays.passthru self.overlays.pkgs
];
in {
x86_64-linux = allPkgsFor "x86_64-linux";
aarch64-linux = allPkgsFor "aarch64-linux";
};
# extract only our own packages from the full set
packages = builtins.mapAttrs
(_: full: full.sane // { inherit (full) sane uninsane-dot-org; })
self.legacyPackages;
apps."x86_64-linux" =
let
pkgs = self.legacyPackages."x86_64-linux";
in {
update-feeds = {
type = "app";
program = "${pkgs.feeds.passthru.updateScript}";
};
init-feed = {
type = "app";
program = "${pkgs.feeds.passthru.initFeedScript}";
};
};
templates = {
python-data = {
# initialize with:
# - `nix flake init -t '/home/colin/dev/nixos/#python-data'`
# then enter with:
# - `nix develop`
path = ./templates/python-data;
description = "python environment for data processing";
};
};
};
};
}

22
hosts/common/cross.nix Normal file
View File

@@ -0,0 +1,22 @@
{ config, ... }:
let
mkCrossFrom = localSystem: pkgs: import pkgs.path {
inherit localSystem;
crossSystem = pkgs.stdenv.hostPlatform.system;
inherit (config.nixpkgs) config overlays;
};
in
{
# the configuration of which specific package set `pkgs.cross` refers to happens elsewhere;
# here we just define them all.
nixpkgs.overlays = [
(next: prev: {
# non-emulated packages build *from* local *for* target.
# for large packages like the linux kernel which are expensive to build under emulation,
# the config can explicitly pull such packages from `pkgs.cross` to do more efficient cross-compilation.
crossFrom."x86_64-linux" = mkCrossFrom "x86_64-linux" next;
crossFrom."aarch64-linux" = mkCrossFrom "aarch64-linux" next;
})
];
}

View File

@@ -2,6 +2,7 @@
{
imports = [
./bluetooth.nix
./cross.nix
./feeds.nix
./fs.nix
./hardware
@@ -38,6 +39,11 @@
nix.extraOptions = ''
experimental-features = nix-command flakes
'';
# allow `nix-shell` (and probably nix-index?) to locate our patched and custom packages
nix.nixPath = [
"nixpkgs=${pkgs.path}"
"nixpkgs-overlays=${../..}/overlays"
];
# TODO: move this into home-manager?
fonts = {

View File

@@ -1,4 +1,4 @@
{ ... }:
{ lib, sane-data, ... }:
let
hourly = { freq = "hourly"; };
daily = { freq = "daily"; };
@@ -12,6 +12,8 @@ let
tech = { cat = "tech"; };
uncat = { cat = "uncat"; };
text = { format = "text"; };
mkRss = format: url: { inherit url format; } // uncat // infrequent;
# format-specific helpers
mkText = mkRss "text";
@@ -21,48 +23,74 @@ let
# host-specific helpers
mkSubstack = subdomain: { substack = subdomain; };
fromDb = name:
let
raw = sane-data.feeds."${name}";
in {
url = raw.url;
# not sure the exact mapping with velocity here: entries per day?
freq = lib.mkDefault (
if raw.velocity or 0 > 2 then
"hourly"
else if raw.velocity or 0 > 0.5 then
"daily"
else if raw.velocity or 0 > 0.1 then
"weekly"
else
"infrequent"
);
} // lib.optionalAttrs (raw.is_podcast or false) {
format = "podcast";
} // lib.optionalAttrs (raw.title or "" != "") {
title = lib.mkDefault raw.title;
};
podcasts = [
(mkPod "https://lexfridman.com/feed/podcast/" // rat // weekly)
(fromDb "lexfridman.com/podcast" // rat)
# (mkPod "https://lexfridman.com/feed/podcast/" // rat // weekly)
## Astral Codex Ten
(mkPod "http://feeds.libsyn.com/108018/rss" // rat // daily)
(fromDb "sscpodcast.libsyn.com" // rat)
## Econ Talk
(mkPod "https://feeds.simplecast.com/wgl4xEgL" // rat // daily)
## Cory Doctorow
(mkPod "https://feeds.feedburner.com/doctorow_podcast" // pol // infrequent)
(fromDb "feeds.simplecast.com/wgl4xEgL" // rat)
## Cory Doctorow -- both podcast & text entries
(fromDb "craphound.com" // pol)
(mkPod "https://congressionaldish.libsyn.com/rss" // pol // infrequent)
## Civboot
(mkPod "https://anchor.fm/s/34c7232c/podcast/rss" // tech // infrequent)
(mkPod "https://feeds.feedburner.com/80000HoursPodcast" // rat // weekly)
(mkPod "https://allinchamathjason.libsyn.com/rss" // pol // weekly)
(mkPod "https://acquired.libsyn.com/rss" // tech // infrequent)
(mkPod "https://rss.acast.com/deconstructed" // pol // infrequent)
## Civboot -- https://anchor.fm/civboot
(fromDb "anchor.fm/s/34c7232c/podcast/rss" // tech)
(fromDb "feeds.feedburner.com/80000HoursPodcast" // rat)
(fromDb "allinchamathjason.libsyn.com" // pol)
(fromDb "acquired.libsyn.com" // tech)
# The Intercept - Deconstructed; also available: <rss.acast.com/deconstructed>
(fromDb "rss.prod.firstlook.media/deconstructed/podcast.rss" // pol)
## The Daily
(mkPod "https://feeds.simplecast.com/54nAGcIl" // pol // daily)
(mkPod "https://rss.acast.com/intercepted-with-jeremy-scahill" // pol // weekly)
(mkPod "https://podcast.posttv.com/itunes/post-reports.xml" // pol // weekly)
# The Intercept - Intercepted; also available: <https://rss.acast.com/intercepted-with-jeremy-scahill>
(fromDb "rss.prod.firstlook.media/intercepted/podcast.rss" // pol)
(fromDb "podcast.posttv.com/itunes/post-reports.xml" // pol)
## Eric Weinstein
(mkPod "https://rss.art19.com/the-portal" // rat // infrequent)
(mkPod "https://feeds.megaphone.fm/darknetdiaries" // tech // infrequent)
(mkPod "http://feeds.wnyc.org/radiolab" // pol // infrequent)
(mkPod "https://wakingup.libsyn.com/rss" // pol // infrequent)
## 99% Invisible
(mkPod "https://feeds.simplecast.com/BqbsxVfO" // pol // infrequent)
(mkPod "https://rss.acast.com/ft-tech-tonic" // tech // infrequent)
(mkPod "https://feeds.feedburner.com/dancarlin/history?format=xml" // rat // infrequent)
## 60 minutes (NB: this features more than *just* audio?)
(mkPod "https://www.cbsnews.com/latest/rss/60-minutes" // pol // infrequent)
(fromDb "rss.art19.com/the-portal" // rat)
(fromDb "darknetdiaries.com" // tech)
## Radiolab -- also available here, but ONLY OVER HTTP: <http://feeds.wnyc.org/radiolab>
(fromDb "feeds.feedburner.com/radiolab" // pol)
## Sam Harris
(fromDb "wakingup.libsyn.com" // pol)
## 99% Invisible -- also available here: <https://feeds.simplecast.com/BqbsxVfO>
(fromDb "feeds.99percentinvisible.org/99percentinvisible" // pol)
(fromDb "rss.acast.com/ft-tech-tonic" // tech)
(fromDb "feeds.feedburner.com/dancarlin/history" // rat)
(fromDb "rss.art19.com/60-minutes" // pol)
## The Verge - Decoder
(mkPod "https://feeds.megaphone.fm/recodedecode" // tech // weekly)
(fromDb "feeds.megaphone.fm/recodedecode" // tech)
## Matrix (chat) Live
(mkPod "https://feed.podbean.com/matrixlive/feed.xml" // tech // weekly)
## Michael Malice - Your Welcome
(mkPod "https://www.podcastone.com/podcast?categoryID2=2232" // pol // weekly)
(fromDb "feed.podbean.com/matrixlive/feed.xml" // tech)
## Michael Malice - Your Welcome -- also available here: <https://origin.podcastone.com/podcast?categoryID2=2232>
(fromDb "rss.art19.com/your-welcome" // pol)
];
texts = [
# AGGREGATORS (> 1 post/day)
(mkText "https://www.lesswrong.com/feed.xml" // rat // hourly)
(mkText "http://www.econlib.org/index.xml" // pol // hourly)
(fromDb "lesswrong.com" // rat)
(fromDb "econlib.org" // pol)
# AGGREGATORS (< 1 post/day)
(mkText "https://palladiummag.com/feed" // uncat // weekly)
@@ -75,10 +103,10 @@ let
(mkText "https://www.rifters.com/crawl/?feed=rss2" // uncat // weekly)
# DEVELOPERS
(mkText "https://uninsane.org/atom.xml" // infrequent // tech)
(mkText "https://mg.lol/blog/rss/" // infrequent // tech)
(fromDb "uninsane.org" // tech)
(fromDb "mg.lol" // tech)
## Ken Shirriff
(mkText "https://www.righto.com/feeds/posts/default" // tech // infrequent)
(fromDb "righto.com" // tech)
## Vitalik Buterin
(mkText "https://vitalik.ca/feed.xml" // tech // infrequent)
## ian (Sanctuary)
@@ -94,7 +122,7 @@ let
(mkText "https://pomeroyb.com/feed.xml" // tech // infrequent)
# (TECH; POL) COMMENTATORS
(mkSubstack "edwardsnowden" // pol // infrequent)
(fromDb "edwardsnowden.substack.com" // pol // text)
(mkText "http://benjaminrosshoffman.com/feed" // pol // weekly)
## Ben Thompson
(mkText "https://www.stratechery.com/rss" // pol // weekly)
@@ -148,4 +176,11 @@ let
in
{
sane.feeds = texts ++ images ++ podcasts;
assertions = builtins.map
(p: {
assertion = p.format or "unknown" == "podcast";
message = ''${p.url} is not a podcast: ${p.format or "unknown"}'';
})
podcasts;
}

View File

@@ -86,6 +86,7 @@ in
"Pictures"
"Videos"
".cache/nix"
".cargo"
".rustup"
];

View File

@@ -1,10 +1,23 @@
# trampoline from flake.nix into the specific host definition, while doing a tiny bit of common setup
hostName: { ... }: {
{ hostName, localSystem }:
{ ... }:
{
imports = [
./${hostName}
./common
];
networking.hostName = hostName;
nixpkgs.overlays = [
(next: prev: {
# for local != target we by default just emulate the target while building.
# provide a `pkgs.cross.<pkg>` alias that consumers can use instead of `pkgs.<foo>`
# to explicitly opt into non-emulated cross compilation for any specific package.
# this is most beneficial for large packages with few pre-requisites -- like Linux.
cross = next.crossFrom."${localSystem}";
})
];
}

View File

@@ -125,6 +125,9 @@ in
# aarch64-unknown-linux-gnu-gcc: error: unrecognized command line option '-mfpu=neon'
# make[3]: *** [../scripts/Makefile.build:289: drivers/video/fbdev/sun5i-eink-neon.o] Error 1
FB_SUN5I_EINK = no;
# used by the pinephone pro, but fails to compile with:
# ../drivers/media/i2c/ov8858.c:1834:27: error: implicit declaration of function 'compat_ptr'
VIDEO_OV8858 = no;
})
))
];

View File

@@ -1,5 +1,5 @@
# docs: https://nixos.wiki/wiki/Nginx
{ config, pkgs, ... }:
{ config, lib, pkgs, ... }:
let
# make the logs for this host "public" so that they show up in e.g. metrics

View File

@@ -4,6 +4,9 @@
# don't put things like fully-specific ~/.config files in here,
# even if they're "relatively unopinionated".
moduleArgs:
{
feeds = import ./feeds moduleArgs;
keys = import ./keys.nix;
}

View File

@@ -0,0 +1,51 @@
{ lib, ... }:
let
inherit (builtins) concatLists concatStringsSep foldl' fromJSON map readDir readFile;
inherit (lib) hasSuffix listToAttrs mapAttrsToList removeSuffix splitString;
# given a path to a .json file relative to sources, construct the best feed object we can.
# the .json file could be empty, in which case we make assumptions about the feed based
# on its fs path.
# Type: feedFromSourcePath :: String -> { name = String; value = feed; }
feedFromSourcePath = json-path:
assert hasSuffix "/default.json" json-path;
let
canonical-name = removeSuffix "/default.json" json-path;
default-url = "https://${canonical-name}";
feed-details = { url = default-url; } // (tryImportJson (./sources/${json-path}));
in { name = canonical-name; value = mkFeed feed-details; };
# TODO: for now, feeds are just ordinary Attrs.
# in the future, we'd like to set them up with an update script.
mkFeed = { url, ... }@details: details;
# return an AttrSet representing the json at the provided path,
# or {} if the path is empty.
tryImportJson = path:
let
as-str = readFile path;
in
if as-str == "" then
{}
else
fromJSON as-str;
sources = enumerateFilePaths ./sources;
# like `lib.listFilesRecursive` but does not mangle paths.
# Type: enumerateFilePaths :: path -> [String]
enumerateFilePaths = base:
concatLists (
mapAttrsToList
(name: type:
if type == "directory" then
# enumerate this directory and then prefix each result with the directory's name
map (e: "${name}/${e}") (enumerateFilePaths (base + "/${name}"))
else
[ name ]
)
(readDir base)
);
in
listToAttrs (map feedFromSourcePath sources)

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 1369733,
"content_type": "application/rss+xml; charset=utf-8",
"description": "Every company has a story. Learn the playbooks that built the worlds greatest companies — and how you can apply them as a founder, operator, or investor.",
"favicon": null,
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 173,
"last_seen": "2023-01-11T15:26:37.515527+00:00",
"last_updated": "2022-12-19T07:22:28+00:00",
"score": 18,
"self_url": "https://acquired.libsyn.com/rss",
"site_name": null,
"site_url": null,
"title": "Acquired",
"url": "https://acquired.libsyn.com/rss",
"velocity": 0.066,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 1030773,
"content_type": "application/rss+xml; charset=utf-8",
"description": "Industry veterans, degenerate gamblers & besties Chamath Palihapitiya, Jason Calacanis, David Sacks & David Friedberg cover all things economic, tech, political, social & poker.",
"favicon": null,
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 124,
"last_seen": "2023-01-11T12:44:53.606606+00:00",
"last_updated": "2023-01-06T10:51:00+00:00",
"score": 18,
"self_url": "https://allinchamathjason.libsyn.com/rss",
"site_name": "All-In with Chamath, Jason, Sacks & Friedberg",
"site_url": "https://allinchamathjason.libsyn.com",
"title": "All-In with Chamath, Jason, Sacks & Friedberg",
"url": "https://allinchamathjason.libsyn.com/rss",
"velocity": 0.12,
"version": "rss20"
}

View File

@@ -0,0 +1,23 @@
{
"bozo": 0,
"content_length": 13316,
"content_type": "application/rss+xml; charset=utf-8",
"description": "A podcast around the idea of creating a Civilizational Bootstrapper, a set of tools and technology that can be used to replicate the foundations of civilization along with itself.",
"favicon": null,
"hubs": [
"https://pubsubhubbub.appspot.com/"
],
"is_podcast": true,
"is_push": true,
"item_count": 6,
"last_seen": "2023-01-11T16:11:01.720399+00:00",
"last_updated": "2022-04-13T19:37:17+00:00",
"score": 22,
"self_url": "https://anchor.fm/s/34c7232c/podcast/rss",
"site_name": "Anchor",
"site_url": "https://anchor.fm",
"title": "Civboot",
"url": "https://anchor.fm/s/34c7232c/podcast/rss",
"velocity": 0.009,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 12669,
"content_type": "application/rss+xml; charset=utf-8",
"description": "The territory is a map of the map.",
"favicon": "http://benjaminrosshoffman.com/favicon.ico",
"hubs": [],
"is_podcast": false,
"is_push": false,
"item_count": 10,
"last_seen": "2023-01-11T12:32:52.176940+00:00",
"last_updated": "2023-01-09T04:33:31+00:00",
"score": -15,
"self_url": "http://benjaminrosshoffman.com/comments/feed/",
"site_name": "Compass Rose",
"site_url": "http://benjaminrosshoffman.com",
"title": "Comments for Compass Rose",
"url": "http://benjaminrosshoffman.com/comments/feed/",
"velocity": 0.312,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 56666,
"content_type": "application/rss+xml; charset=utf-8",
"description": "Cory Doctorow's Literary Works",
"favicon": "https://craphound.com/favicon.ico",
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 20,
"last_seen": "2023-01-11T12:55:10.545856+00:00",
"last_updated": "2022-12-12T14:46:35+00:00",
"score": 12,
"self_url": "https://craphound.com/feed/",
"site_name": "Cory Doctorow's craphound.com | Cory Doctorow's Literary Works",
"site_url": "https://craphound.com",
"title": "Cory Doctorow's craphound.com",
"url": "https://craphound.com/feed/",
"velocity": 0.069,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 227480,
"content_type": "application/xml; charset=utf-8",
"description": "True stories from the dark side of the Internet",
"favicon": "https://darknetdiaries.com/imgs/favicon.png",
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 131,
"last_seen": "2023-01-11T14:49:53.136566+00:00",
"last_updated": "2022-12-27T08:00:00+00:00",
"score": 20,
"self_url": "https://darknetdiaries.com/feedfree.xml",
"site_name": "Darknet Diaries True stories from the dark side of the Internet.",
"site_url": "https://darknetdiaries.com",
"title": "Darknet Diaries (ad free)",
"url": "https://darknetdiaries.com/feedfree.xml",
"velocity": 0.067,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 66775,
"content_type": "application/rss+xml; charset=utf-8",
"description": "The Library of Economics and Liberty",
"favicon": null,
"hubs": [],
"is_podcast": false,
"is_push": false,
"item_count": 10,
"last_seen": "2023-01-11T10:46:38.526754+00:00",
"last_updated": "2023-01-10T05:21:31+00:00",
"score": 14,
"self_url": "https://www.econlib.org/feed/",
"site_name": "Econlib",
"site_url": "https://www.econlib.org",
"title": "Econlib",
"url": "https://www.econlib.org/feed/",
"velocity": 2.549,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 27185,
"content_type": "application/rss+xml; charset=utf-8",
"description": "The Library of Economics and Liberty",
"favicon": null,
"hubs": [],
"is_podcast": false,
"is_push": false,
"item_count": 10,
"last_seen": "2023-01-11T13:05:47.318206+00:00",
"last_updated": "2023-01-09T11:30:25+00:00",
"score": 14,
"self_url": "https://www.econtalk.org/feed/",
"site_name": null,
"site_url": null,
"title": "EconTalk Podcast Econlib",
"url": "https://www.econtalk.org/feed",
"velocity": 0.143,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 429348,
"content_type": "application/rss+xml; charset=utf-8",
"description": "The world's most famous whistleblower writes from exile on the intersection of technology, humanity, and power.",
"favicon": "https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/2a7d3aa2-3c2f-4196-ab7c-31541be1272e/favicon.ico",
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 16,
"last_seen": "2023-01-11T12:32:02.320483+00:00",
"last_updated": "2022-09-20T13:03:59+00:00",
"score": 14,
"self_url": "https://edwardsnowden.substack.com/feed",
"site_name": "Continuing Ed — with Edward Snowden",
"site_url": "https://edwardsnowden.substack.com",
"title": "Continuing Ed — with Edward Snowden",
"url": "https://edwardsnowden.substack.com/feed",
"velocity": 0.032,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 281377,
"content_type": "text/xml; charset=utf-8",
"description": "Matrix Live, now as an audio podcast",
"favicon": "https://feed.podbean.com/favicon.ico",
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 100,
"last_seen": "2023-01-11T15:54:24.440541+00:00",
"last_updated": "2023-01-06T16:45:00+00:00",
"score": 18,
"self_url": "https://feed.podbean.com/matrixlive/feed.xml",
"site_name": null,
"site_url": "https://feed.podbean.com",
"title": "Matrix Live",
"url": "https://feed.podbean.com/matrixlive/feed.xml",
"velocity": 0.12,
"version": "rss20"
}

View File

@@ -0,0 +1,23 @@
{
"bozo": 0,
"content_length": 1600578,
"content_type": "application/xml; charset=utf-8",
"description": "Design is everywhere in our lives, perhaps most importantly in the places where we've just stopped noticing. 99% Invisible is a weekly exploration of the process and power of design and architecture. From award winning producer Roman Mars. Learn more at 99percentinvisible.org.",
"favicon": null,
"hubs": [
"https://simplecast.superfeedr.com/"
],
"is_podcast": true,
"is_push": true,
"item_count": 577,
"last_seen": "2023-01-11T15:25:01.536556+00:00",
"last_updated": "2023-01-10T23:46:05+00:00",
"score": 4,
"self_url": "https://feeds.simplecast.com/BqbsxVfO",
"site_name": null,
"site_url": null,
"title": "99% Invisible",
"url": "https://feeds.simplecast.com/BqbsxVfO",
"velocity": 0.128,
"version": "rss20"
}

View File

@@ -0,0 +1,23 @@
{
"bozo": 0,
"content_length": 1505641,
"content_type": "text/xml; charset=utf-8",
"description": "<p>Unusually in-depth conversations about the world's most pressing problems and what you can do to solve them.<br /></p>",
"favicon": null,
"hubs": [
"https://pubsubhubbub.appspot.com/"
],
"is_podcast": true,
"is_push": true,
"item_count": 181,
"last_seen": "2023-01-11T13:29:43.501516+00:00",
"last_updated": "2023-01-09T22:57:00+00:00",
"score": 14,
"self_url": "https://feeds.backtracks.fm/feeds/80000hours/80000-hours-podcast-with-rob-wiblin/feed.xml",
"site_name": null,
"site_url": null,
"title": "80,000 Hours Podcast with Rob Wiblin",
"url": "https://feeds.feedburner.com/80000HoursPodcast",
"velocity": 0.087,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 23712,
"content_type": "text/xml; charset=utf-8",
"description": "This isn't academic history (and Carlin isn't a historian) but the podcast's unique blend of high drama, masterful narration and Twilight Zone-style twists has entertained millions of listeners.",
"favicon": null,
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 13,
"last_seen": "2023-01-11T15:05:34.359948+00:00",
"last_updated": "2022-03-06T19:08:44+00:00",
"score": 2,
"self_url": "https://feeds.feedburner.com/dancarlin/history?format=xml",
"site_name": null,
"site_url": null,
"title": "Dan Carlin's Hardcore History",
"url": "https://feeds.feedburner.com/dancarlin/history",
"velocity": 0.005,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 62633,
"content_type": "text/xml; charset=utf-8",
"description": "Articles, speeches, stories and novels by an award-winning science fiction writer, read aloud in small regular chunks",
"favicon": null,
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 20,
"last_seen": "2023-01-11T12:57:50.103797+00:00",
"last_updated": "2022-12-12T14:46:35+00:00",
"score": 4,
"self_url": "https://craphound.com/category/podcast/feed/",
"site_name": null,
"site_url": null,
"title": "Podcast Cory Doctorow's craphound.com",
"url": "https://feeds.feedburner.com/doctorow_podcast",
"velocity": 0.068,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 1315558,
"content_type": "text/xml; charset=utf-8",
"description": "Radiolab",
"favicon": null,
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 150,
"last_seen": "2023-01-11T15:01:17.273650+00:00",
"last_updated": "2023-01-06T15:00:00+00:00",
"score": 4,
"self_url": "https://www.wnycstudios.org/feeds/series/podcasts",
"site_name": null,
"site_url": null,
"title": "Radiolab",
"url": "https://feeds.feedburner.com/radiolab",
"velocity": 0.139,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 2976783,
"content_type": "application/xml; charset=utf-8",
"description": "A business show about big ideas — and other problems.",
"favicon": null,
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 660,
"last_seen": "2023-01-11T15:51:13.652417+00:00",
"last_updated": "2023-01-10T10:00:00+00:00",
"score": 14,
"self_url": "https://feeds.megaphone.fm/recodedecode",
"site_name": null,
"site_url": null,
"title": "Decoder with Nilay Patel",
"url": "https://feeds.megaphone.fm/recodedecode",
"velocity": 0.24,
"version": "rss20"
}

View File

@@ -0,0 +1,23 @@
{
"bozo": 0,
"content_length": 2940192,
"content_type": "application/xml; charset=utf-8",
"description": "EconTalk: Conversations for the Curious is an award-winning weekly podcast hosted by Russ Roberts of Shalem College in Jerusalem and Stanford's Hoover Institution. The eclectic guest list includes authors, doctors, psychologists, historians, philosophers, economists, and more. Learn how the health care system really works, the serenity that comes from humility, the challenge of interpreting data, how potato chips are made, what it's like to run an upscale Manhattan restaurant, what caused the 2008 financial crisis, the nature of consciousness, and more. EconTalk has been taking the Monday out of Mondays since 2006. All 800+ episodes are available in the archive. Go to EconTalk.org for transcripts, related resources, and comments.",
"favicon": null,
"hubs": [
"https://simplecast.superfeedr.com/"
],
"is_podcast": true,
"is_push": true,
"item_count": 875,
"last_seen": "2023-01-11T14:31:49.308489+00:00",
"last_updated": "2023-01-09T11:30:00+00:00",
"score": 24,
"self_url": "https://feeds.simplecast.com/wgl4xEgL",
"site_name": null,
"site_url": null,
"title": "EconTalk",
"url": "https://feeds.simplecast.com/wgl4xEgL",
"velocity": 0.142,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 337440,
"content_type": "application/rss+xml; charset=utf-8",
"description": "A community blog devoted to refining the art of rationality",
"favicon": "https://res.cloudinary.com/lesswrong-2-0/image/upload/v1497915096/favicon_lncumn.ico",
"hubs": [],
"is_podcast": false,
"is_push": false,
"item_count": 10,
"last_seen": "2023-01-11T10:39:58.575828+00:00",
"last_updated": "2023-01-11T09:58:49+00:00",
"score": 32,
"self_url": "https://www.lesswrong.com/feed.xml?view=rss&karmaThreshold=2",
"site_name": "LessWrong",
"site_url": "https://www.lesswrong.com",
"title": "LessWrong",
"url": "https://www.lesswrong.com/feed.xml",
"velocity": 12.052,
"version": "rss20"
}

View File

@@ -0,0 +1,23 @@
{
"bozo": 0,
"content_length": 841679,
"content_type": "application/rss+xml; charset=utf-8",
"description": "Conversations about AI, science, technology, history, philosophy and the nature of intelligence, consciousness, love, and power.",
"favicon": "https://lexfridman.com/wordpress/wp-content/uploads/2017/06/cropped-lex-favicon-4-1-32x32.png",
"hubs": [
"https://pubsubhubbub.appspot.com/"
],
"is_podcast": true,
"is_push": true,
"item_count": 300,
"last_seen": "2023-01-11T12:40:59.343327+00:00",
"last_updated": "2022-12-29T17:35:50+00:00",
"score": 20,
"self_url": "https://lexfridman.com/feed/podcast/",
"site_name": "Lex Fridman",
"site_url": "https://lexfridman.com",
"title": "Lex Fridman Podcast",
"url": "https://lexfridman.com/feed/podcast/",
"velocity": 0.265,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 83074,
"content_type": "text/xml; charset=utf-8",
"description": "projects & research",
"favicon": null,
"hubs": [],
"is_podcast": false,
"is_push": false,
"item_count": 14,
"last_seen": "2023-01-11T12:28:34.383284+00:00",
"last_updated": "2021-07-29T05:10:05+00:00",
"score": 14,
"self_url": "https://mg.lol/blog/rss/",
"site_name": null,
"site_url": "https://mg.lol",
"title": "MG",
"url": "https://mg.lol/blog/rss/",
"velocity": 0.004,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 3568150,
"content_type": "application/rss+xml; charset=utf-8",
"description": "Post Reports",
"favicon": null,
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 1070,
"last_seen": "2023-01-11T14:37:23.650030+00:00",
"last_updated": "2023-01-10T21:40:40+00:00",
"score": 14,
"self_url": "https://podcast.posttv.com/itunes/post-reports.xml",
"site_name": null,
"site_url": null,
"title": "Post Reports",
"url": "https://podcast.posttv.com/itunes/post-reports.xml",
"velocity": 0.711,
"version": "rss20"
}

View File

@@ -0,0 +1,23 @@
{
"bozo": 0,
"content_length": 862917,
"content_type": "application/atom+xml; charset=utf-8",
"description": "Computer history, restoring vintage computers, IC reverse engineering, and whatever",
"favicon": "https://www.blogger.com/about/favicon/favicon.ico",
"hubs": [
"http://pubsubhubbub.appspot.com/"
],
"is_podcast": false,
"is_push": true,
"item_count": 25,
"last_seen": "2023-01-11T12:29:19.820378+00:00",
"last_updated": "2023-01-10T18:21:20.265000+00:00",
"score": -2,
"self_url": "https://www.blogger.com/feeds/6264947694886887540/posts/default",
"site_name": "Blogger.com - Create a unique and beautiful blog easily.",
"site_url": "https://www.blogger.com",
"title": "Ken Shirriff's blog",
"url": "https://www.blogger.com/feeds/6264947694886887540/posts/default",
"velocity": 0.12,
"version": "atom10"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 550915,
"content_type": "application/xml; charset=utf-8",
"description": "The show that looks at the way technology is changing our economies, societies and daily lives.",
"favicon": null,
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 160,
"last_seen": "2023-01-11T15:31:40.303733+00:00",
"last_updated": "2022-11-22T05:00:36+00:00",
"score": 10,
"self_url": "https://feeds.acast.com/public/shows/125ef5a6-6c61-4024-b70e-3487a971a26c",
"site_name": null,
"site_url": null,
"title": "FT Tech Tonic",
"url": "https://feeds.acast.com/public/shows/125ef5a6-6c61-4024-b70e-3487a971a26c",
"velocity": 0.072,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 1041745,
"content_type": "application/rss+xml; charset=utf-8",
"description": "<p>Get the best reporting and storytelling on television from 60 Minutes - on your schedule. Now you can listen to the show in its entirety every week. 60 Minutes is the most successful broadcast in television history with more than 80 Emmys under its belt. 60 Minutes offers unbiased reporting on politics, in-depth investigations and important adventures from around the world- like no one else. </p>",
"favicon": "https://rss.art19.com/favicon.ico",
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 374,
"last_seen": "2023-01-11T15:45:07.189940+00:00",
"last_updated": "2023-01-09T03:00:00+00:00",
"score": 18,
"self_url": "https://rss.art19.com/60-minutes",
"site_name": null,
"site_url": "https://rss.art19.com",
"title": "60 Minutes",
"url": "https://rss.art19.com/60-minutes",
"velocity": 0.082,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 235911,
"content_type": "application/xml; charset=utf-8",
"description": "<p>The Portal is an exploration into discovery, including conversations with thought leaders. Host Eric Weinstein, Managing Director of Thiel Capital, brings his unique expertise and diverse roster of guests for a wide range of discussions, including science, culture, business, and capitalism. The show will feature people whose lives demonstrate that portals into what we would normally consider impossible, are indeed possible.&nbsp;&nbsp;Guests include presidential candidate Andrew Yang, NY Times bestselling author Sam Harris, and retired Navy Seal and creator of the hit business podcast Jocko Willink.</p>",
"favicon": null,
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 44,
"last_seen": "2023-01-11T14:47:44.995855+00:00",
"last_updated": "2020-12-02T07:50:55+00:00",
"score": -12,
"self_url": "https://www.omnycontent.com/d/playlist/9b7dacdf-a925-4f95-84dc-ac46003451ff/1713c520-edb6-43a3-b1b9-acb8002fdae7/58e33a0c-f86b-41c5-a11c-acb8002fdaf5/podcast.rss",
"site_name": null,
"site_url": null,
"title": "The Portal",
"url": "https://www.omnycontent.com/d/playlist/9b7dacdf-a925-4f95-84dc-ac46003451ff/1713c520-edb6-43a3-b1b9-acb8002fdae7/58e33a0c-f86b-41c5-a11c-acb8002fdaf5/podcast.rss",
"velocity": 0.082,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 1462485,
"content_type": "text/xml; charset=utf-8",
"description": "Michael Malice brings his unique perspective and plenty of sick burns as he discusses everything from north Korea to American politics and culture with a bevy of guests.",
"favicon": null,
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 238,
"last_seen": "2023-01-11T15:58:45.264936+00:00",
"last_updated": "2023-01-04T10:40:00+00:00",
"score": -10,
"self_url": "http://origin.podcastone.com/podcast?categoryID2=2232",
"site_name": null,
"site_url": null,
"title": "\"YOUR WELCOME\" with Michael Malice",
"url": "https://www.podcastone.com/podcast?categoryID2=2232",
"velocity": 0.141,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"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"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 1034995,
"content_type": "application/xml+rss; charset=utf-8",
"description": "The people behind The Intercepts 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"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 3905927,
"content_type": "application/rss+xml; charset=utf-8",
"description": "The official audio version of Astral Codex Ten, with an archive of posts from Slate Star Codex. It's just me reading Scott Alexander's blog posts.",
"favicon": null,
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 739,
"last_seen": "2023-01-11T11:05:40.604126+00:00",
"last_updated": "2023-01-11T05:13:00+00:00",
"score": 18,
"self_url": "https://sscpodcast.libsyn.com/rss",
"site_name": "Astral Codex Ten Podcast",
"site_url": "https://sscpodcast.libsyn.com",
"title": "Astral Codex Ten Podcast",
"url": "https://sscpodcast.libsyn.com/rss",
"velocity": 0.384,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 1,
"content_length": 178687,
"content_type": "text/xml; charset=utf-8",
"description": null,
"favicon": null,
"hubs": [],
"is_podcast": false,
"is_push": false,
"item_count": 6,
"last_seen": "2023-01-11T10:51:13.435393+00:00",
"last_updated": "2022-10-13T00:00:00+00:00",
"score": -4,
"self_url": "https://uninsane.org/atom.xml",
"site_name": "Perfectly Sane",
"site_url": "https://uninsane.org",
"title": "Perfectly Sane",
"url": "https://uninsane.org/atom.xml",
"velocity": 0.025,
"version": "atom10"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 825822,
"content_type": "application/rss+xml; charset=utf-8",
"description": "Join neuroscientist, philosopher, and best-selling author Sam Harris as he explores questions about the human mind, society, and current events.",
"favicon": null,
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 326,
"last_seen": "2023-01-11T15:13:28.154435+00:00",
"last_updated": "2023-01-05T18:36:25+00:00",
"score": 18,
"self_url": "https://wakingup.libsyn.com/rss",
"site_name": "Making Sense with Sam Harris",
"site_url": "https://wakingup.libsyn.com",
"title": "Making Sense with Sam Harris",
"url": "https://wakingup.libsyn.com/rss",
"velocity": 0.096,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 2302,
"content_type": "text/xml; charset=utf-8",
"description": null,
"favicon": "https://xkcd.com/s/919f27.ico",
"hubs": [],
"is_podcast": false,
"is_push": false,
"item_count": 4,
"last_seen": "2023-01-11T10:29:36.530001+00:00",
"last_updated": "2023-01-09T00:00:00+00:00",
"score": 16,
"self_url": null,
"site_name": "xkcd",
"site_url": "https://xkcd.com",
"title": "xkcd.com",
"url": "https://xkcd.com/atom.xml",
"velocity": 0.429,
"version": "atom10"
}

View File

@@ -21,4 +21,10 @@
servo.root = root;
};
};
com.github = rec {
# documented here: <https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/githubs-ssh-key-fingerprints>
# Github actually uses multiple keys -- one per format
root = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl";
};
}

View File

@@ -18,6 +18,6 @@
_module.args = {
sane-lib = import ./lib { inherit lib utils; };
sane-data = import ./data;
sane-data = import ./data { inherit lib; };
};
}

View File

@@ -1,4 +1,4 @@
{ lib, ... }:
{ lib, sane-data, ... }:
with lib;
let
@@ -14,6 +14,11 @@ let
};
format = mkOption {
type = types.enum [ "text" "image" "podcast" ];
default = "text";
};
title = mkOption {
type = types.nullOr types.str;
default = null;
};
url = mkOption {
type = types.str;

View File

@@ -1,6 +1,7 @@
https://search.nixos.org/options?channel=unstable&query=
https://search.nixos.org/packages?channel=unstable&query=
https://nixos.wiki/index.php?go=Go&search=
https://nixos.org/manual/nix/stable/language/builtins.html
https://github.com/nixos/nixpkgs/pulls?q=
https://nur.nix-community.org/
https://nix-community.github.io/home-manager/options.html

View File

@@ -82,7 +82,7 @@ in
in
lib.mkIf cfg.enable
{
system.build.img-without-firmware = with pkgs; imageBuilder.diskImage.makeGPT {
system.build.img-without-firmware = with pkgs; pkgs.imageBuilder.diskImage.makeGPT {
name = "nixos";
diskID = vfatUuidFromFs bootFs;
# leave some space for firmware

View File

@@ -12,8 +12,24 @@ rec {
# transform a list of feeds into an attrs mapping cat => [ feed0 feed1 ... ]
partitionByCat = feeds: builtins.groupBy (f: f.cat) feeds;
xmlTag = tag: close: attrs:
let
fmt-attrs = builtins.concatStringsSep
" "
(lib.mapAttrsToList (name: value: ''${lib.escapeXML name}="${lib.escapeXML value}"'') attrs);
fmt-close = if close then "/" else "";
in
''<${tag} ${fmt-attrs} ${fmt-close}>'';
# represents a single RSS feed.
opmlTerminal = feed: ''<outline xmlUrl="${feed.url}" type="rss"/>'';
opmlTerminal = feed: xmlTag "outline" true (
{
xmlUrl = feed.url;
type = "rss";
} // lib.optionalAttrs (feed.title != null) {
title = feed.title;
}
);
# a list of RSS feeds.
opmlTerminals = feeds: lib.concatStringsSep "\n" (builtins.map opmlTerminal feeds);
# one node which packages some flat grouping of terminals.

View File

@@ -31,11 +31,11 @@ rec {
let
# define the current path, but nothing more.
curLevel = lib.setAttrByPath path {};
# `take` will either set:
# - { $path = path } => { $path = {} };
# - { $path.next = path.next } => { $path = { next = ?; } }
# `take curLevel` will act one of two ways here:
# - { $path = f.$path; } => { $path = {}; };
# - { $path.subAttr = f.$path.subAttr; } => { $path = { subAttr = ?; }; }
# so, index $path into the output of `take`,
# and if it has any attrs that means we're interested in those too.
# and if it has any attrs (like `subAttr`) that means we're interested in those too.
nextLevel = lib.getAttrFromPath path (take curLevel);
in
builtins.attrNames nextLevel;
@@ -49,10 +49,7 @@ rec {
in if subNames == [] then
[ path ]
else
let
terminalsPerChild = builtins.map (name: findTerminalPaths take (path ++ [name])) subNames;
in
lib.concatLists terminalsPerChild;
lib.concatMap (name: findTerminalPaths take (path ++ [name])) subNames;
# ensures that all nodes in the attrset from the root to and including the given path
# are ordinary attrs -- if they exist.
@@ -64,19 +61,15 @@ rec {
items = lib.pushDownProperties i;
# now items is a list where every element is undecorated at the toplevel.
# e.g. each item is an ordinary attrset or primitive.
in
if path == [] then
items
# we still need to discharge the *rest* of the path though, for every item.
name = lib.head path;
downstream = lib.tail path;
dischargeDownstream = it: if path != [] && it ? name then
builtins.map (v: it // { "${name}" = v; }) (dischargeToPath downstream it."${name}")
else
let
name = lib.head path;
downstream = lib.tail path;
dischargeItem = it: if it ? name then
builtins.map (v: it // { "${name}" = v; }) (dischargeToPath downstream it."${name}")
else
[ it ];
in
lib.concatMap dischargeItem items;
[ it ];
in
lib.concatMap dischargeDownstream items;
# discharge many items but only over one path.
# Type: dischargeItemsToPaths :: [Attrs] -> String -> [Attrs]
@@ -96,9 +89,12 @@ rec {
# check that attrset `i` contains no terminals other than those specified in (or direct ancestors of) paths
assertNoExtraPaths = paths: i:
let
clearPath = acc: path: lib.recursiveUpdate acc (lib.setAttrByPath path null);
remainder = builtins.foldl' clearPath i paths;
expected-remainder = builtins.foldl' clearPath {} paths;
# since the act of discharging should have forced all the relevant data out to the leaves,
# we just set each expected terminal to null (initializing the parents when necessary)
# and that gives a standard value for any fully-consumed items that we can do equality comparisons with.
wipePath = acc: path: lib.recursiveUpdate acc (lib.setAttrByPath path null);
remainder = builtins.foldl' wipePath i paths;
expected-remainder = builtins.foldl' wipePath {} paths;
in
assert remainder == expected-remainder; true;
}

View File

@@ -102,7 +102,9 @@ let
gnome.gnome-terminal # works on phosh
gnome.gnome-weather
{ pkg = gpodder-configured; dir = [ "gPodder/Downloads" ]; }
# XXX: we preserve the whole thing because if we only preserve gPodder/Downloads
# then startup is SLOW during feed import, and we might end up with zombie eps in the dl dir.
{ pkg = gpodder-configured; dir = [ "gPodder" ]; }
gthumb
handbrake
@@ -151,7 +153,9 @@ let
# vlc remembers play position in ~/.config/vlc/vlc-qt-interface.conf
{ pkg = vlc; dir = [ ".config/vlc" ]; }
whalebird # pleroma client. input is broken on phosh
# pleroma client (Electron). input is broken on phosh.
{ pkg = whalebird; private = [ ".config/Whalebird" ]; }
xdg-utils # for xdg-open
xterm # broken on phosh
]
@@ -212,6 +216,7 @@ let
jq
killall
lsof
nano
netcat
nethogs
nmap

View File

@@ -103,7 +103,7 @@ let
(orig: lib.recursiveUpdate
(builtins.removeAttrs orig ["user" "group" "mode" ])
{
acl = sane-lib.filterByName ["user" "group" "mode"] (orig.acl or {});
acl = sane-lib.filterByName ["user" "group" "mode"] orig;
}
)
to;

26
nixpatches/flake.lock generated Normal file
View File

@@ -0,0 +1,26 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1673163619,
"narHash": "sha256-B33PFBL64ZgTWgMnhFL3jgheAN/DjHPsZ1Ih3z0VE5I=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "8c54d842d9544361aac5f5b212ba04e4089e8efe",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-22.11",
"type": "indirect"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

26
nixpatches/flake.nix Normal file
View File

@@ -0,0 +1,26 @@
{
inputs = {
nixpkgs.url = "nixpkgs/nixos-22.11";
};
outputs = { self, nixpkgs }:
let
patchedPkgsFor = system: nixpkgs.legacyPackages.${system}.applyPatches {
name = "nixpkgs-patched-uninsane";
src = nixpkgs;
patches = import ./list.nix {
inherit (nixpkgs.legacyPackages.${system}) fetchpatch;
inherit (nixpkgs.lib) fakeHash;
};
};
patchedFlakeFor = system: import "${patchedPkgsFor system}/flake.nix";
patchedFlakeOutputsFor = system:
(patchedFlakeFor system).outputs { inherit self; };
in
{
legacyPackages = builtins.mapAttrs
(system: _:
(patchedFlakeOutputsFor system).legacyPackages."${system}"
)
nixpkgs.legacyPackages;
};
}

View File

@@ -16,7 +16,14 @@
# kiwix-tools: init at 3.4.0
(fetchpatch {
url = "https://github.com/NixOS/nixpkgs/pull/206254.diff";
sha256 = "sha256-Z4V9mOv4HYg3kDnWoYcxz3ch03I/1USrLjzlq4X9YqI=";
sha256 = "sha256-Cendm7a23qj/YRBj5qVM8jhl9oTpztaDEkXcSG4dJys=";
})
# whalebird: 4.6.5 -> 4.7.4
(fetchpatch {
# url = "https://git.uninsane.org/colin/nixpkgs/compare/master...pr.whalebird-4.7.4.diff";
url = "https://git.uninsane.org/colin/nixpkgs/commit/f5c7c70dde720e990fa7e0748d1dc4764d6e4406.diff";
sha256 = "sha256-L9Ie80loaP6yl5ZFnJ1b5WMDpvO1QFE8tbrW5HBauko=";
})
./2022-12-19-i2p-aarch64.patch

67
overlays/pkgs.nix Normal file
View File

@@ -0,0 +1,67 @@
(next: prev:
let
sane = rec {
#### my own, non-upstreamable packages:
sane-scripts = prev.callPackage ../pkgs/sane-scripts { };
feeds = prev.callPackage ../pkgs/feeds { };
tow-boot-pinephone = prev.callPackage ../pkgs/tow-boot-pinephone { };
tow-boot-rpi4 = prev.callPackage ../pkgs/tow-boot-rpi4 { };
bootpart-uefi-x86_64 = prev.callPackage ../pkgs/bootpart-uefi-x86_64 { };
bootpart-tow-boot-rpi-aarch64 = prev.callPackage ../pkgs/bootpart-tow-boot-rpi-aarch64 {
# not sure why i can't just do `next.callPackage` instead
inherit tow-boot-rpi4;
};
bootpart-u-boot-rpi-aarch64 = prev.callPackage ../pkgs/bootpart-u-boot-rpi-aarch64 {
# not sure why i can't just do `next.callPackage` instead
inherit ubootRaspberryPi4_64bit;
};
rtl8723cs-firmware = prev.callPackage ../pkgs/rtl8723cs-firmware { };
linux-megous = prev.callPackage ../pkgs/linux-megous {
kernelPatches = [
prev.kernelPatches.bridge_stp_helper
prev.kernelPatches.request_key_helper
];
};
sublime-music-mobile = prev.callPackage ../pkgs/sublime-music-mobile { };
#### customized packages
fluffychat-moby = prev.callPackage ../pkgs/fluffychat-moby { };
gpodder-configured = prev.callPackage ../pkgs/gpodder-configured { };
# nixos-unstable pleroma is too far out-of-date for our db
pleroma = prev.callPackage ../pkgs/pleroma { };
# jackett doesn't allow customization of the bind address: this will probably always be here.
jackett = prev.callPackage ../pkgs/jackett { inherit (prev) jackett; };
# mozilla keeps nerfing itself and removing configuration options
firefox-unwrapped = prev.callPackage ../pkgs/firefox-unwrapped { };
# patch rpi uboot with something that fixes USB HDD boot
ubootRaspberryPi4_64bit = prev.callPackage ../pkgs/ubootRaspberryPi4_64bit { };
gocryptfs = prev.callPackage ../pkgs/gocryptfs { inherit (prev) gocryptfs; };
browserpass = prev.callPackage ../pkgs/browserpass { inherit (prev) browserpass; inherit sane-scripts; };
fractal-latest = prev.callPackage ../pkgs/fractal-latest { };
#### TEMPORARY: PACKAGES WAITING TO BE UPSTREAMED
pythonPackagesExtensions = prev.pythonPackagesExtensions ++ [
(py-final: py-prev: {
feedsearch-crawler = py-final.callPackage ../pkgs/feedsearch-crawler { };
})
];
kaiteki = prev.callPackage ../pkgs/kaiteki { };
lightdm-mobile-greeter = prev.callPackage ../pkgs/lightdm-mobile-greeter { };
browserpass-extension = prev.callPackage ../pkgs/browserpass-extension { };
gopass-native-messaging-host = prev.callPackage ../pkgs/gopass-native-messaging-host { };
tokodon = prev.libsForQt5.callPackage ../pkgs/tokodon { };
signaldctl = prev.callPackage ../pkgs/signaldctl { };
splatmoji = prev.callPackage ../pkgs/splatmoji { };
# trust-dns = prev.callPackage ../pkgs/trust-dns { };
# kaiteki = prev.kaiteki;
};
in sane // { inherit sane; }
)

42
pkgs/feeds/default.nix Normal file
View File

@@ -0,0 +1,42 @@
{ lib
, pkgs
}:
(lib.makeScope pkgs.newScope (self:
let
# TODO: dependency-inject this.
sane-data = import ../../modules/data { inherit lib; };
template = self.callPackage ./template.nix;
feed-pkgs = lib.mapAttrs
(name: feed-details: template {
feedName = name;
jsonPath = "modules/data/feeds/sources/${name}/default.json";
inherit (feed-details) url;
})
sane-data.feeds;
update-scripts = lib.mapAttrsToList
(name: feed: builtins.concatStringsSep " " feed.passthru.updateScript)
feed-pkgs;
in
feed-pkgs // {
passthru.updateScript = pkgs.writeShellScript
"feeds-update"
(builtins.concatStringsSep "\n" update-scripts);
passthru.initFeedScript = pkgs.writeShellScript
"init-feed"
''
sources_dir=modules/data/feeds/sources
name="$1"
url="https://$name"
json_path="$sources_dir/$name/default.json"
# the name could have slashes in it, so we want to mkdir -p that
# but in a way where the least could go wrong.
pushd "$sources_dir"; mkdir -p "$name"; popd
${./update.py} "$url" "$json_path"
cat "$json_path"
'';
}
))

25
pkgs/feeds/template.nix Normal file
View File

@@ -0,0 +1,25 @@
{ lib
, stdenv
, callPackage
, fetchurl
# feed-specific args
, feedName
, jsonPath
, url
}:
stdenv.mkDerivation {
pname = feedName;
version = "20230112";
src = fetchurl {
inherit url;
};
passthru.updateScript = [ ./update.py url jsonPath ];
meta = {
description = "metadata about any feeds available at ${feedName}";
homepage = feedName;
maintainers = with lib.maintainers; [ colinsane ];
platforms = lib.platforms.all;
};
}

24
pkgs/feeds/update.py Executable file
View File

@@ -0,0 +1,24 @@
#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ps.feedsearch-crawler ])"
from feedsearch_crawler import search, sort_urls
from feedsearch_crawler.crawler import coerce_url
import json
import sys
url, jsonPath = sys.argv[1:]
url = coerce_url(url, default_scheme="https")
items = search(url)
items = sort_urls(items)
# print all results
serialized = [item.serialize() for item in items]
for item in serialized:
print(json.dumps(item, sort_keys=True, indent=2))
# save the first result to disk
keep = serialized[0] if serialized else {}
results = json.dumps(keep, sort_keys=True, indent=2)
with open(jsonPath, "w") as out:
out.write(results)

View File

@@ -0,0 +1,65 @@
{ lib
, buildPythonPackage
, fetchFromGitHub
# nativeBuildInputs python packages
, poetry-core
# propagatedBuildInputs python packages
, aiodns
, aiohttp
, beautifulsoup4
, brotlipy
, cchardet
, feedparser
, python-dateutil
, uvloop
, w3lib
, yarl
}:
buildPythonPackage rec {
pname = "feedsearch-crawler";
version = "2022-05-28";
format = "pyproject";
src = fetchFromGitHub {
owner = "DBeath";
repo = "feedsearch-crawler";
rev = "f49a6f5a07e796e359c4482fd29305b1a019f71f";
hash = "sha256-pzvyeXzqdi8pRjk2+QjKhJfgtxbgVT6C08K9fhVFVmY=";
};
nativeBuildInputs = [
poetry-core
];
postPatch = ''
substituteInPlace pyproject.toml \
--replace 'w3lib = "^1.22.0"' 'w3lib = "*"' \
--replace 'aiodns = "^2.0.0"' 'aiodns = "*"' \
--replace 'uvloop = "^0.15.2"' 'uvloop = "*"'
'';
propagatedBuildInputs = [
aiodns
aiohttp
beautifulsoup4
brotlipy
cchardet
feedparser
python-dateutil
uvloop
w3lib
yarl
];
pythonImportsCheck = [
"feedsearch_crawler"
];
meta = with lib; {
homepage = "https://feedsearch.dev";
description = "Crawl sites for RSS, Atom, and JSON feeds";
license = licenses.mit;
maintainers = with maintainers; [ colinsane ];
};
}

View File

@@ -1,22 +1,28 @@
{ makeWrapper
, gpodder
, linkFarm
, symlinkJoin
, writeShellScript
, config
}:
let
remove-extra = linkFarm "gpodder-remove-extra" [
{ name = "bin/gpodder-remove-extra"; path = ./remove_extra.py; }
];
in
# we use a symlinkJoin so that we can inherit the .desktop and icon files from the original gPodder
(symlinkJoin {
name = "gpodder-configured";
paths = [ gpodder ];
paths = [ gpodder remove-extra ];
buildInputs = [ makeWrapper ];
# gpodder keeps all its feeds in a sqlite3 database.
# we can configure the feeds externally by wrapping gpodder and just instructing it to import
# a feedlist every time we run it.
# repeat imports are deduplicated -- assuming network access (not sure how it behaves when disconnected).
# repeat imports are deduplicated by url, even when offline.
postBuild = ''
makeWrapper $out/bin/gpodder $out/bin/gpodder-configured \
--run "$out/bin/gpo import ~/.config/gpodderFeeds.opml"
--run "$out/bin/gpodder-remove-extra ~/.config/gpodderFeeds.opml" \
--run "$out/bin/gpo import ~/.config/gpodderFeeds.opml" \
# fix up the .desktop file to invoke our wrapped application
orig_desktop=$(readlink $out/share/applications/gpodder.desktop)

View File

@@ -0,0 +1,79 @@
#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p "python3.withPackages (ps: [gnome-feeds.listparser])" -p gpodder
from dataclasses import dataclass, field
import listparser
import subprocess
import sys
@dataclass(repr=True)
class Feed:
url: str
title: str # Optional
def __init__(self, url: str, title: str):
self.url = url
self.title = title if title else None
def __eq__(self, other: 'Feed') -> bool:
return self.url == other.url and \
(self.title == other.title or None in [self.title, other.title])
@dataclass(init=True)
class Partitioned:
has_not_wanted: list[Feed] = field(default_factory=list)
wanted_not_has: list[Feed] = field(default_factory=list)
intersection: list[Feed] = field(default_factory=list)
def wanted_feeds(opml_file: str):
parsed = listparser.parse(open(opml_file).read())
return [Feed(url=p['url'], title=p['title']) for p in parsed.feeds]
def has_feeds():
listing = subprocess.check_output(["gpo", "list"]).decode()
feeds = []
title = None
for line in listing.split("\n"):
if line.startswith("# "): # title
title = line[2:].strip()
elif line.startswith("http"): # feed URL:
feeds.append(Feed(url=line, title=title))
title = None
return feeds
def partition_feeds(wanted: list[Feed], has: list[Feed]) -> Partitioned:
p = Partitioned()
for f in wanted + has:
w, h = f in wanted, f in has
if h and not w:
p.has_not_wanted.append(f)
elif w and not h:
p.wanted_not_has.append(f)
else:
assert w and h
p.intersection.append(f)
return p
def remove_feed(feed: Feed):
subprocess.check_output(['gpo', 'unsubscribe', feed.url])
def rationalize_feeds(opml_file: str):
wanted = wanted_feeds(opml_file)
has = has_feeds()
partitioned = partition_feeds(wanted, has)
print("extra feeds:", "" if partitioned.has_not_wanted else "(none)")
for f in partitioned.has_not_wanted:
print(" ", f)
print()
for f in partitioned.has_not_wanted:
remove_feed(f)
if __name__ == "__main__":
wanted_opml, = sys.argv[1:]
rationalize_feeds(wanted_opml)

View File

@@ -5,7 +5,7 @@ with lib;
let
base = "6.1.0";
# set to empty if not a release candidate
rc = "-rc7";
rc = "-rc8";
in buildLinux (args // rec {
version = base + rc;
@@ -16,9 +16,15 @@ in buildLinux (args // rec {
extraMeta.branch = versions.majorMinor version;
src = fetchFromGitHub {
# HOW TO UPDATE:
# - `git fetch` from megous' github.
# - there should be some new tag, like `orange-pi-6.1-blah`. use that.
# - 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.
owner = "megous";
repo = "linux";
rev = "orange-pi-6.1-20221128-1027";
hash = "sha256-kEujs4v5rPHPYy4YLyEWHa1Bu0sxoXLgSvmOH9QPWos=";
rev = "orange-pi-6.1-20221211-1046";
hash = "sha256-TgFXH8bHWHs26rlf7a/zNO9zubFazC8Ie6J1gj4gLgw=";
};
} // (args.argsOverride or { }))

View File

@@ -1,55 +0,0 @@
(next: prev: rec {
#### my own, non-upstreamable packages:
sane-scripts = prev.callPackage ./sane-scripts { };
tow-boot-pinephone = prev.callPackage ./tow-boot-pinephone { };
tow-boot-rpi4 = prev.callPackage ./tow-boot-rpi4 { };
bootpart-uefi-x86_64 = prev.callPackage ./bootpart-uefi-x86_64 { };
bootpart-tow-boot-rpi-aarch64 = prev.callPackage ./bootpart-tow-boot-rpi-aarch64 {
# not sure why i can't just do `next.callPackage` instead
inherit tow-boot-rpi4;
};
bootpart-u-boot-rpi-aarch64 = prev.callPackage ./bootpart-u-boot-rpi-aarch64 {
# not sure why i can't just do `next.callPackage` instead
inherit ubootRaspberryPi4_64bit;
};
rtl8723cs-firmware = prev.callPackage ./rtl8723cs-firmware { };
linux-megous = prev.callPackage ./linux-megous {
kernelPatches = [
prev.kernelPatches.bridge_stp_helper
prev.kernelPatches.request_key_helper
];
};
sublime-music-mobile = prev.callPackage ./sublime-music-mobile { };
#### customized packages
fluffychat-moby = prev.callPackage ./fluffychat-moby { };
gpodder-configured = prev.callPackage ./gpodder-configured { };
# nixos-unstable pleroma is too far out-of-date for our db
pleroma = prev.callPackage ./pleroma { };
# jackett doesn't allow customization of the bind address: this will probably always be here.
jackett = prev.callPackage ./jackett { inherit (prev) jackett; };
# mozilla keeps nerfing itself and removing configuration options
firefox-unwrapped = prev.callPackage ./firefox-unwrapped { };
# patch rpi uboot with something that fixes USB HDD boot
ubootRaspberryPi4_64bit = prev.callPackage ./ubootRaspberryPi4_64bit { };
gocryptfs = prev.callPackage ./gocryptfs { inherit (prev) gocryptfs; };
browserpass = prev.callPackage ./browserpass { inherit (prev) browserpass; inherit sane-scripts; };
fractal-latest = prev.callPackage ./fractal-latest { };
#### TEMPORARY: PACKAGES WAITING TO BE UPSTREAMED
kaiteki = prev.callPackage ./kaiteki { };
lightdm-mobile-greeter = prev.callPackage ./lightdm-mobile-greeter { };
browserpass-extension = prev.callPackage ./browserpass-extension { };
gopass-native-messaging-host = prev.callPackage ./gopass-native-messaging-host { };
tokodon = prev.libsForQt5.callPackage ./tokodon { };
signaldctl = prev.callPackage ./signaldctl { };
splatmoji = prev.callPackage ./splatmoji { };
# trust-dns = prev.callPackage ./trust-dns { };
# kaiteki = prev.kaiteki;
})

View File

@@ -1,4 +1,5 @@
#!/usr/bin/env python
#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ps.natsort ps.requests ])"
"""
usage: sane-bt-search <query_string>
@@ -67,5 +68,6 @@ q = " ".join(sys.argv[1:])
client = Client()
res = client.query(q)
print(f"found {len(res)} result(s)")
for r in res[:5]:
print(r)

View File

@@ -1,7 +1,7 @@
to deploy:
```sh
nixos-rebuild --flake "./#servo" {build,switch}
nixos-rebuild --flake ".#servo" {build,switch}
```
if the target is the same as the host, nix will grab the hostname automatically:
@@ -20,7 +20,7 @@ nix flake show
## secrets
i use [sops](https://github.com/Mic92/sops-nix) for secrets.
see `modules/universal/secrets.nix` for some tips.
see `hosts/common/secrets.nix` for some tips.
## building images
@@ -34,31 +34,34 @@ refer to flake.nix for more details.
## building packages
to build one of the custom sane packages, just name it:
```sh
nix build ./#fluffychat-moby
build anything with
```
nix build .#<pkgname>
```
to build a nixpkg:
specifically, i pass the full package closure to the `legacyPackages` flake output. that includes both my own packages and upstream packages.
on the other hand the `packages` output contains only my own packages.
in addition, my packages are placed into both the global scope and a `sane` scope.
so use the scoped path when you want to be explicit.
```sh
nix build ./#nixpkgs.curl
```
to build a package for another platform:
```sh
nix build ./#packages.aarch64-linux.nixpkgs.ubootRaspberryPi4_64bit
nix build sane.linux-megous
```
## using this repo in your own config
i try to ensure everything in the `modules/` directory is hidden behind some enable flag or other.
it should be possible to copy that whole directory into your own config, and then selectively
populate what you want (like the impermenance paths, etc).
more practically, a lot of things in there still assume a user named `colin`, so you'll probably
want to patch it for your name -- or just use it as a reference.
this should be a pretty "standard" flake. just reference it, and import either
- `nixosModules.sane` (for the modules)
- `overlays.pkgs` (for the packages)
`nixosModules.sane` corresponds to everything in the `modules/` directory.
it's a mix of broad and narrow scope options.
e.g. `sane.fs` is a completely standalone thing,
whereas `sane.web-browser` is highly personalized and doesn't *really* make sense to export.
regardless of scope, i do try to ensure that everything in `modules/` is hidden behind some enable flag
so that the disorganization isn't that critical.
## contact