Compare commits
124 Commits
tx-to-desk
...
wip-doofne
Author | SHA1 | Date | |
---|---|---|---|
4b99607f7b | |||
0d99293b2f | |||
b3890b82dc | |||
3fc96a3e32 | |||
1af7b613bd | |||
4c8695aae8 | |||
d45e3fda5e | |||
456e0de872 | |||
7825ddc123 | |||
dd47a5083c | |||
14d5d9eb5a | |||
1f6f2399d6 | |||
b0ee12ba7b | |||
a6d268ca72 | |||
1ecc033ff5 | |||
c87dab93b3 | |||
53139a7cdf | |||
f37014a856 | |||
0237d3a144 | |||
656ad76f25 | |||
b7c71dc67b | |||
aaa40eae04 | |||
d8ed82cfdf | |||
0e73f95ab1 | |||
b1ba0cad03 | |||
4bcbfbc8aa | |||
0f6c9f3cde | |||
f4d806c0c2 | |||
6963998519 | |||
a63f6281c5 | |||
df0a8cf900 | |||
a4f5343fb5 | |||
c50a4d1d71 | |||
aadbeab3ac | |||
aafcf7b478 | |||
a78b840215 | |||
3c2347faba | |||
ebff35a378 | |||
1515f01384 | |||
60a5c61500 | |||
417b85450c | |||
2e0a3dc8ef | |||
3165c95d0f | |||
6dd4d9da3e | |||
5a086b359d | |||
a204f0a987 | |||
317251338c | |||
01cfed2438 | |||
ba0524d193 | |||
26a4f20f6c | |||
46f5a7e37d | |||
88a487f565 | |||
d037afd75c | |||
654858f8ff | |||
5abcc7d399 | |||
65823507ad | |||
63a88da3b4 | |||
734da36639 | |||
49ccf95fb3 | |||
e70d0f3c8e | |||
c00cccd429 | |||
02fdc91237 | |||
14616f9b61 | |||
f9d856b3bb | |||
d52db06ffe | |||
![]() |
dc2c31f220 | ||
52322e3207 | |||
26f1f2b581 | |||
74c188012a | |||
e0c741427e | |||
999a173001 | |||
330a64d820 | |||
2e2f5dd373 | |||
5561dde31d | |||
c3ae60d71b | |||
1c79209e23 | |||
6d1db1ee67 | |||
88d462764f | |||
8f634d9bb0 | |||
3e35210e4b | |||
04f4d330a8 | |||
ce60e53b9a | |||
3ff9f974a6 | |||
11e9ad5eca | |||
bf99a64b89 | |||
3b43562841 | |||
131e43e975 | |||
e34a9957e3 | |||
ea1a0b72b5 | |||
aab9ed0d35 | |||
f477370e4c | |||
b5fc8cfd4e | |||
4fdaacf8ad | |||
f1705686b8 | |||
0d0fa8b37f | |||
b5b39d1500 | |||
86482e922c | |||
111c69b368 | |||
60c13d34a7 | |||
823d064ab0 | |||
3f88d750c6 | |||
05f29ba01e | |||
2b11bac1eb | |||
86adc38537 | |||
b787289b39 | |||
63f3b8e89b | |||
448b8007ca | |||
9fc4119275 | |||
8f1332797d | |||
368184e24f | |||
c8e73d3f76 | |||
43da4955b7 | |||
46e9d5f758 | |||
66a012b555 | |||
fff965ab9b | |||
406adde549 | |||
c9b2699c9f | |||
f91d3e35f3 | |||
4712ba9f2d | |||
03b2f2a433 | |||
51b1a6e679 | |||
f148e5a580 | |||
079f945f38 | |||
29cc7e4676 |
25
README.md
25
README.md
@@ -2,6 +2,8 @@
|
||||
|
||||
# .❄️≡We|_c0m3 7o m`/ f14k≡❄️.
|
||||
|
||||
(er, it's not a flake anymore. welcome to my nix files.)
|
||||
|
||||
## What's Here
|
||||
|
||||
this is the top-level repo from which i configure/deploy all my NixOS machines:
|
||||
@@ -29,11 +31,7 @@ you might specifically be interested in these files (elaborated further in #key-
|
||||
|
||||
## Using This Repo In Your Own Config
|
||||
|
||||
this should be a pretty "standard" flake. just reference it, and import either
|
||||
- `nixosModules.sane` (for the modules)
|
||||
- `overlays.pkgs` (for the packages)
|
||||
|
||||
or follow the instructions [here][NUR] to use it via the Nix User Repositories.
|
||||
follow the instructions [here][NUR] to access my packages through the Nix User Repositories.
|
||||
|
||||
[NUR]: https://nur.nix-community.org/
|
||||
|
||||
@@ -41,19 +39,15 @@ or follow the instructions [here][NUR] to use it via the Nix User Repositories.
|
||||
- `doc/`
|
||||
- instructions for tasks i find myself doing semi-occasionally in this repo.
|
||||
- `hosts/`
|
||||
- the bulk of config which isn't factored with external use in mind.
|
||||
- configs which aren't factored with external use in mind.
|
||||
- that is, if you were to add this repo to a flake.nix for your own use,
|
||||
you won't likely be depending on anything in this directory.
|
||||
- `integrations/`
|
||||
- code intended for consumption by external tools (e.g. the Nix User Repos)
|
||||
- code intended for consumption by external tools (e.g. the Nix User Repos).
|
||||
- `modules/`
|
||||
- config which is gated behind `enable` flags, in similar style to nixpkgs'
|
||||
`nixos/` directory.
|
||||
- if you depend on this repo, it's most likely for something in this directory.
|
||||
- `nixpatches/`
|
||||
- literally, diffs i apply atop upstream nixpkgs before performing further eval.
|
||||
- config which is gated behind `enable` flags, in similar style to nixpkgs' `nixos/` directory.
|
||||
- if you depend on this repo for anything besides packages, it's most likely for something in this directory.
|
||||
- `overlays/`
|
||||
- exposed via the `overlays` output in `flake.nix`.
|
||||
- predominantly a list of `callPackage` directives.
|
||||
- `pkgs/`
|
||||
- derivations for things not yet packaged in nixpkgs.
|
||||
@@ -61,13 +55,12 @@ or follow the instructions [here][NUR] to use it via the Nix User Repositories.
|
||||
- inline code for wholly custom packages (e.g. `pkgs/additional/sane-scripts/` for CLI tools
|
||||
that are highly specific to my setup).
|
||||
- `scripts/`
|
||||
- scripts which aren't reachable on a deployed system, but may aid manual deployments
|
||||
- scripts which aren't reachable on a deployed system, but may aid manual deployments.
|
||||
- `secrets/`
|
||||
- encrypted keys, API tokens, anything which one or more of my machines needs
|
||||
read access to but shouldn't be world-readable.
|
||||
- not much to see here
|
||||
- not much to see here.
|
||||
- `templates/`
|
||||
- exposed via the `templates` output in `flake.nix`.
|
||||
- used to instantiate short-lived environments.
|
||||
- used to auto-fill the boiler-plate portions of new packages.
|
||||
|
||||
|
15
TODO.md
15
TODO.md
@@ -2,7 +2,6 @@
|
||||
- `rmDbusServices` may break sandboxing
|
||||
- e.g. if the package ships a systemd unit which references $out, then make-sandboxed won't properly update that unit.
|
||||
- `rmDbusServicesInPlace` is not affected
|
||||
- moby: touchscreen input is still enabled when screen is off
|
||||
- when moby wlan is explicitly set down (via ip link set wlan0 down), /var/lib/trust-dns/dhcp-configs doesn't get reset
|
||||
- `ip monitor` can detect those manual link state changes (NM-dispatcher it seems cannot)
|
||||
- or try dnsmasq?
|
||||
@@ -25,6 +24,8 @@
|
||||
- moby: bpf is effectively disabled?
|
||||
- `dmesg | grep 'systemd[1]: bpf-lsm: Failed to load BPF object: No such process'`
|
||||
- `dmesg | grep 'hid_bpf: error while preloading HID BPF dispatcher: -22'`
|
||||
- `s6` is not re-entrant
|
||||
- so if the desktop crashes, the login process from `unl0kr` fails to re-launch the GUI
|
||||
|
||||
## REFACTORING:
|
||||
- add import checks to my Python nix-shell scripts
|
||||
@@ -78,22 +79,21 @@
|
||||
- it adds like 50-70ms launch time _on my laptop_. i'd hate to know how much that is on the pinephone.
|
||||
- make dconf stuff less monolithic
|
||||
- i.e. per-app dconf profiles for those which need it. possible static config.
|
||||
- flatpak/spectrum has some stuff to proxy dconf per-app
|
||||
- canaries for important services
|
||||
- e.g. daily email checks; daily backup checks
|
||||
- integrate `nix check` into Gitea actions?
|
||||
|
||||
#### sudo-free world
|
||||
- `systemctl restart FOO`: needs `sudo`
|
||||
- `systemctl daemon-reload`: needs sudo
|
||||
- `watch ifconfig`: needs `SANEBOX_DISABLE=1`
|
||||
|
||||
### user experience
|
||||
- rofi: sort items case-insensitively
|
||||
- xdg-desktop-portal shouldn't kill children on exit
|
||||
- *maybe* a job for `setsid -f`?
|
||||
- replace starship prompt with something more efficient
|
||||
- watch `forkstat`: it does way too much
|
||||
- cleanup waybar so that it's not invoking playerctl every 2 seconds
|
||||
- cleanup waybar/nwg-panel so that it's not invoking playerctl every 2 seconds
|
||||
- nwg-panel: swaync icon is stuck as the refresh icon
|
||||
- nwg-panel: doesn't appear on all desktops
|
||||
- nwg-panel: doesn't know that virtual-desktop 10/TV exists
|
||||
- install apps:
|
||||
- display QR codes for WiFi endpoints: <https://linuxphoneapps.org/apps/noappid.wisperwind.wifi2qr/>
|
||||
- shopping list (not in nixpkgs): <https://linuxphoneapps.org/apps/ro.hume.cosmin.shoppinglist/>
|
||||
@@ -103,6 +103,7 @@
|
||||
- Gnome Highscore (retro games)?: <https://gitlab.gnome.org/World/highscore>
|
||||
- better maps for mobile (Osmin (QtQuick)? Pure Maps (Qt/Kirigami)?
|
||||
- note-taking app: <https://linuxphoneapps.org/categories/note-taking/>
|
||||
- Folio is nice, uses standard markdown, though it only supports flat repos
|
||||
- OSK overlay specifically for mobile gaming
|
||||
- i.e. mock joysticks, for use with SuperTux and SuperTuxKart
|
||||
- install mobile-friendly games:
|
||||
|
66
default.nix
66
default.nix
@@ -3,7 +3,65 @@
|
||||
#
|
||||
# the primary purpose of this file is so i can run `updateScript`s which expect
|
||||
# the root to be `default.nix`
|
||||
{ pkgs ? import <nixpkgs> {} }:
|
||||
pkgs.appendOverlays [
|
||||
(import ./overlays/all.nix)
|
||||
]
|
||||
{ }:
|
||||
let
|
||||
mkPkgs = args: (import ./pkgs/additional/nixpkgs args).extend
|
||||
(import ./overlays/all.nix);
|
||||
inherit (mkPkgs {}) lib;
|
||||
|
||||
evalHost = { name, system, branch ? "master", variant ? null }:
|
||||
let
|
||||
pkgs = mkPkgs { inherit system; variant = branch; };
|
||||
in pkgs.nixos (
|
||||
[
|
||||
(lib.optionalAttrs (variant == "light") {
|
||||
sane.maxBuildCost = 2;
|
||||
})
|
||||
(lib.optionalAttrs (variant == "min") {
|
||||
sane.maxBuildCost = 0;
|
||||
})
|
||||
(import ./hosts/instantiate.nix { hostName = name; })
|
||||
(import ./modules)
|
||||
pkgs.sops-nix.nixosModules.sops
|
||||
]
|
||||
);
|
||||
mkFlavoredHost = args: let
|
||||
host = evalHost args;
|
||||
# expose the toplevel nixos system as the toplevel attribute itself,
|
||||
# with nested aliases for other common build targets
|
||||
in host.config.system.build.toplevel.overrideAttrs (base: {
|
||||
passthru = (base.passthru or {}) // {
|
||||
config = host.config;
|
||||
fs = host.config.sane.fs;
|
||||
img = host.config.system.build.img;
|
||||
pkgs = host.config.system.build.pkgs;
|
||||
programs = lib.mapAttrs (_: p: p.package) host.config.sane.programs;
|
||||
toplevel = host.config.system.build.toplevel; #< self
|
||||
};
|
||||
});
|
||||
mkHost = args: {
|
||||
# TODO: swap order: $host-{next,staging}-{min,light}:
|
||||
# then lexicographically-adjacent targets would also have the minimal difference in closure,
|
||||
# and the order in which each target should be built is more evident
|
||||
"${args.name}" = mkFlavoredHost args;
|
||||
"${args.name}-next" = mkFlavoredHost args // { branch = "staging-next"; };
|
||||
"${args.name}-staging" = mkFlavoredHost args // { branch = "staging"; };
|
||||
"${args.name}-light" = mkFlavoredHost args // { variant = "light"; };
|
||||
"${args.name}-light-next" = mkFlavoredHost args // { variant = "light"; branch = "staging-next"; };
|
||||
"${args.name}-light-staging" = mkFlavoredHost args // { variant = "light"; branch = "staging"; };
|
||||
"${args.name}-min" = mkFlavoredHost args // { variant = "min"; };
|
||||
"${args.name}-min-next" = mkFlavoredHost args // { variant = "min"; branch = "staging-next"; };
|
||||
"${args.name}-min-staging" = mkFlavoredHost args // { variant = "min"; branch = "staging-staging"; };
|
||||
};
|
||||
|
||||
hosts = lib.foldl' (acc: host: acc // (mkHost host)) {} [
|
||||
{ name = "crappy"; system = "armv7l-linux"; }
|
||||
{ name = "desko"; system = "x86_64-linux"; }
|
||||
{ name = "lappy"; system = "x86_64-linux"; }
|
||||
{ name = "moby"; system = "aarch64-linux"; }
|
||||
{ name = "rescue"; system = "x86_64-linux"; }
|
||||
{ name = "servo"; system = "x86_64-linux"; }
|
||||
];
|
||||
in {
|
||||
inherit hosts;
|
||||
} // (mkPkgs {})
|
||||
|
7
flake.lock
generated
7
flake.lock
generated
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"nodes": {
|
||||
"root": {}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
586
flake.nix
586
flake.nix
@@ -1,586 +0,0 @@
|
||||
# FLAKE FEEDBACK:
|
||||
# - if flake inputs are meant to be human-readable, a human should be able to easily track them down given the URL.
|
||||
# - this is not the case with registry URLs, like `nixpkgs/nixos-22.11`.
|
||||
# - this is marginally the case with schemes like `github:nixos/nixpkgs`.
|
||||
# - given the *existing* `git+https://` scheme, i propose expressing github URLs similarly:
|
||||
# - `github+https://github.com/nixos/nixpkgs/tree/nixos-22.11`
|
||||
# - this would allow for the same optimizations as today's `github:nixos/nixpkgs`, but without obscuring the source.
|
||||
# a code reader could view the source being referenced simply by clicking the https:// portion of that URI.
|
||||
# - need some way to apply local patches to inputs.
|
||||
#
|
||||
#
|
||||
# DEVELOPMENT DOCS:
|
||||
# - Flake docs: <https://nixos.wiki/wiki/Flakes>
|
||||
# - Flake RFC: <https://github.com/tweag/rfcs/blob/flakes/rfcs/0049-flakes.md>
|
||||
# - Discussion: <https://github.com/NixOS/rfcs/pull/49>
|
||||
# - <https://serokell.io/blog/practical-nix-flakes>
|
||||
#
|
||||
#
|
||||
# COMMON OPERATIONS:
|
||||
# - update a specific flake input:
|
||||
# - `nix flake lock --update-input nixpkgs`
|
||||
|
||||
{
|
||||
outputs = {
|
||||
self,
|
||||
}@inputs:
|
||||
let
|
||||
inherit (builtins) attrNames elem listToAttrs map mapAttrs;
|
||||
# redefine some nixpkgs `lib` functions to avoid the infinite recursion
|
||||
# of if we tried to use patched `nixpkgs.lib` as part of the patching process.
|
||||
mapAttrs' = f: set:
|
||||
listToAttrs (map (attr: f attr set.${attr}) (attrNames set));
|
||||
optionalAttrs = cond: attrs: if cond then attrs else {};
|
||||
# mapAttrs but without the `name` argument
|
||||
mapAttrValues = f: mapAttrs (_: f);
|
||||
|
||||
nixpkgs' = import ./pkgs/additional/nixpkgs;
|
||||
nixpkgsUnpatched = nixpkgs' { doPatch = false; localSystem = "x86_64-linux"; };
|
||||
nixpkgsCompiledBy = { system, variant ? "master" }:
|
||||
(nixpkgs' { inherit variant system; }).legacyPackages."${system}";
|
||||
|
||||
evalHost = { name, local, target, variant ? null, nixpkgs ? nixpkgs' { localSystem = local; system = target;} }: nixpkgs.nixos (
|
||||
[
|
||||
(optionalAttrs (variant == "light") {
|
||||
sane.maxBuildCost = 2;
|
||||
})
|
||||
(optionalAttrs (variant == "min") {
|
||||
sane.maxBuildCost = 0;
|
||||
})
|
||||
(import ./hosts/instantiate.nix { hostName = name; })
|
||||
(import ./modules)
|
||||
(nixpkgs.appendOverlays [ self.overlays.pkgs ]).sops-nix.nixosModules.sops
|
||||
{
|
||||
nixpkgs.overlays = [
|
||||
self.overlays.sane-all
|
||||
];
|
||||
}
|
||||
]
|
||||
);
|
||||
in {
|
||||
nixosConfigurations = let
|
||||
hosts = {
|
||||
servo = { name = "servo"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
||||
desko = { name = "desko"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
||||
desko-light = { name = "desko"; local = "x86_64-linux"; target = "x86_64-linux"; variant = "light"; };
|
||||
lappy = { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
||||
lappy-light = { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; variant = "light"; };
|
||||
lappy-min = { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; variant = "min"; };
|
||||
moby = { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; };
|
||||
moby-light = { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; variant = "light"; };
|
||||
moby-min = { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; variant = "min"; };
|
||||
# crappy is technically armv7a, and armv7l uses only a _subset_ of the available ISA.
|
||||
# but it's not as widely cached.
|
||||
crappy = { name = "crappy"; local = "x86_64-linux"; target = "armv7l-linux"; };
|
||||
crappy-min = { name = "crappy"; local = "x86_64-linux"; target = "armv7l-linux"; variant = "min"; };
|
||||
crappy-7a = { name = "crappy"; local = "x86_64-linux"; target = "armv7a-linux"; variant = "min"; };
|
||||
rescue = { name = "rescue"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
||||
};
|
||||
hostsNext = mapAttrs' (h: v: {
|
||||
name = "${h}-next";
|
||||
value = v // {
|
||||
nixpkgs = nixpkgs' {
|
||||
localSystem = v.local;
|
||||
system = v.target;
|
||||
variant = "staging-next";
|
||||
};
|
||||
};
|
||||
}) hosts;
|
||||
hostsStaging = mapAttrs' (h: v: {
|
||||
name = "${h}-staging";
|
||||
value = v // {
|
||||
nixpkgs = nixpkgs' {
|
||||
localSystem = v.local;
|
||||
system = v.target;
|
||||
variant = "staging";
|
||||
};
|
||||
};
|
||||
}) hosts;
|
||||
in mapAttrValues evalHost (
|
||||
hosts // hostsNext // hostsStaging
|
||||
);
|
||||
|
||||
# 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)
|
||||
# - resize the root partition (use cfdisk)
|
||||
# - mount the part
|
||||
# - chown root:nixbld <part>/nix/store
|
||||
# - chown root:root -R <part>/nix/store/*
|
||||
# - chown root:root -R <part>/persist # if using impermanence
|
||||
# - populate any important things (persist/, home/colin/.ssh, etc)
|
||||
# - boot
|
||||
# - 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`
|
||||
imgs = mapAttrValues (host: host.config.system.build.img) self.nixosConfigurations;
|
||||
|
||||
# unofficial output
|
||||
hostConfigs = mapAttrValues (host: host.config) self.nixosConfigurations;
|
||||
hostSystems = mapAttrValues (host: host.config.system.build.toplevel) self.nixosConfigurations;
|
||||
hostPkgs = mapAttrValues (host: host.config.system.build.pkgs) self.nixosConfigurations;
|
||||
hostPrograms = mapAttrValues (host: mapAttrValues (p: p.package) host.config.sane.programs) self.nixosConfigurations;
|
||||
|
||||
overlays = {
|
||||
# N.B.: `nix flake check` requires every overlay to take `final: prev:` at defn site,
|
||||
# hence the weird redundancy.
|
||||
default = final: prev: self.overlays.pkgs final prev;
|
||||
sane-all = final: prev: import ./overlays/all.nix final prev;
|
||||
pkgs = final: prev: import ./overlays/pkgs.nix final prev;
|
||||
preferences = final: prev: import ./overlays/preferences.nix final prev;
|
||||
};
|
||||
|
||||
# this includes both our native packages and all the nixpkgs packages.
|
||||
legacyPackages =
|
||||
let
|
||||
allPkgsFor = variant: additionalOverlays: system:
|
||||
(nixpkgs' { inherit system variant; localSystem = "x86_64-linux"; })
|
||||
.appendOverlays (
|
||||
[
|
||||
self.overlays.pkgs
|
||||
] ++ additionalOverlays
|
||||
);
|
||||
allPkgsFor' = system: allPkgsFor
|
||||
"master"
|
||||
[(self: super: {
|
||||
# build `pkgsNext.FOO` to build the package FOO from nixpkgs staging-next branch
|
||||
pkgsNext = allPkgsFor "staging-next" [] system;
|
||||
pkgsStaging = allPkgsFor "staging" [] system;
|
||||
})]
|
||||
system
|
||||
;
|
||||
in {
|
||||
x86_64-linux = allPkgsFor' "x86_64-linux";
|
||||
aarch64-linux = allPkgsFor' "aarch64-linux";
|
||||
};
|
||||
|
||||
# extract only our own packages from the full set.
|
||||
# because of `nix flake check`, we flatten the package set and only surface x86_64-linux packages.
|
||||
packages = mapAttrs
|
||||
(system: passthruPkgs: passthruPkgs.lib.filterAttrs
|
||||
(name: pkg:
|
||||
# keep only packages which will pass `nix flake check`, i.e. keep only:
|
||||
# - derivations (not package sets)
|
||||
# - packages that build for the given platform
|
||||
(! elem name [ "feeds" "pythonPackagesExtensions" ])
|
||||
&& (passthruPkgs.lib.meta.availableOn passthruPkgs.stdenv.hostPlatform pkg)
|
||||
)
|
||||
(
|
||||
import ./pkgs { pkgs = passthruPkgs; }
|
||||
)
|
||||
)
|
||||
# self.legacyPackages;
|
||||
{
|
||||
x86_64-linux = nixpkgs' { localSystem = "x86_64-linux"; };
|
||||
}
|
||||
;
|
||||
|
||||
apps."x86_64-linux" =
|
||||
let
|
||||
pkgs = self.legacyPackages."x86_64-linux";
|
||||
sanePkgs = import ./pkgs { inherit pkgs; };
|
||||
deployScript = host: addr: action: pkgs.writeShellScript "deploy-${host}" ''
|
||||
set -e
|
||||
|
||||
host="${host}"
|
||||
addr="${addr}"
|
||||
action="${if action != null then action else ""}"
|
||||
runOnTarget() {
|
||||
# run the command ($@) on the machine we're deploying to.
|
||||
# if that's a remote machine, then do it via ssh, else local shell.
|
||||
if [ -n "$addr" ]; then
|
||||
ssh "$addr" "$@"
|
||||
else
|
||||
"$@"
|
||||
fi
|
||||
}
|
||||
|
||||
nix build ".#nixosConfigurations.$host.config.system.build.toplevel" --out-link "./build/result-$host" "$@"
|
||||
storePath="$(readlink ./build/result-$host)"
|
||||
|
||||
# mimic `nixos-rebuild --target-host`, in effect:
|
||||
# - nix-copy-closure ...
|
||||
# - nix-env --set ...
|
||||
# - switch-to-configuration <boot|dry-activate|switch|test|>
|
||||
# avoid the actual `nixos-rebuild` for a few reasons:
|
||||
# - fewer nix evals
|
||||
# - more introspectability and debuggability
|
||||
# - sandbox friendliness (especially: `git` doesn't have to be run as root)
|
||||
|
||||
if [ -n "$addr" ]; then
|
||||
sudo nix store sign -r -k /run/secrets/nix_signing_key "$storePath"
|
||||
# add more `-v` for more verbosity (up to 5).
|
||||
# builders-use-substitutes false: optimizes so that the remote machine doesn't try to get paths from its substituters.
|
||||
# we already have all paths here, and the remote substitution is slow to check and SERIOUSLY flaky on moby in particular.
|
||||
nix copy -vv --option builders-use-substitutes false --to "ssh-ng://$addr" "$storePath"
|
||||
fi
|
||||
|
||||
if [ -n "$action" ]; then
|
||||
runOnTarget sudo nix-env -p /nix/var/nix/profiles/system --set "$storePath"
|
||||
runOnTarget sudo "$storePath/bin/switch-to-configuration" "$action"
|
||||
fi
|
||||
'';
|
||||
deployApp = host: addr: action: {
|
||||
type = "app";
|
||||
program = ''${deployScript host addr action}'';
|
||||
};
|
||||
|
||||
# pkg updating.
|
||||
# a cleaner alternative lives here: <https://discourse.nixos.org/t/how-can-i-run-the-updatescript-of-personal-packages/25274/2>
|
||||
# mkUpdater :: [ String ] -> { type = "app"; program = path; }
|
||||
mkUpdater = attrPath: {
|
||||
type = "app";
|
||||
program = let
|
||||
pkg = pkgs.lib.getAttrFromPath attrPath sanePkgs;
|
||||
strAttrPath = pkgs.lib.concatStringsSep "." attrPath;
|
||||
commandArgv = pkg.updateScript.command or pkg.updateScript;
|
||||
command = pkgs.lib.escapeShellArgs commandArgv;
|
||||
in builtins.toString (pkgs.writeShellScript "update-${strAttrPath}" ''
|
||||
set -x
|
||||
env UPDATE_NIX_NAME=${pkg.name} UPDATE_NIX_PNAME=${pkg.pname} UPDATE_NIX_OLD_VERSION=${pkg.version} UPDATE_NIX_ATTR_PATH=${strAttrPath} ${command}
|
||||
'');
|
||||
};
|
||||
mkUpdatersNoAliases = opts: basePath: pkgs.lib.concatMapAttrs
|
||||
(name: pkg:
|
||||
if pkg.recurseForDerivations or false then {
|
||||
"${name}" = mkUpdaters opts (basePath ++ [ name ]);
|
||||
} else if pkg.updateScript or null != null then {
|
||||
"${name}" = mkUpdater (basePath ++ [ name ]);
|
||||
} else {}
|
||||
)
|
||||
(pkgs.lib.getAttrFromPath basePath sanePkgs);
|
||||
mkUpdaters = { ignore ? [], flakePrefix ? [] }@opts: basePath:
|
||||
let
|
||||
updaters = mkUpdatersNoAliases opts basePath;
|
||||
invokeUpdater = name: pkg:
|
||||
let
|
||||
fullPath = basePath ++ [ name ];
|
||||
doUpdateByDefault = !builtins.elem fullPath ignore;
|
||||
|
||||
# in case `name` has a `.` in it, we have to quote it
|
||||
escapedPath = builtins.map (p: ''"${p}"'') fullPath;
|
||||
updatePath = builtins.concatStringsSep "." (flakePrefix ++ escapedPath);
|
||||
in pkgs.lib.optionalString doUpdateByDefault (
|
||||
pkgs.lib.escapeShellArgs [
|
||||
"nix" "run" ".#${updatePath}"
|
||||
]
|
||||
);
|
||||
in {
|
||||
type = "app";
|
||||
# top-level app just invokes the updater of everything one layer below it
|
||||
program = builtins.toString (pkgs.writeShellScript
|
||||
(builtins.concatStringsSep "-" (flakePrefix ++ basePath))
|
||||
(builtins.concatStringsSep
|
||||
"\n"
|
||||
(pkgs.lib.mapAttrsToList invokeUpdater updaters)
|
||||
)
|
||||
);
|
||||
} // updaters;
|
||||
in {
|
||||
help = {
|
||||
type = "app";
|
||||
program = let
|
||||
helpMsg = builtins.toFile "nixos-config-help-message" ''
|
||||
commands:
|
||||
- `nix run '.#help'`
|
||||
- show this message
|
||||
- `nix run '.#update.pkgs'`
|
||||
- updates every package
|
||||
- `nix run '.#update.feeds'`
|
||||
- updates metadata for all feeds
|
||||
- `nix run '.#init-feed' <url>`
|
||||
- `nix run '.#deploy.{desko,lappy,moby,servo}[-light|-test]' [nix args ...]`
|
||||
- build and deploy the host
|
||||
- `nix run '.#preDeploy.{desko,lappy,moby,servo}[-light]' [nix args ...]`
|
||||
- copy closures to a host, but don't activate it
|
||||
- or `nix run '.#preDeploy'` to target all hosts
|
||||
- `nix run '.#check'`
|
||||
- make sure all systems build; NUR evaluates
|
||||
- `nix run '.#bench'`
|
||||
- benchmark the eval time of common targets this flake provides
|
||||
|
||||
specific build targets of interest:
|
||||
- `nix build '.#imgs.rescue'`
|
||||
'';
|
||||
in builtins.toString (pkgs.writeShellScript "nixos-config-help" ''
|
||||
cat ${helpMsg}
|
||||
echo ""
|
||||
echo "complete flake structure:"
|
||||
nix flake show --option allow-import-from-derivation true
|
||||
'');
|
||||
};
|
||||
# wrangle some names to get package updaters which refer back into the flake, but also conditionally ignore certain paths (e.g. sane.feeds).
|
||||
# TODO: better design
|
||||
update = rec {
|
||||
_impl.pkgs.sane = mkUpdaters { flakePrefix = [ "update" "_impl" "pkgs" ]; ignore = [ [ "sane" "feeds" ] ]; } [ "sane" ];
|
||||
pkgs = _impl.pkgs.sane;
|
||||
_impl.feeds.sane.feeds = mkUpdaters { flakePrefix = [ "update" "_impl" "feeds" ]; } [ "sane" "feeds" ];
|
||||
feeds = _impl.feeds.sane.feeds;
|
||||
};
|
||||
|
||||
init-feed = {
|
||||
type = "app";
|
||||
program = "${pkgs.feeds.init-feed}";
|
||||
};
|
||||
|
||||
deploy = {
|
||||
desko = deployApp "desko" "desko" "switch";
|
||||
desko-light = deployApp "desko-light" "desko" "switch";
|
||||
lappy = deployApp "lappy" "lappy" "switch";
|
||||
lappy-light = deployApp "lappy-light" "lappy" "switch";
|
||||
lappy-min = deployApp "lappy-min" "lappy" "switch";
|
||||
moby = deployApp "moby" "moby" "switch";
|
||||
moby-light = deployApp "moby-light" "moby" "switch";
|
||||
moby-min = deployApp "moby-min" "moby" "switch";
|
||||
moby-test = deployApp "moby" "moby" "test";
|
||||
servo = deployApp "servo" "servo" "switch";
|
||||
|
||||
# like `nixos-rebuild --flake . switch`
|
||||
self = deployApp "$(hostname)" "" "switch";
|
||||
self-light = deployApp "$(hostname)-light" "" "switch";
|
||||
self-min = deployApp "$(hostname)-min" "" "switch";
|
||||
|
||||
type = "app";
|
||||
program = builtins.toString (pkgs.writeShellScript "deploy-all" ''
|
||||
nix run '.#deploy.lappy'
|
||||
nix run '.#deploy.moby'
|
||||
nix run '.#deploy.desko'
|
||||
nix run '.#deploy.servo'
|
||||
'');
|
||||
};
|
||||
preDeploy = {
|
||||
# build the host and copy the runtime closure to that host, but don't activate it.
|
||||
desko = deployApp "desko" "desko" null;
|
||||
desko-light = deployApp "desko-light" "desko" null;
|
||||
lappy = deployApp "lappy" "lappy" null;
|
||||
lappy-light = deployApp "lappy-light" "lappy" null;
|
||||
lappy-min = deployApp "lappy-min" "lappy" null;
|
||||
moby = deployApp "moby" "moby" null;
|
||||
moby-light = deployApp "moby-light" "moby" null;
|
||||
moby-min = deployApp "moby-min" "moby" null;
|
||||
servo = deployApp "servo" "servo" null;
|
||||
type = "app";
|
||||
program = builtins.toString (pkgs.writeShellScript "predeploy-all" ''
|
||||
# copy the -min/-light variants first; this might be run while waiting on a full build. or the full build failed.
|
||||
nix run '.#preDeploy.moby-min' -- "$@"
|
||||
nix run '.#preDeploy.lappy-min' -- "$@"
|
||||
nix run '.#preDeploy.moby-light' -- "$@"
|
||||
nix run '.#preDeploy.lappy-light' -- "$@"
|
||||
nix run '.#preDeploy.desko-light' -- "$@"
|
||||
nix run '.#preDeploy.lappy' -- "$@"
|
||||
nix run '.#preDeploy.servo' -- "$@"
|
||||
nix run '.#preDeploy.moby' -- "$@"
|
||||
nix run '.#preDeploy.desko' -- "$@"
|
||||
'');
|
||||
};
|
||||
|
||||
sync = {
|
||||
type = "app";
|
||||
program = builtins.toString (pkgs.writeShellScript "sync-all" ''
|
||||
RC_lappy=$(nix run '.#sync.lappy' -- "$@")
|
||||
RC_moby=$(nix run '.#sync.moby' -- "$@")
|
||||
RC_desko=$(nix run '.#sync.desko' -- "$@")
|
||||
|
||||
echo "lappy: $RC_lappy"
|
||||
echo "moby: $RC_moby"
|
||||
echo "desko: $RC_desko"
|
||||
'');
|
||||
};
|
||||
|
||||
sync.desko = {
|
||||
# copy music from servo to desko
|
||||
# can run this from any device that has ssh access to desko and servo
|
||||
type = "app";
|
||||
program = builtins.toString (pkgs.writeShellScript "sync-to-desko" ''
|
||||
sudo mount /mnt/desko/home
|
||||
${pkgs.sane-scripts.sync-music}/bin/sane-sync-music --compat /mnt/servo/media/Music /mnt/desko/home/Music "$@"
|
||||
'');
|
||||
};
|
||||
|
||||
sync.lappy = {
|
||||
# copy music from servo to lappy
|
||||
# can run this from any device that has ssh access to lappy and servo
|
||||
type = "app";
|
||||
program = builtins.toString (pkgs.writeShellScript "sync-to-lappy" ''
|
||||
sudo mount /mnt/lappy/home
|
||||
${pkgs.sane-scripts.sync-music}/bin/sane-sync-music --compress --compat /mnt/servo/media/Music /mnt/lappy/home/Music "$@"
|
||||
'');
|
||||
};
|
||||
|
||||
sync.moby = {
|
||||
# copy music from servo to moby
|
||||
# can run this from any device that has ssh access to moby and servo
|
||||
type = "app";
|
||||
program = builtins.toString (pkgs.writeShellScript "sync-to-moby" ''
|
||||
sudo mount /mnt/moby/home
|
||||
sudo mount /mnt/desko/home
|
||||
sudo mount /mnt/servo/media/Books
|
||||
# copy photos/screenshots from moby to desko:
|
||||
${pkgs.rsync}/bin/rsync -arv --exclude servo-macros /mnt/moby/home/Pictures/ /mnt/desko/home/Pictures/moby/
|
||||
# copy books from servo to moby; delete old/untracked ones, but keep KOreader state files (sdr)
|
||||
${pkgs.rsync}/bin/rsync -arv --delete --exclude unprocessed --exclude '*.sdr' /mnt/servo/media/Books/ /mnt/moby/home/Books/local/servo/
|
||||
# N.B.: limited by network/disk -> reduce job count to improve pause/resume behavior
|
||||
${pkgs.sane-scripts.sync-music}/bin/sane-sync-music --compress --compat --jobs 4 /mnt/servo/media/Music /mnt/moby/home/Music "$@"
|
||||
'');
|
||||
};
|
||||
|
||||
check = {
|
||||
type = "app";
|
||||
program = builtins.toString (pkgs.writeShellScript "check-all" ''
|
||||
nix run '.#check.nur'
|
||||
RC0=$?
|
||||
nix run '.#check.hostConfigs'
|
||||
RC1=$?
|
||||
nix run '.#check.rescue'
|
||||
RC2=$?
|
||||
echo "nur: $RC0"
|
||||
echo "hostConfigs: $RC1"
|
||||
echo "rescue: $RC2"
|
||||
exit $(($RC0 | $RC1 | $RC2))
|
||||
'');
|
||||
};
|
||||
|
||||
check.nur = {
|
||||
# `nix run '.#check-nur'`
|
||||
# validates that my repo can be included in the Nix User Repository
|
||||
type = "app";
|
||||
program = builtins.toString (pkgs.writeShellScript "check-nur" ''
|
||||
cd ${./.}/integrations/nur
|
||||
NIX_PATH= NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM=1 nix-env -f . -qa \* --meta --xml \
|
||||
--allowed-uris https://static.rust-lang.org \
|
||||
--option restrict-eval true \
|
||||
--option allow-import-from-derivation true \
|
||||
--drv-path --show-trace \
|
||||
-I nixpkgs=${nixpkgsUnpatched} \
|
||||
-I nixpkgs-overlays=${./.}/hosts/common/nix/overlay \
|
||||
-I ../../ \
|
||||
| tee # tee to prevent interactive mode
|
||||
'');
|
||||
};
|
||||
|
||||
check.hostConfigs = {
|
||||
type = "app";
|
||||
program = let
|
||||
checkHost = host: let
|
||||
shellHost = pkgs.lib.replaceStrings [ "-" ] [ "_" ] host;
|
||||
in ''
|
||||
nix build -v '.#nixosConfigurations.${host}.config.system.build.toplevel' --out-link ./build/result-${host} -j2 "$@"
|
||||
RC_${shellHost}=$?
|
||||
'';
|
||||
in builtins.toString (pkgs.writeShellScript
|
||||
"check-host-configs"
|
||||
''
|
||||
# build minimally-usable hosts first, then their full image.
|
||||
# this gives me a minimal image i can deploy or copy over, early.
|
||||
${checkHost "lappy-min"}
|
||||
${checkHost "moby-min"}
|
||||
|
||||
${checkHost "desko-light"}
|
||||
${checkHost "moby-light"}
|
||||
${checkHost "lappy-light"}
|
||||
|
||||
${checkHost "desko"}
|
||||
${checkHost "lappy"}
|
||||
${checkHost "servo"}
|
||||
${checkHost "moby"}
|
||||
${checkHost "rescue"}
|
||||
|
||||
# still want to build the -light variants first so as to avoid multiple simultaneous webkitgtk builds
|
||||
${checkHost "desko-light-next"}
|
||||
${checkHost "moby-light-next"}
|
||||
|
||||
${checkHost "desko-next"}
|
||||
${checkHost "lappy-next"}
|
||||
${checkHost "servo-next"}
|
||||
${checkHost "moby-next"}
|
||||
${checkHost "rescue-next"}
|
||||
|
||||
echo "desko: $RC_desko"
|
||||
echo "lappy: $RC_lappy"
|
||||
echo "servo: $RC_servo"
|
||||
echo "moby: $RC_moby"
|
||||
echo "rescue: $RC_rescue"
|
||||
|
||||
echo "desko-next: $RC_desko_next"
|
||||
echo "lappy-next: $RC_lappy_next"
|
||||
echo "servo-next: $RC_servo_next"
|
||||
echo "moby-next: $RC_moby_next"
|
||||
echo "rescue-next: $RC_rescue_next"
|
||||
|
||||
# i don't really care if the -next hosts fail. i build them mostly to keep the cache fresh/ready
|
||||
exit $(($RC_desko | $RC_lappy | $RC_servo | $RC_moby | $RC_rescue))
|
||||
''
|
||||
);
|
||||
};
|
||||
|
||||
check.rescue = {
|
||||
type = "app";
|
||||
program = builtins.toString (pkgs.writeShellScript "check-rescue" ''
|
||||
nix build -v '.#imgs.rescue' --out-link ./build/result-rescue-img -j2
|
||||
'');
|
||||
};
|
||||
|
||||
bench = {
|
||||
type = "app";
|
||||
program = builtins.toString (pkgs.writeShellScript "bench" ''
|
||||
doBench() {
|
||||
attrPath="$1"
|
||||
shift
|
||||
echo -n "benchmarking eval of '$attrPath'... "
|
||||
/run/current-system/sw/bin/time -f "%e sec" -o /dev/stdout \
|
||||
nix eval --no-eval-cache --quiet --raw ".#$attrPath" --apply 'result: if result != null then "" else "unexpected null"' $@ 2> /dev/null
|
||||
}
|
||||
|
||||
if [ -n "$1" ]; then
|
||||
doBench "$@"
|
||||
else
|
||||
doBench hostConfigs
|
||||
doBench hostConfigs.lappy
|
||||
doBench hostConfigs.lappy.sane.programs
|
||||
doBench hostConfigs.lappy.sane.users.colin
|
||||
doBench hostConfigs.lappy.sane.fs
|
||||
doBench hostConfigs.lappy.environment.systemPackages
|
||||
fi
|
||||
'');
|
||||
};
|
||||
};
|
||||
|
||||
templates = {
|
||||
env.python-data = {
|
||||
# initialize with:
|
||||
# - `nix flake init -t '/home/colin/dev/nixos/#env.python-data'`
|
||||
# then enter with:
|
||||
# - `nix develop`
|
||||
path = ./templates/env/python-data;
|
||||
description = "python environment for data processing";
|
||||
};
|
||||
|
||||
pkgs.make = {
|
||||
# initialize with:
|
||||
# - `nix flake init -t '/home/colin/dev/nixos/#pkgs.make'`
|
||||
path = ./templates/pkgs/make;
|
||||
description = "default Makefile-based derivation";
|
||||
};
|
||||
pkgs.python = {
|
||||
# initialize with:
|
||||
# - `nix flake init -t '/home/colin/dev/nixos/#pkgs.python'`
|
||||
path = ./templates/pkgs/python;
|
||||
description = "python package";
|
||||
};
|
||||
pkgs.rust-inline = {
|
||||
# initialize with:
|
||||
# - `nix flake init -t '/home/colin/dev/nixos/#pkgs.rust-inline'`
|
||||
path = ./templates/pkgs/rust-inline;
|
||||
description = "rust package and development environment (inline rust sources)";
|
||||
};
|
||||
pkgs.rust = {
|
||||
# initialize with:
|
||||
# - `nix flake init -t '/home/colin/dev/nixos/#pkgs.rust'`
|
||||
path = ./templates/pkgs/rust;
|
||||
description = "rust package fit to ship in nixpkgs";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@@ -12,6 +12,7 @@
|
||||
|
||||
users.users.colin.initialPassword = "147147";
|
||||
sane.programs.sway.enableFor.user.colin = true;
|
||||
|
||||
sane.programs.calls.enableFor.user.colin = false;
|
||||
sane.programs.consoleMediaUtils.enableFor.user.colin = true;
|
||||
sane.programs.epiphany.enableFor.user.colin = true;
|
||||
@@ -21,6 +22,12 @@
|
||||
sane.programs.signal-desktop.enableFor.user.colin = false;
|
||||
sane.programs.wike.enableFor.user.colin = true;
|
||||
|
||||
sane.programs.dino.config.autostart = false;
|
||||
sane.programs.dissent.config.autostart = false;
|
||||
sane.programs.fractal.config.autostart = false;
|
||||
|
||||
# sane.programs.guiApps.enableFor.user.colin = false;
|
||||
|
||||
# sane.programs.pcGuiApps.enableFor.user.colin = false; #< errors!
|
||||
|
||||
sane.programs.blueberry.enableFor.user.colin = false; # bluetooth manager: doesn't cross compile!
|
||||
|
@@ -35,6 +35,11 @@
|
||||
sane.programs."gnome.geary".config.autostart = true;
|
||||
sane.programs.signal-desktop.config.autostart = true;
|
||||
|
||||
sane.programs.nwg-panel.config = {
|
||||
battery = false;
|
||||
brightness = false;
|
||||
};
|
||||
|
||||
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
||||
|
||||
# needed to use libimobiledevice/ifuse, for iphone sync
|
||||
|
@@ -3,9 +3,19 @@
|
||||
let
|
||||
portOpts = with lib; types.submodule {
|
||||
options = {
|
||||
visibleTo.ovpn = mkOption {
|
||||
visibleTo.ovpns = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
whether to forward inbound traffic on the OVPN vpn port to the corresponding localhost port.
|
||||
'';
|
||||
};
|
||||
visibleTo.doof = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
whether to forward inbound traffic on the doofnet vpn port to the corresponding localhost port.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -13,7 +23,7 @@ in
|
||||
{
|
||||
options = with lib; {
|
||||
sane.ports.ports = mkOption {
|
||||
# add the `visibleTo.ovpn` option
|
||||
# add the `visibleTo.{doof,ovpns}` options
|
||||
type = types.attrsOf portOpts;
|
||||
};
|
||||
};
|
||||
@@ -40,18 +50,16 @@ in
|
||||
|
||||
# tun-sea config
|
||||
sane.dns.zones."uninsane.org".inet.A."doof.tunnel" = "205.201.63.12";
|
||||
sane.dns.zones."uninsane.org".inet.AAAA."doof.tunnel" = "2602:fce8:106::51";
|
||||
networking.wireguard.interfaces.wg-doof = let
|
||||
ip = "${pkgs.iproute2}/bin/ip";
|
||||
in {
|
||||
# sane.dns.zones."uninsane.org".inet.AAAA."doof.tunnel" = "2602:fce8:106::51"; #< TODO: enable IPv6
|
||||
networking.wireguard.interfaces.wg-doof = {
|
||||
privateKeyFile = config.sops.secrets.wg_doof_privkey.path;
|
||||
# wg is active only in this namespace.
|
||||
# run e.g. ip netns exec doof <some command like ping/curl/etc, it'll go through wg>
|
||||
# sudo ip netns exec doof ping www.google.com
|
||||
interfaceNamespace = "doof";
|
||||
ips = [
|
||||
"205.201.63.12/32"
|
||||
"2602:fce8:106::51/128"
|
||||
"205.201.63.12"
|
||||
# "2602:fce8:106::51/128" #< TODO: enable IPv6
|
||||
];
|
||||
peers = [
|
||||
{
|
||||
@@ -63,45 +71,24 @@ in
|
||||
persistentKeepalive = 25; #< keep the NAT alive
|
||||
}
|
||||
];
|
||||
preSetup = ''
|
||||
${ip} netns add doof || (test -e /run/netns/doof && echo "doof already exists")
|
||||
'';
|
||||
postShutdown = ''
|
||||
${ip} netns delete doof || echo "couldn't delete doof"
|
||||
'';
|
||||
};
|
||||
sane.netns.doof.hostVethIpv4 = "10.0.2.5";
|
||||
sane.netns.doof.netnsVethIpv4 = "10.0.2.6";
|
||||
sane.netns.doof.netnsPubIpv4 = "205.201.63.12";
|
||||
sane.netns.doof.routeTable = 12;
|
||||
|
||||
# OVPN CONFIG (https://www.ovpn.com):
|
||||
# DOCS: https://nixos.wiki/wiki/WireGuard
|
||||
# if you `systemctl restart wireguard-wg-ovpns`, make sure to also restart any other services in `NetworkNamespacePath = .../ovpns`.
|
||||
# TODO: why not create the namespace as a seperate operation (nix config for that?)
|
||||
networking.wireguard.enable = true;
|
||||
networking.wireguard.interfaces.wg-ovpns = let
|
||||
ip = "${pkgs.iproute2}/bin/ip";
|
||||
in-ns = "${ip} netns exec ovpns";
|
||||
iptables = "${pkgs.iptables}/bin/iptables";
|
||||
veth-host-ip = "10.0.1.5";
|
||||
veth-local-ip = "10.0.1.6";
|
||||
vpn-ip = "185.157.162.178";
|
||||
# DNS = 46.227.67.134, 192.165.9.158, 2a07:a880:4601:10f0:cd45::1, 2001:67c:750:1:cafe:cd45::1
|
||||
vpn-dns = "46.227.67.134";
|
||||
bridgePort = port: proto: ''
|
||||
${in-ns} ${iptables} -A PREROUTING -t nat -p ${proto} --dport ${port} -m iprange --dst-range ${vpn-ip} \
|
||||
-j DNAT --to-destination ${veth-host-ip}
|
||||
'';
|
||||
bridgeStatements = lib.foldlAttrs
|
||||
(acc: port: portCfg: acc ++ (builtins.map (bridgePort port) portCfg.protocol))
|
||||
[]
|
||||
config.sane.ports.ports;
|
||||
in {
|
||||
networking.wireguard.interfaces.wg-ovpns = {
|
||||
privateKeyFile = config.sops.secrets.wg_ovpns_privkey.path;
|
||||
# wg is active only in this namespace.
|
||||
# run e.g. ip netns exec ovpns <some command like ping/curl/etc, it'll go through wg>
|
||||
# sudo ip netns exec ovpns ping www.google.com
|
||||
interfaceNamespace = "ovpns";
|
||||
ips = [
|
||||
"185.157.162.178/32"
|
||||
];
|
||||
ips = [ "185.157.162.178" ];
|
||||
peers = [
|
||||
{
|
||||
publicKey = "SkkEZDCBde22KTs/Hc7FWvDBfdOCQA4YtBEuC3n5KGs=";
|
||||
@@ -119,99 +106,11 @@ in
|
||||
# dynamicEndpointRefreshRestartSeconds = 5;
|
||||
}
|
||||
];
|
||||
preSetup = ''
|
||||
${ip} netns add ovpns || (test -e /run/netns/ovpns && echo "ovpns already exists")
|
||||
'';
|
||||
postShutdown = ''
|
||||
${in-ns} ip link del ovpns-veth-b || echo "couldn't delete ovpns-veth-b"
|
||||
${ip} link del ovpns-veth-a || echo "couldn't delete ovpns-veth-a"
|
||||
${ip} netns delete ovpns || echo "couldn't delete ovpns"
|
||||
# restore rules/routes
|
||||
${ip} rule del from ${veth-host-ip} lookup ovpns pref 50 || echo "couldn't delete init -> ovpns rule"
|
||||
${ip} route del default via ${veth-local-ip} dev ovpns-veth-a proto kernel src ${veth-host-ip} metric 1002 table ovpns || echo "couldn't delete init -> ovpns route"
|
||||
${ip} rule add from all lookup local pref 0
|
||||
${ip} rule del from all lookup local pref 100
|
||||
'';
|
||||
postSetup = ''
|
||||
# DOCS:
|
||||
# - some of this approach is described here: <https://josephmuia.ca/2018-05-16-net-namespaces-veth-nat/>
|
||||
# - iptables primer: <https://danielmiessler.com/study/iptables/>
|
||||
# create veth pair
|
||||
${ip} link add ovpns-veth-a type veth peer name ovpns-veth-b
|
||||
${ip} addr add ${veth-host-ip}/24 dev ovpns-veth-a
|
||||
${ip} link set ovpns-veth-a up
|
||||
|
||||
# mv veth-b into the ovpns namespace
|
||||
${ip} link set ovpns-veth-b netns ovpns
|
||||
${in-ns} ip addr add ${veth-local-ip}/24 dev ovpns-veth-b
|
||||
${in-ns} ip link set ovpns-veth-b up
|
||||
|
||||
# make it so traffic originating from the host side of the veth
|
||||
# is sent over the veth no matter its destination.
|
||||
${ip} rule add from ${veth-host-ip} lookup ovpns pref 50
|
||||
# for traffic originating at the host veth to the WAN, use the veth as our gateway
|
||||
# not sure if the metric 1002 matters.
|
||||
${ip} route add default via ${veth-local-ip} dev ovpns-veth-a proto kernel src ${veth-host-ip} metric 1002 table ovpns
|
||||
# give the default route lower priority
|
||||
${ip} rule add from all lookup local pref 100
|
||||
${ip} rule del from all lookup local pref 0
|
||||
|
||||
# in order to access DNS in this netns, we need to route it to the VPN's nameservers
|
||||
# - alternatively, we could fix DNS servers like 1.1.1.1.
|
||||
${in-ns} ${iptables} -A OUTPUT -t nat -p udp --dport 53 -m iprange --dst-range 127.0.0.53 \
|
||||
-j DNAT --to-destination ${vpn-dns}:53
|
||||
'' + (lib.concatStringsSep "\n" bridgeStatements);
|
||||
};
|
||||
|
||||
# create a new routing table that we can use to proxy traffic out of the root namespace
|
||||
# through the ovpns namespace, and to the WAN via VPN.
|
||||
networking.iproute2.rttablesExtraConfig = ''
|
||||
5 ovpns
|
||||
'';
|
||||
networking.iproute2.enable = true;
|
||||
|
||||
|
||||
# HURRICANE ELECTRIC CONFIG:
|
||||
# networking.sits = {
|
||||
# hurricane = {
|
||||
# remote = "216.218.226.238";
|
||||
# local = "192.168.0.5";
|
||||
# # local = "10.0.0.5";
|
||||
# # remote = "10.0.0.1";
|
||||
# # local = "10.0.0.22";
|
||||
# dev = "eth0";
|
||||
# ttl = 255;
|
||||
# };
|
||||
# };
|
||||
# networking.interfaces."hurricane".ipv6 = {
|
||||
# addresses = [
|
||||
# # mx.uninsane.org (publically routed /64)
|
||||
# {
|
||||
# address = "2001:470:b:465::1";
|
||||
# prefixLength = 128;
|
||||
# }
|
||||
# # client addr
|
||||
# # {
|
||||
# # address = "2001:470:a:466::2";
|
||||
# # prefixLength = 64;
|
||||
# # }
|
||||
# ];
|
||||
# routes = [
|
||||
# {
|
||||
# address = "::";
|
||||
# prefixLength = 0;
|
||||
# # via = "2001:470:a:466::1";
|
||||
# }
|
||||
# ];
|
||||
# };
|
||||
|
||||
# # after configuration, we want the hurricane device to look like this:
|
||||
# # hurricane: flags=209<UP,POINTOPOINT,RUNNING,NOARP> mtu 1480
|
||||
# # inet6 2001:470:a:450::2 prefixlen 64 scopeid 0x0<global>
|
||||
# # inet6 fe80::c0a8:16 prefixlen 64 scopeid 0x20<link>
|
||||
# # sit txqueuelen 1000 (IPv6-in-IPv4)
|
||||
# # test with:
|
||||
# # curl --interface hurricane http://[2607:f8b0:400a:80b::2004]
|
||||
# # ping 2607:f8b0:400a:80b::2004
|
||||
sane.netns.ovpns.hostVethIpv4 = "10.0.1.5";
|
||||
sane.netns.ovpns.netnsVethIpv4 = "10.0.1.6";
|
||||
sane.netns.ovpns.netnsPubIpv4 = "185.157.162.178";
|
||||
sane.netns.ovpns.routeTable = 11;
|
||||
sane.netns.ovpns.dns = "46.227.67.134"; #< DNS requests inside the namespace are forwarded here
|
||||
};
|
||||
}
|
||||
|
@@ -55,7 +55,7 @@ in
|
||||
# protocol = [ "tcp" "udp" ];
|
||||
# # visibleTo.lan = true;
|
||||
# # visibleTo.wan = true;
|
||||
# visibleTo.ovpn = true; # forward traffic from the VPN to the root NS
|
||||
# visibleTo.ovpns = true; # forward traffic from the VPN to the root NS
|
||||
# description = "colin-stun-turn";
|
||||
# };
|
||||
# "5349" = {
|
||||
@@ -63,7 +63,7 @@ in
|
||||
# protocol = [ "tcp" ];
|
||||
# # visibleTo.lan = true;
|
||||
# # visibleTo.wan = true;
|
||||
# visibleTo.ovpn = true;
|
||||
# visibleTo.ovpns = true;
|
||||
# description = "colin-stun-turn-over-tls";
|
||||
# };
|
||||
# }
|
||||
@@ -76,7 +76,7 @@ in
|
||||
# protocol = [ "tcp" "udp" ];
|
||||
# # visibleTo.lan = true;
|
||||
# # visibleTo.wan = true;
|
||||
# visibleTo.ovpn = true;
|
||||
# visibleTo.ovpns = true;
|
||||
# description = "colin-turn-${builtins.toString count}-of-${builtins.toString numPorts}";
|
||||
# };
|
||||
# })
|
||||
|
@@ -50,7 +50,11 @@
|
||||
ENABLE_CAPTCHA = true;
|
||||
NOREPLY_ADDRESS = "noreply.anonymous.git@uninsane.org";
|
||||
};
|
||||
session.COOKIE_SECURE = true;
|
||||
session = {
|
||||
COOKIE_SECURE = true;
|
||||
# keep me logged in for 30 days
|
||||
SESSION_LIFE_TIME = 60 * 60 * 24 * 30;
|
||||
};
|
||||
repository = {
|
||||
DEFAULT_BRANCH = "master";
|
||||
ENABLE_PUSH_CREATE_USER = true;
|
||||
|
@@ -18,13 +18,15 @@ in
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
visibleTo.wan = true;
|
||||
visibleTo.ovpn = true; # so that letsencrypt can procure a cert for the mx record
|
||||
visibleTo.ovpns = true; # so that letsencrypt can procure a cert for the mx record
|
||||
visibleTo.doof = true;
|
||||
description = "colin-http-uninsane.org";
|
||||
};
|
||||
sane.ports.ports."443" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
visibleTo.wan = true;
|
||||
visibleTo.doof = true;
|
||||
description = "colin-https-uninsane.org";
|
||||
};
|
||||
|
||||
|
@@ -22,8 +22,7 @@
|
||||
|
||||
sane.ports.ports."50300" = {
|
||||
protocol = [ "tcp" ];
|
||||
# not visible to WAN: i run this in a separate netns
|
||||
visibleTo.ovpn = true;
|
||||
# visibleTo.ovpns = true; #< not needed: it runs in the ovpns namespace
|
||||
description = "colin-soulseek";
|
||||
};
|
||||
|
||||
|
@@ -197,7 +197,7 @@ lib.mkIf false #< TODO: re-enable once confident of sandboxing
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."bt" = "native";
|
||||
sane.ports.ports."51413" = {
|
||||
protocol = [ "tcp" "udp" ];
|
||||
visibleTo.ovpn = true;
|
||||
# visibleTo.ovpns = true; #< not needed: it runs in the ovpns namespace
|
||||
description = "colin-bittorrent";
|
||||
};
|
||||
}
|
||||
|
@@ -5,13 +5,15 @@ let
|
||||
dyn-dns = config.sane.services.dyn-dns;
|
||||
nativeAddrs = lib.mapAttrs (_name: builtins.head) config.sane.dns.zones."uninsane.org".inet.A;
|
||||
bindOvpn = "10.0.1.5";
|
||||
bindDoof = "10.0.2.5";
|
||||
in
|
||||
{
|
||||
sane.ports.ports."53" = {
|
||||
protocol = [ "udp" "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
visibleTo.wan = true;
|
||||
visibleTo.ovpn = true;
|
||||
visibleTo.ovpns = true;
|
||||
visibleTo.doof = true;
|
||||
description = "colin-dns-hosting";
|
||||
};
|
||||
|
||||
@@ -99,6 +101,7 @@ in
|
||||
listenAddrsIpv4 = [
|
||||
nativeAddrs."servo.lan"
|
||||
bindOvpn
|
||||
bindDoof
|
||||
];
|
||||
};
|
||||
lan = {
|
||||
|
@@ -9,7 +9,7 @@
|
||||
./ids.nix
|
||||
./machine-id.nix
|
||||
./net
|
||||
./nix
|
||||
./nix.nix
|
||||
./persist.nix
|
||||
./polyunfill.nix
|
||||
./programs
|
||||
|
@@ -195,6 +195,7 @@ let
|
||||
(fromDb "weekinethereumnews.com" // tech)
|
||||
(fromDb "willow.phantoma.online") # wizard@xyzzy.link
|
||||
(fromDb "xn--gckvb8fzb.com" // tech)
|
||||
(fromDb "xorvoid.com" // tech)
|
||||
(mkSubstack "astralcodexten" // rat // daily) # Scott Alexander
|
||||
(mkSubstack "eliqian" // rat // weekly)
|
||||
(mkSubstack "oversharing" // pol // daily)
|
||||
|
@@ -59,14 +59,18 @@
|
||||
# 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"
|
||||
# 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/overlay"
|
||||
# to avoid `switch`ing so much during development.
|
||||
# TODO: it would be nice to remove this someday!
|
||||
# it's an impurity that touches way more than i need and tends to cause hard-to-debug eval issues
|
||||
# when it goes wrong. should i port my `nix-shell` scripts to something more tailored to my uses
|
||||
# and then delete `nixpkgs-overlays`?
|
||||
"nixpkgs-overlays=/home/colin/dev/nixos/integrations/nixpkgs/nixpkgs-overlays.nix"
|
||||
];
|
||||
|
||||
# ensure new deployments have a source of this repo with which they can bootstrap.
|
||||
# this however changes on every commit and can be slow to copy for e.g. `moby`.
|
||||
environment.etc."nixos" = lib.mkIf (config.sane.maxBuildCost >= 3) {
|
||||
source = ../../..;
|
||||
source = pkgs.sane-nix-files;
|
||||
};
|
||||
environment.etc."nix/registry.json" = lib.mkIf (config.sane.maxBuildCost < 3) {
|
||||
enable = false;
|
@@ -1,4 +0,0 @@
|
||||
# XXX: NIX_PATH=...:nixpkgs-overlays=... will import every overlay in the directory
|
||||
# so we prefer to give it a directory with just this *one* overlay, otherwise it imports conflicting overlays
|
||||
# and gets stuck in a loop until it OOMs
|
||||
import ../../../../overlays/all.nix
|
@@ -50,6 +50,7 @@ in
|
||||
"fd"
|
||||
"file"
|
||||
"forkstat" # monitor every spawned/forked process
|
||||
"free"
|
||||
# "fwupd"
|
||||
"gawk"
|
||||
"gdb" # to debug segfaults
|
||||
@@ -84,6 +85,7 @@ in
|
||||
"parted"
|
||||
"pciutils"
|
||||
"powertop"
|
||||
"ps"
|
||||
"pstree"
|
||||
"ripgrep"
|
||||
"s6-rc" # service manager
|
||||
@@ -97,6 +99,7 @@ in
|
||||
"usbutils" # lsusb
|
||||
"util-linux" # lsblk, lscpu, etc
|
||||
"valgrind"
|
||||
"watch"
|
||||
"wget"
|
||||
"wirelesstools" # iwlist
|
||||
# "xq" # jq for XML
|
||||
@@ -294,6 +297,7 @@ in
|
||||
"loupe" # image viewer
|
||||
"mate.engrampa" # archive manager
|
||||
"mepo" # maps viewer
|
||||
"mesa-demos" # for eglinfo, glxinfo & other testing tools
|
||||
"mpv"
|
||||
"networkmanagerapplet" # for nm-connection-editor: it's better than not having any gui!
|
||||
"ntfy-sh" # notification service
|
||||
@@ -355,7 +359,7 @@ in
|
||||
"gnome.gnome-disk-utility"
|
||||
"gnome.nautilus" # file browser
|
||||
# "gnome.totem" # video player, supposedly supports UPnP
|
||||
"handbrake"
|
||||
# "handbrake" #< TODO: fix build
|
||||
"inkscape"
|
||||
# "jellyfin-media-player"
|
||||
"kdenlive"
|
||||
@@ -815,6 +819,8 @@ in
|
||||
mercurial.sandbox.net = "clearnet";
|
||||
mercurial.sandbox.whitelistPwd = true;
|
||||
|
||||
mesa-demos = {};
|
||||
|
||||
# actual monero blockchain (not wallet/etc; safe to delete, just slow to regenerate)
|
||||
monero-gui.buildCost = 1;
|
||||
# XXX: is it really safe to persist this? it doesn't have info that could de-anonymize if captured?
|
||||
@@ -1117,6 +1123,8 @@ in
|
||||
"tmp"
|
||||
];
|
||||
|
||||
watch.sandbox.enable = false; #< it executes the command it's given
|
||||
|
||||
wdisplays.sandbox.method = "bwrap";
|
||||
wdisplays.sandbox.whitelistWayland = true;
|
||||
|
||||
|
@@ -1,36 +1,24 @@
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
sane.programs.sane-battery-estimate = {
|
||||
packageUnwrapped = pkgs.static-nix-shell.mkBash {
|
||||
pname = "sane-battery-estimate";
|
||||
srcRoot = ./.;
|
||||
};
|
||||
sandbox.method = "bwrap";
|
||||
sandbox.extraPaths = [
|
||||
"/sys/class/power_supply"
|
||||
"/sys/devices"
|
||||
];
|
||||
};
|
||||
|
||||
sane.programs.conky = {
|
||||
sandbox.method = "bwrap";
|
||||
sandbox.net = "clearnet"; #< for the scripts it calls (weather)
|
||||
sandbox.extraPaths = [
|
||||
"/sys/class/power_supply"
|
||||
"/sys/devices" # needed by battery_estimate
|
||||
"/sys/devices" # needed by sane-sysinfo
|
||||
# "/sys/devices/cpu"
|
||||
# "/sys/devices/system"
|
||||
];
|
||||
sandbox.whitelistWayland = true;
|
||||
|
||||
suggestedPrograms = [
|
||||
"sane-battery-estimate"
|
||||
"sane-sysinfo"
|
||||
"sane-weather"
|
||||
];
|
||||
|
||||
fs.".config/conky/conky.conf".symlink.target = pkgs.substituteAll {
|
||||
src = ./conky.conf;
|
||||
bat = "sane-battery-estimate";
|
||||
bat = "sane-sysinfo";
|
||||
weather = "timeout 20 sane-weather";
|
||||
};
|
||||
|
||||
|
@@ -1,183 +0,0 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash
|
||||
|
||||
usage() {
|
||||
echo "usage: battery_estimate [options...]"
|
||||
echo
|
||||
echo "pretty-prints a battery estimate (icon to indicate state, and a duration estimate)"
|
||||
echo
|
||||
echo "options:"
|
||||
echo " --debug: output additional information, to stderr"
|
||||
echo " --minute-suffix <string>: use the provided string as a minutes suffix"
|
||||
echo " --hour-suffix <string>: use the provided string as an hours suffix"
|
||||
echo " --icon-suffix <string>: use the provided string as an icon suffix"
|
||||
echo " --percent-suffix <string>: use the provided string when displaying percents"
|
||||
}
|
||||
|
||||
# these icons may only render in nerdfonts
|
||||
icon_bat_chg=("" "" "" "")
|
||||
icon_bat_dis=("" "" "" "")
|
||||
suffix_icon=" " # thin space
|
||||
suffix_percent="%"
|
||||
# suffix_icon=" "
|
||||
|
||||
# render time like: 2ʰ08ᵐ
|
||||
# unicode sub/super-scripts: <https://en.wikipedia.org/wiki/Unicode_subscripts_and_superscripts>
|
||||
# symbol_hr="ʰ"
|
||||
# symbol_min="ᵐ"
|
||||
|
||||
# render time like: 2ₕ08ₘ
|
||||
# symbol_hr="ₕ"
|
||||
# symbol_min="ₘ"
|
||||
|
||||
# render time like: 2h08m
|
||||
# symbol_hr="h"
|
||||
# symbol_min="m"
|
||||
|
||||
# render time like: 2:08
|
||||
# symbol_hr=":"
|
||||
# symbol_min=
|
||||
|
||||
# render time like: 2꞉08⧗
|
||||
symbol_hr="꞉"
|
||||
symbol_min="⧗"
|
||||
# variants:
|
||||
# symbol_hr=":"
|
||||
# symbol_min="⧖"
|
||||
# symbol_min="⌛"
|
||||
|
||||
# render time like: 2'08"
|
||||
# symbol_hr="'"
|
||||
# symbol_min='"'
|
||||
|
||||
log() {
|
||||
if [ "$BATTERY_ESTIMATE_DEBUG" = "1" ]; then
|
||||
printf "$@" >&2
|
||||
echo >&2
|
||||
fi
|
||||
}
|
||||
|
||||
render_icon() {
|
||||
# args:
|
||||
# 1: "chg" or "dis"
|
||||
# 2: current battery percentage
|
||||
level=$(($2 / 25))
|
||||
level=$(($level > 3 ? 3 : $level))
|
||||
level=$(($level < 0 ? 0 : $level))
|
||||
log "icon: %s %d" "$1" "$level"
|
||||
if [ "$1" = "dis" ]; then
|
||||
printf "%s" "${icon_bat_dis[$level]}"
|
||||
elif [ "$1" = "chg" ]; then
|
||||
printf "%s" "${icon_bat_chg[$level]}"
|
||||
fi
|
||||
}
|
||||
|
||||
try_path() {
|
||||
# assigns output variables:
|
||||
# - perc, perc_from_full (0-100)
|
||||
# - full, rate (pos means charging)
|
||||
if [ -f "$1/capacity" ]; then
|
||||
log "perc, perc_from_full from %s" "$1/capacity"
|
||||
perc=$(cat "$1/capacity")
|
||||
perc_from_full=$((100 - $perc))
|
||||
fi
|
||||
|
||||
if [ -f "$1/charge_full_design" ] && [ -f "$1/current_now" ]; then
|
||||
log "full, rate from %s and %s" "$1/charge_full_design" "$1/current_now"
|
||||
# current is positive when charging
|
||||
full=$(cat "$1/charge_full_design")
|
||||
rate=$(cat "$1/current_now")
|
||||
elif [ -f "$1/energy_full" ] && [ -f "$1/power_now" ]; then
|
||||
log "full, rate from %s and %s" "$1/energy_full" "$1/power_now"
|
||||
# power_now is positive when discharging
|
||||
full=$(cat "$1/energy_full")
|
||||
rate=-$(cat "$1/power_now")
|
||||
elif [ -f "$1/energy_full" ] && [ -f "$1/energy_now" ]; then
|
||||
log "full, rate from %s and %s" "$1/energy_full" "$1/energy_now"
|
||||
log " this is a compatibility path for legacy Thinkpad batteries which do not populate the 'power_now' field, and incorrectly populate 'energy_now' with power info"
|
||||
# energy_now is positive when discharging
|
||||
full=$(cat "$1/energy_full")
|
||||
rate=-$(cat "$1/energy_now")
|
||||
fi
|
||||
}
|
||||
|
||||
try_all_paths() {
|
||||
try_path "/sys/class/power_supply/axp20x-battery" # Pinephone
|
||||
try_path "/sys/class/power_supply/BAT0" # Thinkpad
|
||||
log "perc: %d, perc_from_full: %d" "$perc" "$perc_from_full"
|
||||
log "full: %f, rate: %f" "$full" "$rate"
|
||||
log " rate > 0 means charging, else discharging"
|
||||
}
|
||||
|
||||
fmt_minutes() {
|
||||
# args:
|
||||
# 1: icon to render
|
||||
# 2: string to show if charge/discharge time is indefinite
|
||||
# 3: minutes to stable state (i.e. to full charge or full discharge)
|
||||
# - we work in minutes instead of hours for precision: bash math is integer-only
|
||||
log "charge/discharge time: %f min" "$3"
|
||||
# args: <battery symbol> <text if ludicrous estimate> <estimated minutes to full/empty>
|
||||
if [ -n "$3" ] && [ "$3" -lt 1440 ]; then
|
||||
hr=$(($3 / 60))
|
||||
hr_in_min=$(($hr * 60))
|
||||
min=$(($3 - $hr_in_min))
|
||||
printf "%s%s%d%s%02d%s" "$1" "$suffix_icon" "$hr" "$symbol_hr" "$min" "$symbol_min"
|
||||
else
|
||||
log "charge/discharge duration > 1d"
|
||||
printf "%s%s%s" "$1" "$suffix_icon" "$2" # more than 1d
|
||||
fi
|
||||
}
|
||||
|
||||
pretty_output() {
|
||||
if [ -n "$perc" ]; then
|
||||
duration=""
|
||||
if [ "$rate" -gt 0 ]; then
|
||||
log "charging"
|
||||
icon="$(render_icon chg $perc)"
|
||||
duration="$(($full * 60 * $perc_from_full / (100 * $rate)))"
|
||||
else
|
||||
log "discharging"
|
||||
icon="$(render_icon dis $perc)"
|
||||
if [ "$rate" -lt 0 ]; then
|
||||
duration="$(($full * 60 * $perc / (-100 * $rate)))"
|
||||
fi
|
||||
fi
|
||||
fmt_minutes "$icon" "$perc$suffix_percent" "$duration"
|
||||
fi
|
||||
}
|
||||
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
"--debug")
|
||||
shift
|
||||
BATTERY_ESTIMATE_DEBUG=1
|
||||
;;
|
||||
"--icon-suffix")
|
||||
shift
|
||||
suffix_icon="$1"
|
||||
shift
|
||||
;;
|
||||
"--hour-suffix")
|
||||
shift
|
||||
symbol_hr="$1"
|
||||
shift
|
||||
;;
|
||||
"--minute-suffix")
|
||||
shift
|
||||
symbol_min="$1"
|
||||
shift
|
||||
;;
|
||||
"--percent-suffix")
|
||||
shift
|
||||
suffix_percent="$1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
try_all_paths
|
||||
pretty_output
|
@@ -45,6 +45,7 @@
|
||||
./flare-signal.nix
|
||||
./fontconfig.nix
|
||||
./fractal.nix
|
||||
./free.nix
|
||||
./frozen-bubble.nix
|
||||
./fwupd.nix
|
||||
./g4music.nix
|
||||
@@ -93,14 +94,17 @@
|
||||
./nmcli.nix
|
||||
./notejot.nix
|
||||
./ntfy-sh.nix
|
||||
./nwg-panel
|
||||
./objdump.nix
|
||||
./obsidian.nix
|
||||
./offlineimap.nix
|
||||
./open-in-mpv.nix
|
||||
./pactl.nix
|
||||
./pipewire.nix
|
||||
./planify.nix
|
||||
./portfolio-filemanager.nix
|
||||
./playerctl.nix
|
||||
./ps.nix
|
||||
./rhythmbox.nix
|
||||
./ripgrep.nix
|
||||
./rofi
|
||||
@@ -110,6 +114,7 @@
|
||||
./sane-open.nix
|
||||
./sane-screenshot.nix
|
||||
./sane-scripts.nix
|
||||
./sane-sysinfo.nix
|
||||
./sane-theme.nix
|
||||
./sanebox.nix
|
||||
./schlock.nix
|
||||
@@ -130,6 +135,7 @@
|
||||
./swayidle.nix
|
||||
./swaylock.nix
|
||||
./swaynotificationcenter
|
||||
./switchboard.nix
|
||||
./sysvol.nix
|
||||
./tangram.nix
|
||||
./tor-browser.nix
|
||||
|
9
hosts/common/programs/free.nix
Normal file
9
hosts/common/programs/free.nix
Normal file
@@ -0,0 +1,9 @@
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
sane.programs.free = {
|
||||
packageUnwrapped = pkgs.linkIntoOwnPackage pkgs.procps "bin/free";
|
||||
sandbox.method = "bwrap";
|
||||
sandbox.isolatePids = false;
|
||||
};
|
||||
}
|
||||
|
159
hosts/common/programs/nwg-panel/config.nix
Normal file
159
hosts/common/programs/nwg-panel/config.nix
Normal file
@@ -0,0 +1,159 @@
|
||||
# TODO:
|
||||
# - try this PR to get custom workspace names to work:
|
||||
# - <https://github.com/nwg-piotr/nwg-panel/pull/191>
|
||||
# - add network/bluetooth indicator
|
||||
# - <https://github.com/nwg-piotr/nwg-panel/issues/269>
|
||||
# - add CPU/meminfo executor
|
||||
# - use sane-sysinfo
|
||||
{
|
||||
components,
|
||||
height,
|
||||
playerctlChars,
|
||||
windowIcon,
|
||||
windowTitle,
|
||||
workspaceHideEmpty,
|
||||
workspaceNumbers,
|
||||
}:
|
||||
[
|
||||
{
|
||||
controls = "right";
|
||||
css-name = "panel-top";
|
||||
exclusive-zone = true;
|
||||
height = height;
|
||||
homogeneous = false; #< homogenous=false means to not force modules-{left,center,right} to an inflexible 33%/33%/33% real-estate split.
|
||||
icons = "light";
|
||||
items-padding = 0;
|
||||
layer = "bottom";
|
||||
margin-bottom = 0;
|
||||
margin-top = 0;
|
||||
menu-start = "off";
|
||||
name = "panel-top";
|
||||
# output = "All" => display the bar on every output.
|
||||
# - documented: <https://github.com/nwg-piotr/nwg-panel/issues/48>
|
||||
# alternatively, i could declare one bar per display,
|
||||
# and then customize it so that the external display(s) render a less noisy bar.
|
||||
# this will be easier once this is addressed: <https://github.com/nwg-piotr/nwg-panel/issues/215>
|
||||
output = "All";
|
||||
padding-horizontal = 0;
|
||||
padding-vertical = 0;
|
||||
position = "top";
|
||||
sigrt = 64;
|
||||
spacing = 0;
|
||||
start-hidden = false;
|
||||
use-sigrt = false;
|
||||
width = "auto";
|
||||
|
||||
modules-left = [
|
||||
"sway-workspaces"
|
||||
];
|
||||
modules-center = [
|
||||
"clock"
|
||||
];
|
||||
modules-right = [
|
||||
"playerctl"
|
||||
];
|
||||
|
||||
clock = {
|
||||
angle = 0.0;
|
||||
calendar-css-name = "calendar-window";
|
||||
calendar-icon-size = 24;
|
||||
calendar-interval = 60;
|
||||
calendar-margin-horizontal = 0;
|
||||
calendar-margin-vertical = 0;
|
||||
calendar-on = true;
|
||||
calendar-path = "";
|
||||
calendar-placement = "top";
|
||||
css-name = "clock";
|
||||
format = "%H:%M";
|
||||
interval = 30;
|
||||
on-left-click = "";
|
||||
on-middle-click = "";
|
||||
on-right-click = "";
|
||||
on-scroll-down = "";
|
||||
on-scroll-up = "";
|
||||
root-css-name = "root-clock";
|
||||
tooltip-date-format = true;
|
||||
tooltip-text = "%a; %d %b %H:%M:%S";
|
||||
};
|
||||
controls-settings = {
|
||||
battery-low-interval = 4; #< notify every N minutes when battery continues to remain low
|
||||
battery-low-level = 15; #< notify if battery is lower than this percent
|
||||
# commands.battery = ""; #< optional action to perform when battery icon is clicked in the drop-down menu
|
||||
components = components;
|
||||
click-closes = false;
|
||||
custom-items = [];
|
||||
css-name = "controls-window";
|
||||
hover-opens = false;
|
||||
icon-size = 16;
|
||||
interval = 1;
|
||||
leave-closes = false;
|
||||
menu.icon = "system-shutdown-symbolic";
|
||||
menu.items = [
|
||||
{
|
||||
# TODO: plumb through the configured locker instead of assuming `swaylock`
|
||||
name = "Lock";
|
||||
cmd = "swaylock -f -c 000000";
|
||||
}
|
||||
{
|
||||
name = "Logout";
|
||||
cmd = "swaymsg exit";
|
||||
}
|
||||
{
|
||||
name = "Reboot";
|
||||
cmd = "systemctl reboot";
|
||||
}
|
||||
{
|
||||
name = "Shutdown";
|
||||
cmd = "systemctl -i poweroff";
|
||||
}
|
||||
];
|
||||
menu.name = "Exit";
|
||||
output-switcher = true; #< allow changing the default audio sink
|
||||
#v `show-<x>` means "show the NUMERICAL VALUE corresponding to <x>"
|
||||
# e.g. show-battery means "show the battery _percentage_ next to its icon".
|
||||
show-battery = true;
|
||||
show-brightness = false;
|
||||
show-values = false;
|
||||
show-volume = false;
|
||||
# window-width: should be 360 for moby, but because of weird `margin` tweaks in style.css
|
||||
# we have to add 20px to both sides
|
||||
window-width = 400;
|
||||
};
|
||||
playerctl = {
|
||||
button-css-name = "playerctl-button";
|
||||
buttons-position = "left";
|
||||
chars = playerctlChars;
|
||||
icon-size = 16;
|
||||
interval = 2;
|
||||
label-css-name = "playerctl-label";
|
||||
scroll = false;
|
||||
};
|
||||
sway-workspaces = {
|
||||
angle = 0.0;
|
||||
custom-labels = [];
|
||||
focused-labels = [];
|
||||
hide-empty = workspaceHideEmpty;
|
||||
image-size = 16;
|
||||
mark-autotiling = true;
|
||||
mark-content = false;
|
||||
name-length = 40;
|
||||
numbers = workspaceNumbers;
|
||||
show-icon = windowIcon;
|
||||
show-layout = false;
|
||||
show-name = windowTitle;
|
||||
};
|
||||
|
||||
# unused modules:
|
||||
brightness-slider = {};
|
||||
dwl-tags = {};
|
||||
hyprland-taskbar = {};
|
||||
hyprland-workspaces = {};
|
||||
keyboard-layout = {};
|
||||
openweather = {};
|
||||
scratchpad = {};
|
||||
sway-mode = {};
|
||||
sway-taskbar = {}; #< windows-style taskbar, usually placed at the bottom of the screen, to show open windows & tab to them on click
|
||||
tray = {};
|
||||
}
|
||||
]
|
||||
|
132
hosts/common/programs/nwg-panel/default.nix
Normal file
132
hosts/common/programs/nwg-panel/default.nix
Normal file
@@ -0,0 +1,132 @@
|
||||
# nwg-panel: a wayland status bar (like waybar, etc)
|
||||
# documentation is in the GitHub Wiki:
|
||||
# - <https://github.com/nwg-piotr/nwg-panel/wiki/Configuration>
|
||||
#
|
||||
# interactively configure with: `nwg-panel-config`
|
||||
# ^ note that this may interfere with the `nwg-panel` service
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.sane.programs.nwg-panel;
|
||||
mkEnableOption' = default: description: lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
inherit default description;
|
||||
};
|
||||
in
|
||||
{
|
||||
sane.programs.nwg-panel = {
|
||||
configOption = with lib; mkOption {
|
||||
default = {};
|
||||
type = types.submodule {
|
||||
options = {
|
||||
clockFontSize = mkOption {
|
||||
type = types.int;
|
||||
# what looks good:
|
||||
# - 15px on moby
|
||||
# - 24px on lappy
|
||||
default = lib.min 24 (cfg.config.fontSize - 1);
|
||||
};
|
||||
fontSize = mkOption {
|
||||
type = types.int;
|
||||
default = 16;
|
||||
};
|
||||
height = mkOption {
|
||||
type = types.int;
|
||||
default = 40;
|
||||
description = ''
|
||||
height of the top bar in px.
|
||||
'';
|
||||
};
|
||||
battery = mkEnableOption' true "display battery status";
|
||||
brightness = mkEnableOption' true "display backlight level and slider";
|
||||
mediaTitle = mkEnableOption' true "display title of current song/media";
|
||||
mediaPrevNext = mkEnableOption' true "display prev/next button in media";
|
||||
windowIcon = mkEnableOption' true "display icon of active window";
|
||||
windowTitle = mkEnableOption' true "display title of active window";
|
||||
workspaceNumbers = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [
|
||||
# TODO: workspace 10 should be rendered as "TV"
|
||||
"1" "2" "3" "4" "5" "6" "7" "8" "9" "10"
|
||||
];
|
||||
description = ''
|
||||
workspaces to monitor
|
||||
'';
|
||||
};
|
||||
workspaceHideEmpty = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
packageUnwrapped = (pkgs.nwg-panel.override {
|
||||
# XXX(2024/06/13): hyprland does not cross compile
|
||||
hyprland = null;
|
||||
# XXX(2024/06/13): wlr-randr does not cross compile
|
||||
wlr-randr = null; #< only used if not on sway/hyprland; or if using dwl
|
||||
}).overrideAttrs (base: {
|
||||
patches = (base.patches or []) ++ lib.optionals (!cfg.config.mediaPrevNext) [
|
||||
./playerctl-no-prev-next.diff
|
||||
];
|
||||
|
||||
# - disable the drop-down chevron by the controls.
|
||||
# it's precious space on moby, doesn't do much to help on lappy either.
|
||||
# - disable brightness indicator for same reason.
|
||||
# - *leave* the volume indicator: one *could* remove it, however on desko that would leave the controls pane empty
|
||||
# making the dropdown inaccessible
|
||||
postPatch = (base.postPatch or "") + ''
|
||||
substituteInPlace nwg_panel/modules/controls.py --replace-fail \
|
||||
'box.pack_start(self.pan_image, False, False, 4)' \
|
||||
'# box.pack_start(self.pan_image, False, False, 4)'
|
||||
substituteInPlace nwg_panel/modules/controls.py --replace-fail \
|
||||
'box.pack_start(self.bri_image, False, False, 4)' \
|
||||
'# box.pack_start(self.bri_image, False, False, 4)'
|
||||
|
||||
# substituteInPlace nwg_panel/modules/controls.py --replace-fail \
|
||||
# 'box.pack_start(self.vol_image, False, False, 4)' \
|
||||
# '# box.pack_start(self.vol_image, False, False, 4)'
|
||||
'';
|
||||
|
||||
# XXX(2024/06/13) the bluetooth stuff doesn't cross compile, so disable it
|
||||
propagatedBuildInputs = lib.filter (p: p.pname != "pybluez") base.propagatedBuildInputs;
|
||||
|
||||
strictDeps = true;
|
||||
});
|
||||
|
||||
suggestedPrograms = [
|
||||
"pactl" # pactl required by `per-app-volume` component.
|
||||
];
|
||||
|
||||
fs.".config/nwg-panel/style.css".symlink.target = pkgs.substituteAll {
|
||||
src = ./style.css;
|
||||
inherit (cfg.config) fontSize clockFontSize;
|
||||
};
|
||||
fs.".config/nwg-panel/config".symlink.target = pkgs.writers.writeJSON "config" (import ./config.nix {
|
||||
inherit (cfg.config) height windowIcon windowTitle workspaceHideEmpty workspaceNumbers;
|
||||
# component order matters, mostly for the drop-down.
|
||||
# default for most tools (e.g. swaync) is brightness control above volume.
|
||||
components =
|
||||
lib.optionals cfg.config.brightness [
|
||||
"brightness"
|
||||
] ++ [
|
||||
"volume"
|
||||
"per-app-volume"
|
||||
] ++ lib.optionals cfg.config.battery [
|
||||
"battery"
|
||||
]
|
||||
;
|
||||
playerctlChars = if cfg.config.mediaTitle then 60 else 0;
|
||||
});
|
||||
|
||||
services.nwg-panel = {
|
||||
description = "nwg-panel status/topbar for wayland";
|
||||
partOf = [ "graphical-session" ];
|
||||
|
||||
# to debug styling, run with GTK_DEBUG=interactive
|
||||
# N.B.: G_MESSAGES_DEBUG=all causes the swaync icon to not render
|
||||
# command = "env G_MESSAGES_DEBUG=all nwg-panel";
|
||||
command = "nwg-panel";
|
||||
};
|
||||
};
|
||||
}
|
36
hosts/common/programs/nwg-panel/playerctl-no-prev-next.diff
Normal file
36
hosts/common/programs/nwg-panel/playerctl-no-prev-next.diff
Normal file
@@ -0,0 +1,36 @@
|
||||
diff --git a/nwg_panel/modules/playerctl.py b/nwg_panel/modules/playerctl.py
|
||||
index 9b53b4b..c4d96ae 100644
|
||||
--- a/nwg_panel/modules/playerctl.py
|
||||
+++ b/nwg_panel/modules/playerctl.py
|
||||
@@ -180,15 +180,6 @@ class Playerctl(Gtk.EventBox):
|
||||
if self.settings["angle"] != 0.0:
|
||||
button_box.set_orientation(Gtk.Orientation.VERTICAL)
|
||||
|
||||
- img = Gtk.Image()
|
||||
- update_image(img, "media-skip-backward-symbolic", self.settings["icon-size"], icons_path=self.icons_path)
|
||||
- btn = Gtk.Button()
|
||||
- btn.set_image(img)
|
||||
- if self.settings["button-css-name"]:
|
||||
- btn.set_property("name", self.settings["button-css-name"])
|
||||
- btn.connect("clicked", self.launch, self.PlayerOps.PREVIOUS)
|
||||
- button_box.pack_start(btn, False, False, 1)
|
||||
-
|
||||
self.play_pause_btn = Gtk.Button()
|
||||
if self.settings["button-css-name"]:
|
||||
self.play_pause_btn.set_property("name", self.settings["button-css-name"])
|
||||
@@ -198,15 +189,6 @@ class Playerctl(Gtk.EventBox):
|
||||
self.play_pause_btn.connect("clicked", self.launch, self.PlayerOps.PLAY_PAUSE)
|
||||
button_box.pack_start(self.play_pause_btn, False, False, 1)
|
||||
|
||||
- img = Gtk.Image()
|
||||
- update_image(img, "media-skip-forward-symbolic", self.settings["icon-size"], icons_path=self.icons_path)
|
||||
- btn = Gtk.Button()
|
||||
- btn.set_image(img)
|
||||
- if self.settings["button-css-name"]:
|
||||
- btn.set_property("name", self.settings["button-css-name"])
|
||||
- btn.connect("clicked", self.launch, self.PlayerOps.NEXT)
|
||||
- button_box.pack_start(btn, False, False, 1)
|
||||
-
|
||||
self.label = AutoScrollLabel(self.settings["scroll"],
|
||||
self.settings["chars"],
|
||||
self.settings["interval"])
|
215
hosts/common/programs/nwg-panel/style.css
Normal file
215
hosts/common/programs/nwg-panel/style.css
Normal file
@@ -0,0 +1,215 @@
|
||||
/* foreground (text)/background */
|
||||
@define-color fg0 #d8d8d8;
|
||||
@define-color fg1 #ffffff;
|
||||
@define-color bg0 #130c0c;
|
||||
@define-color bg1 #1c1716;
|
||||
/* green accents */
|
||||
@define-color accent-g0 #1f5e54;
|
||||
@define-color accent-g1 #418379;
|
||||
@define-color accent-g2 #63a89c;
|
||||
/* red accents */
|
||||
@define-color accent-r0 #c96262;
|
||||
@define-color accent-r1 #d27871;
|
||||
@define-color accent-r2 #ff968b;
|
||||
/* light (teal-white) accents */
|
||||
@define-color accent-l0 #e1f0ef;
|
||||
@define-color accent-l1 #f9fffc;
|
||||
|
||||
|
||||
* {
|
||||
font-size: @fontSize@px;
|
||||
}
|
||||
|
||||
button {
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
#task-box {
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
}
|
||||
|
||||
#task-box-focused {
|
||||
background-color: @accent-g2;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
}
|
||||
|
||||
|
||||
#playerctl-button {
|
||||
background-color: rgba(0, 0, 0, 0.08);
|
||||
background-image: none;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
margin: -1;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
#panel-top {
|
||||
background: @accent-g1;
|
||||
color: @fg1;
|
||||
}
|
||||
|
||||
/* increase the size of each workspace icon */
|
||||
#sway-workspaces-item > label {
|
||||
padding-left: 1px;
|
||||
padding-right: 1px;
|
||||
}
|
||||
/* default config highlights hovered workspace with a gray border */
|
||||
#sway-workspaces > widget:selected {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* the CSS nodes are difficult to determine.
|
||||
* reference: <https://github.com/numixproject/numix-gtk-theme/blob/master/src/gtk-3.20/scss/widgets/_calendar.scss>
|
||||
*/
|
||||
#calendar-window {
|
||||
background-color: @accent-l0;
|
||||
}
|
||||
calendar {
|
||||
background-color: @accent-l0;
|
||||
}
|
||||
calendar :selected {
|
||||
background-color: @accent-r1;
|
||||
}
|
||||
|
||||
|
||||
#controls-window {
|
||||
border-radius: 15px;
|
||||
background: @bg1;
|
||||
color: @fg1;
|
||||
}
|
||||
|
||||
/* default config highlights selected items with a green border */
|
||||
widget:selected {
|
||||
box-shadow: none;
|
||||
background-color: @accent-g0;
|
||||
}
|
||||
#controls-window widget:selected {
|
||||
box-shadow: none;
|
||||
background-color: @accent-r0;
|
||||
}
|
||||
|
||||
/* default config puts a *ridiculous* amount of padding around the whole controls window */
|
||||
#controls-window > widget > .vertical {
|
||||
margin-left: -20px;
|
||||
margin-right: -20px;
|
||||
}
|
||||
#controls-window > widget > .vertical > .horizontal {
|
||||
margin-top: -14px; /* full reset would be -20px */
|
||||
margin-bottom: -20px;
|
||||
}
|
||||
/* add back in a little bit of padding, but in a way such that my highlights apply to it */
|
||||
#controls-window .horizontal widget > box,
|
||||
#controls-window > widget > .vertical > .horizontal > .vertical > .horizontal
|
||||
{
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
}
|
||||
#controls-window > widget > .vertical > .horizontal > .vertical > widget > box
|
||||
{
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
#controls-window > widget > .vertical > .horizontal > .vertical > box > widget > box
|
||||
{
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
|
||||
/* hierarchy is .horizontal > {image, scale > { value, contents > trough > { slider, highlight } } } */
|
||||
scale {
|
||||
padding-right: 0px;
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
scale trough {
|
||||
padding-left: 9px;
|
||||
padding-right: 9px;
|
||||
border-radius: 9px;
|
||||
border-color: rgba(0, 0, 0, 0);
|
||||
background: @bg0;
|
||||
}
|
||||
scale highlight {
|
||||
border-radius: 9px;
|
||||
border-color: rgba(0, 0, 0, 0);
|
||||
margin: 0px;
|
||||
margin-left: -9px;
|
||||
background: @accent-r1;
|
||||
}
|
||||
scale slider {
|
||||
margin-top: -3px;
|
||||
margin-bottom: -3px;
|
||||
background: @accent-l1;
|
||||
min-height: 25px;
|
||||
min-width: 25px;
|
||||
}
|
||||
|
||||
#clock {
|
||||
font-family: monospace;
|
||||
font-size: @clockFontSize@px;
|
||||
}
|
||||
|
||||
/* UNUSED IN MY CURRENT CONFIG: COPIED FROM SAMPLE CONFIG */
|
||||
|
||||
/* Controls window in sample config uses this name */
|
||||
/* Brightness slider popup window in sample config uses this name */
|
||||
#brightness-popup {
|
||||
border-radius: 15px;
|
||||
background: @bg1;
|
||||
color: @fg1;
|
||||
}
|
||||
#brightness-popup box {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
/* Executors usually behave better in monospace fonts */
|
||||
#executor-label {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
/* Bottom panel in sample config uses this name */
|
||||
#panel-bottom {
|
||||
background: #101010;
|
||||
color: #eeeeee;
|
||||
}
|
||||
|
||||
/* Sample executor-weather uses "css-name": "weather" */
|
||||
#weather {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* dwl-tags module */
|
||||
#dwl-tag-box {
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
|
||||
#dwl-tag-occupied {
|
||||
font-family: monospace;
|
||||
color: #eee;
|
||||
background-color: #006699;
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
}
|
||||
|
||||
#dwl-tag-free {
|
||||
font-family: monospace;
|
||||
color: #eee;
|
||||
background-color: rgba (32, 50, 90, 1.0);
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
}
|
||||
|
||||
#dwl-tag-urgent {
|
||||
font-family: monospace;
|
||||
color: #eee;
|
||||
background-color: #ee6600;
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
}
|
||||
|
||||
#dwl-tag-selected {
|
||||
border: solid 2px;
|
||||
border-color: #81a1c1;
|
||||
}
|
6
hosts/common/programs/pactl.nix
Normal file
6
hosts/common/programs/pactl.nix
Normal file
@@ -0,0 +1,6 @@
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
sane.programs.pactl = {
|
||||
packageUnwrapped = pkgs.linkIntoOwnPackage pkgs.pulseaudio "bin/pactl";
|
||||
};
|
||||
}
|
8
hosts/common/programs/ps.nix
Normal file
8
hosts/common/programs/ps.nix
Normal file
@@ -0,0 +1,8 @@
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
sane.programs.ps = {
|
||||
packageUnwrapped = pkgs.linkIntoOwnPackage pkgs.procps "bin/ps";
|
||||
sandbox.method = "bwrap";
|
||||
sandbox.isolatePids = false;
|
||||
};
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p sane-open
|
||||
#!nix-shell -i bash -p bash -p sane-open
|
||||
|
||||
# use:
|
||||
# rofi-run-command <handler>.desktop [cmd [args ...]]
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p gnused -p rofi -p wtype
|
||||
#!nix-shell -i bash -p bash -p gnused -p rofi -p wtype
|
||||
|
||||
# "bookmarking"/snippets inspired by Luke Smith:
|
||||
# - <https://www.youtube.com/watch?v=d_11QaTlf1I>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p coreutils -p jq -p killall -p playerctl -p procps -p sane-open -p sway -p util-linux -p wireplumber
|
||||
#!nix-shell -i bash -p bash -p coreutils -p jq -p killall -p playerctl -p procps -p sane-open -p sway -p util-linux -p wireplumber
|
||||
# vim: set filetype=bash :
|
||||
|
||||
# input map considerations
|
||||
|
10
hosts/common/programs/sane-sysinfo.nix
Normal file
10
hosts/common/programs/sane-sysinfo.nix
Normal file
@@ -0,0 +1,10 @@
|
||||
{ ... }:
|
||||
{
|
||||
sane.programs.sane-sysinfo = {
|
||||
sandbox.method = "bwrap";
|
||||
sandbox.extraPaths = [
|
||||
"/sys/class/power_supply"
|
||||
"/sys/devices"
|
||||
];
|
||||
};
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p jq -p sway -p util-linux
|
||||
#!nix-shell -i bash -p bash -p jq -p sway -p util-linux
|
||||
|
||||
help() {
|
||||
echo "queries the focused window and apply an appropriate display-wide scale."
|
||||
|
@@ -148,6 +148,7 @@ in
|
||||
"fontconfig"
|
||||
# "gnome.gnome-bluetooth" # XXX(2023/05/14): broken
|
||||
# "gnome.gnome-control-center" # XXX(2023/06/28): depends on webkitgtk4_1
|
||||
"nwg-panel"
|
||||
"pipewire"
|
||||
"playerctl" # for waybar & particularly to have playerctld running
|
||||
"rofi" # menu/launcher
|
||||
@@ -161,9 +162,10 @@ in
|
||||
"sway-contrib.grimshot" # used by sway config
|
||||
"swayidle" # enable if you need it
|
||||
"swaynotificationcenter" # notification daemon
|
||||
"switchboard" # network/bluetooth/sound control panel
|
||||
"sysvol" # volume notifier
|
||||
"unl0kr" # greeter
|
||||
"waybar" # used by sway config
|
||||
# "waybar"
|
||||
"wdisplays" # like xrandr
|
||||
"wireplumber" # used by sway config
|
||||
"wl-clipboard"
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p feedbackd -p procps -p swaynotificationcenter -p util-linux
|
||||
#!nix-shell -i bash -p bash -p feedbackd -p procps -p swaynotificationcenter -p util-linux
|
||||
|
||||
# this script does some really unusual indirection with the `start` action:
|
||||
# IT'S INTENTIONAL.
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p s6 -p s6-rc
|
||||
#!nix-shell -i bash -p bash -p s6 -p s6-rc
|
||||
|
||||
# for default $PATH to take precedence over nix-shell PATH if invoked interactively,
|
||||
# otherwise we invoke a s6-rc which does not know where to find files.
|
||||
|
28
hosts/common/programs/switchboard.nix
Normal file
28
hosts/common/programs/switchboard.nix
Normal file
@@ -0,0 +1,28 @@
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
sane.programs.switchboard = {
|
||||
packageUnwrapped = with pkgs.pantheon; switchboard-with-plugs.override {
|
||||
switchboardPlugs = [
|
||||
# switchboard-plug-a11y
|
||||
# switchboard-plug-about
|
||||
# switchboard-plug-applications
|
||||
# switchboard-plug-bluetooth #< TODO(2024/06/13): would be nice to have, but doesn't cross-compile
|
||||
# switchboard-plug-datetime
|
||||
# switchboard-plug-display # could be handy, but crashes
|
||||
# switchboard-plug-keyboard
|
||||
# switchboard-plug-mouse-touchpad # changing settings here doesn't actually impact anything real
|
||||
switchboard-plug-network
|
||||
# switchboard-plug-notifications
|
||||
# switchboard-plug-onlineaccounts
|
||||
# switchboard-plug-pantheon-shell
|
||||
# switchboard-plug-power # needs to be "unlocked" before it can do anything (like change display brightness)
|
||||
# switchboard-plug-printers # requires cups
|
||||
# switchboard-plug-security-privacy
|
||||
# switchboard-plug-sharing
|
||||
switchboard-plug-sound
|
||||
# switchboard-plug-wacom
|
||||
];
|
||||
xorg = pkgs.buildPackages.xorg; #< cross compilation fix (TODO: upstream)
|
||||
};
|
||||
};
|
||||
}
|
@@ -59,7 +59,7 @@
|
||||
partOf = [ "graphical-session" ];
|
||||
|
||||
# options:
|
||||
# -p {0,1,2,3} to attach to top/right/bottom/left screen edge
|
||||
# -p {bottom,left,right,top} to attach to the corresponding screen edge
|
||||
# -t N for the notifier to be dismissed after N seconds (integer only)
|
||||
# -T N reveal/hide transition time in milliseconds
|
||||
# -m N to set the indicator this many pixels in from the edge.
|
||||
@@ -67,7 +67,7 @@
|
||||
# -{H,W} N to set the height/width of the notifier, in px.
|
||||
# -i N to set the size of the volume icon
|
||||
# -P to hide percentage text
|
||||
command = "sysvol -p 0 -t 1 -T 0 -m 22 -H 39 -W 256 -i 32 -P";
|
||||
command = "sysvol -p top -t 1 -T 0 -m 22 -H 39 -W 256 -i 32 -P";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@@ -15,6 +15,15 @@ let
|
||||
PATH=$PATH:$extraPath command -v "$1"
|
||||
}
|
||||
|
||||
# give some time for the framebuffer device to appear;
|
||||
# unl0kr depends on it but doesn't know to wait for it.
|
||||
for _ in $(seq 25); do
|
||||
if [ -e /dev/fb0 ]; then
|
||||
break
|
||||
fi
|
||||
sleep 0.2
|
||||
done
|
||||
|
||||
# TODO: make this more robust to failure.
|
||||
# - if `unl0kr` fails, then the second `redirect-tty` sends a newline to `login`, causing it to exit and the service fails.
|
||||
# - if `redirect-tty` fails, then... the service is left hanging.
|
||||
@@ -134,8 +143,6 @@ in
|
||||
# necessary for `sanebox` to be found. TODO: add this to every systemd service.
|
||||
"/run/current-system/sw" # `/bin` is appended
|
||||
];
|
||||
# needed to find sanebox profiles (TODO: add this to every service)
|
||||
environment.XDG_DATA_DIRS = "/run/current-system/sw/share";
|
||||
|
||||
serviceConfig.Type = "simple";
|
||||
serviceConfig.Restart = "always";
|
||||
|
@@ -1,7 +1,7 @@
|
||||
[general]
|
||||
animations=false
|
||||
#backend=fbdev|drm
|
||||
#timeout=300
|
||||
# backend=fbdev|drm
|
||||
# timeout=300
|
||||
|
||||
[keyboard]
|
||||
autohide=false
|
||||
@@ -16,12 +16,14 @@ obscured=true
|
||||
default=breezy-light
|
||||
alternate=breezy-dark
|
||||
|
||||
#[input]
|
||||
#keyboard=false
|
||||
#pointer=false
|
||||
#touchscreen=false
|
||||
# [input]
|
||||
# keyboard=false
|
||||
# pointer=false
|
||||
# touchscreen=false
|
||||
|
||||
#[quirks]
|
||||
#fbdev_force_refresh=true
|
||||
#terminal_prevent_graphics_mode=true
|
||||
#terminal_allow_keyboard_input=true
|
||||
# [quirks]
|
||||
# fbdev_force_refresh=true
|
||||
# terminal_prevent_graphics_mode=true
|
||||
# TODO: terminal_allow_keyboard_input=true could be used to pipe my password
|
||||
# straight into `login`, instead of the more convoluted redirect approach??
|
||||
# terminal_allow_keyboard_input=true
|
||||
|
@@ -110,7 +110,7 @@ in
|
||||
};
|
||||
|
||||
services.waybar = {
|
||||
description = "swaybar graphical header bar/tray for sway";
|
||||
description = "waybar status/topbar for sway";
|
||||
partOf = [ "graphical-session" ];
|
||||
|
||||
# env G_MESSAGES_DEBUG=all
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p jq -p playerctl
|
||||
#!nix-shell -i bash -p bash -p jq -p playerctl
|
||||
status=$(playerctl status 2> /dev/null | tr 'A-Z' 'a-z')
|
||||
if [ -z "$status" ]; then
|
||||
status="inactive"
|
||||
|
@@ -115,6 +115,7 @@ in
|
||||
programs.zsh = lib.mkIf cfg.enabled {
|
||||
enable = true;
|
||||
shellAliases = {
|
||||
":fg" = "fg";
|
||||
":q" = "exit";
|
||||
# common typos
|
||||
"cd.." = "cd ..";
|
||||
@@ -186,7 +187,7 @@ in
|
||||
};
|
||||
|
||||
function switch() {
|
||||
nix run '.#deploy.self'
|
||||
~/nixos/scripts/deploy "$@"
|
||||
}
|
||||
'';
|
||||
|
||||
|
@@ -7,9 +7,12 @@ let
|
||||
haltTimeout = 10;
|
||||
in
|
||||
{
|
||||
# allow ordinary users to `reboot` or `shutdown`.
|
||||
# source: <https://nixos.wiki/wiki/Polkit>
|
||||
security.polkit.extraConfig = ''
|
||||
/* allow ordinary users to:
|
||||
* - reboot
|
||||
* - shutdown
|
||||
* source: <https://nixos.wiki/wiki/Polkit>
|
||||
*/
|
||||
polkit.addRule(function(action, subject) {
|
||||
if (
|
||||
subject.isInGroup("users")
|
||||
@@ -24,6 +27,19 @@ in
|
||||
return polkit.Result.YES;
|
||||
}
|
||||
})
|
||||
|
||||
/* allow members of wheel to:
|
||||
* - systemctl daemon-reload
|
||||
* - systemctl stop|start|restart SERVICE
|
||||
*/
|
||||
polkit.addRule(function(action, subject) {
|
||||
if (subject.isInGroup("wheel") && (
|
||||
action.id == "org.freedesktop.systemd1.reload-daemon" ||
|
||||
action.id == "org.freedesktop.systemd1.manage-units"
|
||||
)) {
|
||||
return polkit.Result.YES;
|
||||
}
|
||||
})
|
||||
'';
|
||||
|
||||
services.journald.extraConfig = ''
|
||||
|
@@ -22,6 +22,7 @@
|
||||
"media" # servo
|
||||
"networkmanager"
|
||||
"nixbuild"
|
||||
"render" # for crappy, /dev/dri/render*
|
||||
"seat" # for sway, if using seatd
|
||||
"systemd-journal" # allows to view other user's journals (esp system users)
|
||||
"transmission" # servo
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash
|
||||
#!nix-shell -i bash -p bash
|
||||
file="$1"
|
||||
enc="$2"
|
||||
nibbles="$3"
|
||||
|
@@ -128,36 +128,41 @@ in
|
||||
# });
|
||||
# boot.kernelPackages = with pkgs; linuxPackagesFor linux_6_1;
|
||||
# boot.kernelPackages = with pkgs; linuxPackagesFor linux-exynos5-mainline;
|
||||
boot.kernelPackages = with pkgs; linuxPackagesFor (linux-postmarketos-exynos5.override {
|
||||
# linux = let version = "6.6.0-rc1"; rev = "6.6.0-rc6-bi-5264"; in {
|
||||
# # src = pkgs.fetchzip {
|
||||
# # url = "https://git.kernel.org/stable/t/linux-6.2.16.tar.gz";
|
||||
# # };
|
||||
# src = pkgs.fetchFromGitea {
|
||||
# domain = "git.uninsane.org";
|
||||
# owner = "colin";
|
||||
# repo = "linux";
|
||||
# rev = "v${rev}";
|
||||
# hash = linuxSourceHashes."${rev}";
|
||||
# };
|
||||
# inherit version;
|
||||
# modDirVersion = version;
|
||||
# extraMakeFlags = [];
|
||||
# };
|
||||
# linux = linux_6_6;
|
||||
# linux = linux_6_8;
|
||||
# linux = linux_6_9;
|
||||
linux = linux_latest;
|
||||
# optimizeForSize = true;
|
||||
# useEdpPanel = true;
|
||||
revertPanelSimplePatch = true;
|
||||
});
|
||||
# boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux-postmarketos-exynos5;
|
||||
# boot.kernelPackages = pkgs.linuxPackagesFor (pkgs.linux_latest.override {
|
||||
# kernelPatches = [
|
||||
# pkgs.linux-postmarketos-exynos5.sanePatches.revertPanelSimplePatch
|
||||
# ];
|
||||
# boot.kernelPackages = with pkgs; linuxPackagesFor (linux-postmarketos-exynos5.override {
|
||||
# # linux = let version = "6.6.0-rc1"; rev = "6.6.0-rc6-bi-5264"; in {
|
||||
# # # src = pkgs.fetchzip {
|
||||
# # # url = "https://git.kernel.org/stable/t/linux-6.2.16.tar.gz";
|
||||
# # # };
|
||||
# # src = pkgs.fetchFromGitea {
|
||||
# # domain = "git.uninsane.org";
|
||||
# # owner = "colin";
|
||||
# # repo = "linux";
|
||||
# # rev = "v${rev}";
|
||||
# # hash = linuxSourceHashes."${rev}";
|
||||
# # };
|
||||
# # inherit version;
|
||||
# # modDirVersion = version;
|
||||
# # extraMakeFlags = [];
|
||||
# # };
|
||||
# # linux = linux_6_6;
|
||||
# # linux = linux_6_8;
|
||||
# # linux = linux_6_9;
|
||||
# linux = linux_latest;
|
||||
# # optimizeForSize = true;
|
||||
# # useEdpPanel = true;
|
||||
# revertPanelSimplePatch = true;
|
||||
# });
|
||||
# boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux-postmarketos-exynos5;
|
||||
boot.kernelPackages = pkgs.linuxPackagesFor (pkgs.linux-exynos5-mainline.override {
|
||||
kernelPatches = [
|
||||
pkgs.linux-postmarketos-exynos5.sanePatches.revertPanelSimplePatch
|
||||
];
|
||||
structuredExtraConfig = with lib.kernel; {
|
||||
SECURITY = yes;
|
||||
SECURITY_LANDLOCK = yes;
|
||||
LSM = freeform "landlock,lockdown,yama,loadpin,safesetid,selinux,smack,tomoyo,apparmor,bpf";
|
||||
};
|
||||
});
|
||||
|
||||
system.build.u-boot = pkgs.buildUBoot {
|
||||
defconfig = "snow_defconfig";
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p gnused
|
||||
#!nix-shell -i bash -p bash -p gnused
|
||||
# usage: install-bluetooth <source_dir> <destdir>
|
||||
# source_dir contains plain-text files of any filename.
|
||||
# for each file, this extracts the MAC and creates a symlink in destdir which
|
||||
|
@@ -56,6 +56,16 @@
|
||||
modules.windowTitle = false;
|
||||
# TODO: show modem state
|
||||
};
|
||||
sane.programs.nwg-panel.config = {
|
||||
fontSize = 14;
|
||||
height = 26;
|
||||
windowIcon = false;
|
||||
windowTitle = false;
|
||||
mediaPrevNext = false;
|
||||
mediaTitle = false;
|
||||
workspaceNumbers = [ "1" "2" "3" "4" "5" ];
|
||||
workspaceHideEmpty = false;
|
||||
};
|
||||
|
||||
sane.programs.zsh.config.showDeadlines = false; # unlikely to act on them when in shell
|
||||
};
|
||||
|
5
integrations/nixpkgs/nixpkgs-overlays.nix
Normal file
5
integrations/nixpkgs/nixpkgs-overlays.nix
Normal file
@@ -0,0 +1,5 @@
|
||||
# this file exists so i can use my custom packages inside `nix-shell`.
|
||||
# it works by using stock upstream `nixpkgs`
|
||||
# and putting NIX_PATH=nixpkgs-overlays=/path/to/here on the nixbld environment.
|
||||
#
|
||||
[(import ../../overlays/all.nix)]
|
@@ -4,6 +4,6 @@
|
||||
"site_name": " bunnie's blog",
|
||||
"site_url": "https://www.bunniestudios.com",
|
||||
"title": "bunnie's blog",
|
||||
"url": "https://www.bunniestudios.com/blog/?feed=rss2",
|
||||
"velocity": 0.108
|
||||
"url": "https://www.bunniestudios.com/blog/feed/",
|
||||
"velocity": 0.12
|
||||
}
|
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"description": "Radiolab",
|
||||
"description": "Radiolab is on a curiosity bender. We ask deep questions and use investigative journalism to get the answers. A given episode might whirl you through science, legal history, and into the home of someone halfway across the world. The show is known for innovative sound design, smashing information into music. It is hosted by Lulu Miller and Latif Nasser.",
|
||||
"is_podcast": true,
|
||||
"site_name": "",
|
||||
"site_url": "",
|
||||
"title": "Radiolab",
|
||||
"url": "https://feeds.feedburner.com/radiolab",
|
||||
"velocity": 0.136
|
||||
"url": "https://feeds.simplecast.com/EmVW7VGp",
|
||||
"velocity": 0.138
|
||||
}
|
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"description": "*** Named a best podcast of 2021 by Time, Vulture, Esquire and The Atlantic. ***\nEach Tuesday and Friday, Ezra Klein invites you into a conversation on something that matters. How do we address climate change if the political system fails to act? Has the logic of markets infiltrated too many aspects of our lives? What is the future of the Republican Party? What do psychedelics teach us about consciousness? What does sci-fi understand about our present that we miss? Can our food system be just to humans and animals alike?\n\nListen to this podcast in New York Times Audio, our new iOS app for news subscribers. Download now at nytimes.com/audioapp",
|
||||
"description": "Each Tuesday and Friday, Ezra Klein invites you into a conversation on something that matters. How do we address climate change if the political system fails to act? Has the logic of markets infiltrated too many aspects of our lives? What is the future of the Republican Party? What do psychedelics teach us about consciousness? What does sci-fi understand about our present that we miss? Can our food system be just to humans and animals alike?\n\nListen to this podcast in New York Times Audio, our iOS app for news subscribers. Download now at nytimes.com/audioapp",
|
||||
"is_podcast": true,
|
||||
"site_name": "",
|
||||
"site_url": "",
|
||||
"title": "The Ezra Klein Show",
|
||||
"url": "https://feeds.simplecast.com/82FI35Px",
|
||||
"velocity": 0.264
|
||||
"velocity": 0.257
|
||||
}
|
@@ -2,8 +2,8 @@
|
||||
"description": "Long conversations with clever Nixers.",
|
||||
"is_podcast": true,
|
||||
"site_name": "",
|
||||
"site_url": "",
|
||||
"site_url": "https://feeds.transistor.fm",
|
||||
"title": "Full Time Nix",
|
||||
"url": "https://feeds.transistor.fm/full-time-nix",
|
||||
"velocity": 0
|
||||
"velocity": 0.048
|
||||
}
|
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"description": "<p>Playful explorations of the rich past and exciting future that we're all building with our silly little computers. Hosted by Jimmy Miller and Ivan Reese.</p>",
|
||||
"is_podcast": true,
|
||||
"site_name": "",
|
||||
"site_url": "",
|
||||
"site_name": "Omny Studio",
|
||||
"site_url": "https://www.omnycontent.com",
|
||||
"title": "Future of Coding",
|
||||
"url": "https://www.omnycontent.com/d/playlist/c4157e60-c7f8-470d-b13f-a7b30040df73/564f493f-af32-4c48-862f-a7b300e4df49/ac317852-8807-44b8-8eff-a7b300e4df52/podcast.rss",
|
||||
"velocity": 0.028
|
||||
|
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"description": "<p>The most unruly and least considered, most shameful among various Idiomdrottning components and libraries can be found here.</p>\n <p>To contact me, <a href=\"mailto:sandra.snan@idiomdrottning.org\">send mail to sandra.snan@idiomdrottning.org</a></p>",
|
||||
"is_podcast": false,
|
||||
"site_name": "Idiomdrottning",
|
||||
"site_name": "I live like them already",
|
||||
"site_url": "https://idiomdrottning.org",
|
||||
"title": "Idiomdrottning",
|
||||
"url": "https://idiomdrottning.org/blog",
|
||||
"velocity": 0.402
|
||||
"velocity": 0.867
|
||||
}
|
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"description": "Kill the Newsletter! Inbox:\n joh91bv7am2pnznv@kill-the-newsletter.com \u2192\n https://kill-the-newsletter.com/feeds/joh91bv7am2pnznv.xml",
|
||||
"description": null,
|
||||
"is_podcast": false,
|
||||
"site_name": "Kill the Newsletter!",
|
||||
"site_url": "https://kill-the-newsletter.com",
|
||||
"title": "Money Stuff",
|
||||
"url": "https://kill-the-newsletter.com/feeds/joh91bv7am2pnznv.xml",
|
||||
"velocity": 939.13
|
||||
"velocity": 0.667
|
||||
}
|
@@ -2,8 +2,8 @@
|
||||
"description": "The art, science, and history of processor design..",
|
||||
"is_podcast": true,
|
||||
"site_name": "",
|
||||
"site_url": "",
|
||||
"site_url": "https://feeds.transistor.fm",
|
||||
"title": "Microarch Club",
|
||||
"url": "https://feeds.transistor.fm/microarch-club",
|
||||
"velocity": 0.083
|
||||
"velocity": 0.08
|
||||
}
|
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"description": "<p>As long as there’s been oppression, there’ve been people fighting it. This weekly podcast dives into history to drag up the wildest rebels, the most beautiful revolts, and all the people who long to be—and fight to be—free. It explores complex stories of resistance that offer lessons and inspiration for us today, focusing on the ensemble casts that make up each act of history. That is to say, this podcast focuses on Cool People Who Did Cool Stuff.</p>",
|
||||
"description": "<p>As long as there\u2019s been oppression, there\u2019ve been people fighting it. This weekly podcast dives into history to drag up the wildest rebels, the most beautiful revolts, and all the people who long to be\u2014and fight to be\u2014free. It explores complex stories of resistance that offer lessons and inspiration for us today, focusing on the ensemble casts that make up each act of history. That is to say, this podcast focuses on Cool People Who Did Cool Stuff.</p>",
|
||||
"is_podcast": true,
|
||||
"site_name": "Omny Studio",
|
||||
"site_url": "https://www.omnycontent.com",
|
||||
"title": "Cool People Who Did Cool Stuff",
|
||||
"url": "https://www.omnycontent.com/d/playlist/e73c998e-6e60-432f-8610-ae210140c5b1/45bcda9a-4724-45c0-82ca-ae7f00e1dd18/f21245f2-a297-42f7-a016-ae7f00e390c4/podcast.rss",
|
||||
"velocity": 0.271
|
||||
"velocity": 0.299
|
||||
}
|
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"description": "<p>The audio companion to Bloomberg Opinion\u2019s beloved Money Stuff column hosted by its author Matt Levine, \u201cwhose deadpan style mixes technical elucidation and wit\u201d (NY Times). Once a week, Matt and his friend, Bloomberg News reporter and TV host, Katie Greifeld talk about Wall Street, finance and\u2026other stuff. New episodes every Friday.</p>",
|
||||
"description": "<p>The audio companion to Bloomberg Opinion\u2019s beloved Money Stuff column hosted by its author Matt Levine, \u201cwhose deadpan style mixes technical elucidation and wit\u201d (NY Times). Once a week, Matt and his friend, Bloomberg News reporter and TV host Katie Greifeld, talk about Wall Street, finance and\u2026other stuff. New episodes every Friday.</p>",
|
||||
"is_podcast": true,
|
||||
"site_name": "",
|
||||
"site_url": "",
|
||||
"site_name": "Omny Studio",
|
||||
"site_url": "https://www.omnycontent.com",
|
||||
"title": "Money Stuff: The Podcast",
|
||||
"url": "https://www.omnycontent.com/d/playlist/e73c998e-6e60-432f-8610-ae210140c5b1/ee4336cb-155f-4488-90e0-b1400134e40e/77e6a3a7-290d-4a82-8164-b14001353ef2/podcast.rss",
|
||||
"velocity": 0.063
|
||||
"velocity": 0.125
|
||||
}
|
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"description": "<p>Comedians Dave Anthony and Gareth Reynolds picks a subject from history and examine it.</p>",
|
||||
"is_podcast": true,
|
||||
"site_name": "",
|
||||
"site_url": "",
|
||||
"site_name": "Omny Studio",
|
||||
"site_url": "https://www.omnycontent.com",
|
||||
"title": "The Dollop with Dave Anthony and Gareth Reynolds",
|
||||
"url": "https://www.omnycontent.com/d/playlist/885ace83-027a-47ad-ad67-aca7002f1df8/22b063ac-654d-428f-bd69-ae2400349cde/65ff0206-b585-4e2a-9872-ae240034c9c9/podcast.rss",
|
||||
"velocity": 0.188
|
||||
"velocity": 0.192
|
||||
}
|
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"description": "Explore human evolution one story at a time. This award-winning show blends storytelling with science that will change your understanding of who we are.",
|
||||
"is_podcast": true,
|
||||
"site_name": "",
|
||||
"site_url": "",
|
||||
"site_name": "test220119a",
|
||||
"site_url": "https://feeds.libsyn.com",
|
||||
"title": "Origin Stories",
|
||||
"url": "https://feeds.libsyn.com/65014/rss",
|
||||
"velocity": 0.024
|
||||
|
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"description": "<p>Weekly roundup of everything new in the Linux and Open Source world! May contain gaming and privacy related topics.</p>\n<p>This is a longer counterpart to the Linux and Open Source news videos available on The Linux Experiment Youtube Channel.</p>",
|
||||
"description": "<p>Weekly roundup of everything new in the Linux and Open Source world! May contain gaming and privacy related topics.</p>\n<p>This is a longer counterpart to the Linux and Open Source news videos available on The Linux Experiment Youtube Channel.</p>\n<p>I\u2019m Nick, I\u2019ve been making Linux and Open Source related videos on YouTube since 2018, with a sizeable following of more than 300 000 subscribers. I\u2019ve been using Linux since 2006, starting with Ubuntu (like most people), and I have 12 years of experience in project management and UX, and that\u2019s the lens I use to view the progress of our Linux desktops and open source applications!</p>",
|
||||
"is_podcast": true,
|
||||
"site_name": "The Linux Experiment Podcasts",
|
||||
"site_url": "https://podcast.thelinuxexp.com",
|
||||
"title": "Linux + Open Source News, by TLE",
|
||||
"title": "Linux & Open Source News",
|
||||
"url": "https://podcast.thelinuxexp.com/@tlenewspodcast/feed.xml",
|
||||
"velocity": 0.145
|
||||
"velocity": 0.147
|
||||
}
|
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"description": "A Comic",
|
||||
"is_podcast": false,
|
||||
"site_name": "Poorly Drawn Lines",
|
||||
"site_name": "Poorly Drawn Lines | A Comic",
|
||||
"site_url": "https://poorlydrawnlines.com",
|
||||
"title": "Poorly Drawn Lines",
|
||||
"url": "https://poorlydrawnlines.com/feed/",
|
||||
"velocity": 0.237
|
||||
"velocity": 0.3
|
||||
}
|
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"description": "Announcing appearances, publications, and analysis of questions historical, philosophical, and political by author, philosopher, and historian Richard Carrier.",
|
||||
"is_podcast": false,
|
||||
"site_name": "Richard Carrier",
|
||||
"site_name": "Richard Carrier Blogs",
|
||||
"site_url": "https://www.richardcarrier.info",
|
||||
"title": "Richard Carrier",
|
||||
"title": "Richard Carrier Blogs",
|
||||
"url": "https://www.richardcarrier.info/feed",
|
||||
"velocity": 0.141
|
||||
"velocity": 0.131
|
||||
}
|
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"description": "It\u2019s getting harder and harder to talk about politics, especially if you disagree. Well, screw that. Seattle Nice aims to be the most opinionated and smartest analysis of what\u2019s really happening in Seattle politics available in any medium. Each episode dives into contentious and sometimes ridiculous topics, exploring perspectives from across Seattle's political spectrum, from city council brawls to the ways the national political conversation filters through our unique political process. Even if you\u2019re not from Seattle, you need to listen to Seattle Nice. Because it\u2019s coming for you. Unlike the sun, politics rises in the West and sets in the East.",
|
||||
"description": "<p>It\u2019s getting harder and harder to talk about politics, especially if you disagree. Well, screw that. Seattle Nice aims to be the most opinionated and smartest analysis of what\u2019s really happening in Seattle politics available in any medium. Each episode dives into contentious and sometimes ridiculous topics, exploring perspectives from across Seattle's political spectrum, from city council brawls to the ways the national political conversation filters through our unique political process. Even if you\u2019re not from Seattle, you need to listen to Seattle Nice. Because it\u2019s coming for you. Unlike the sun, politics rises in the West and sets in the East. </p>",
|
||||
"is_podcast": true,
|
||||
"site_name": "",
|
||||
"site_url": "",
|
||||
"title": "Seattle Nice",
|
||||
"url": "https://feeds.buzzsprout.com/1897925.rss",
|
||||
"velocity": 0.099
|
||||
"velocity": 0.101
|
||||
}
|
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"description": "On Target Technology News",
|
||||
"is_podcast": false,
|
||||
"site_name": "SemiAccurate - On Target Technology News",
|
||||
"site_name": "SemiAccurate",
|
||||
"site_url": "https://semiaccurate.com",
|
||||
"title": "SemiAccurate",
|
||||
"url": "https://www.semiaccurate.com/feed/",
|
||||
"velocity": 0.106
|
||||
"velocity": 0.098
|
||||
}
|
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"description": "Latest Saturday Morning Breakfast Cereal comics and news",
|
||||
"is_podcast": false,
|
||||
"site_name": "Saturday Morning Breakfast Cereal - Got You",
|
||||
"site_name": "Saturday Morning Breakfast Cereal - Dave",
|
||||
"site_url": "https://www.smbc-comics.com",
|
||||
"title": "Saturday Morning Breakfast Cereal",
|
||||
"url": "https://www.smbc-comics.com/comic/rss",
|
||||
"velocity": 1.172
|
||||
"velocity": 0.999
|
||||
}
|
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"description": "<p>Tales From the Bridge is a bi-weekly Science Fiction podcast. Join Tristan, Kevin, James, and Sam as they chat with your favourite science fiction authors and filmmakers. We also discuss the best in sci-fi, from books and graphic novels - to television and film. We cover cutting-edge concepts in our news segment, Science Fiction-Science Fact and throw in a bit of trivia for fun. <br /><br />Apple Podcasts; https://podcasts.apple.com/us/podcast/tales-from-the-bridge-all-things-sci-fi/id1570902818 Find out more on our website: https://talesfromthebridge.buzzsprout.com/</p>",
|
||||
"description": "<p>Tales From the Bridge is a podcast that discusses all things science fiction. Join Tristan, Kevin, James, Sam as they chat with your favourite science fiction authors and filmmakers. We talk about the best in sci-fi, from books and graphic novels - to television and film. We cover cutting-edge concepts in our news segment, Science Fiction-Science Fact, and often throw in a bit of trivia for fun. <br /><br />Subscribe, follow, like and leave a review. We'd love to hear from you! </p>",
|
||||
"is_podcast": true,
|
||||
"site_name": "",
|
||||
"site_url": "",
|
||||
"title": "Tales From The Bridge: All Things Sci-Fi",
|
||||
"title": "Tales From The Bridge",
|
||||
"url": "https://feeds.buzzsprout.com/1795352.rss",
|
||||
"velocity": 0.093
|
||||
"velocity": 0.091
|
||||
}
|
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"description": "turnoff.us is a geek comic site. Comics about Programming Languages, Web, Cloud, Linux, etc.",
|
||||
"description": "{turnoff.us} is a webcomic that explores the worlds of programming, operating systems, and tech professional life.",
|
||||
"is_podcast": false,
|
||||
"site_name": "turnoff.us",
|
||||
"site_url": "http://turnoff.us",
|
||||
"title": "turnoff.us - geek comic site",
|
||||
"title": "turnoff.us",
|
||||
"url": "https://turnoff.us/feed.xml",
|
||||
"velocity": 0.01
|
||||
"velocity": 0.377
|
||||
}
|
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"description": "systems | complexity | second-order effects",
|
||||
"is_podcast": false,
|
||||
"site_name": "Unintended Consequences - systems | complexity | second-order effects",
|
||||
"site_name": "Unintended Consequences",
|
||||
"site_url": "https://unintendedconsequenc.es",
|
||||
"title": "Unintended Consequences",
|
||||
"url": "https://unintendedconsequenc.es/feed/",
|
||||
"velocity": 0.01
|
||||
"velocity": 0.009
|
||||
}
|
9
modules/data/feeds/sources/xorvoid.com/default.json
Normal file
9
modules/data/feeds/sources/xorvoid.com/default.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"description": "If you stare into the void long enough, you'll find some xors staring back",
|
||||
"is_podcast": false,
|
||||
"site_name": "xorvoid",
|
||||
"site_url": "https://xorvoid.com",
|
||||
"title": "xorvoid",
|
||||
"url": "https://xorvoid.com/rss.xml",
|
||||
"velocity": 0.048
|
||||
}
|
@@ -8,6 +8,7 @@
|
||||
./ids.nix
|
||||
./programs
|
||||
./image.nix
|
||||
./netns.nix
|
||||
./persist
|
||||
./ports.nix
|
||||
./root-on-tmpfs.nix
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash
|
||||
#!nix-shell -i bash -p bash
|
||||
|
||||
set -e
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash
|
||||
#!nix-shell -i bash -p bash
|
||||
|
||||
set -e
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash
|
||||
#!nix-shell -i bash -p bash
|
||||
set -e
|
||||
|
||||
fspath="$1"
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash
|
||||
#!nix-shell -i bash -p bash
|
||||
|
||||
set -e
|
||||
|
||||
|
120
modules/netns.nix
Normal file
120
modules/netns.nix
Normal file
@@ -0,0 +1,120 @@
|
||||
{ config, lib, pkgs, sane-lib, ... }:
|
||||
let
|
||||
cfg = config.sane.netns;
|
||||
netnsOpts = with lib; types.submodule {
|
||||
options = {
|
||||
dns = mkOption {
|
||||
type = types.str;
|
||||
default = "1.1.1.1"; #< TODO: make the default be to forward DNS queries to the init namespace.
|
||||
};
|
||||
hostVethIpv4 = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
netnsVethIpv4 = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
netnsPubIpv4 = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
routeTable = mkOption {
|
||||
type = types.int;
|
||||
description = ''
|
||||
numeric ID for iproute2 (0-255?).
|
||||
each netns gets its own routing table so that i can route a packet out by placing it in the table.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
mkNetNsConfig = name: opts: with opts; {
|
||||
networking.localCommands = let
|
||||
iptables = "${pkgs.iptables}/bin/iptables";
|
||||
in-ns = "ip netns exec ${name}";
|
||||
bridgePort = port: proto: ''
|
||||
${in-ns} ${iptables} -A PREROUTING -t nat -p ${proto} --dport ${port} -m iprange --dst-range ${netnsPubIpv4} \
|
||||
-j DNAT --to-destination ${hostVethIpv4}
|
||||
'';
|
||||
bridgeStatements = lib.foldlAttrs
|
||||
(acc: port: portCfg: acc ++ (builtins.map (bridgePort port) portCfg.protocol))
|
||||
[]
|
||||
(lib.filterAttrs
|
||||
(port: portCfg: portCfg.visibleTo."${name}")
|
||||
config.sane.ports.ports
|
||||
)
|
||||
;
|
||||
in ''
|
||||
ip netns add ${name} || (test -e /run/netns/${name} && echo "${name} already exists")
|
||||
# DOCS:
|
||||
# - some of this approach is described here: <https://josephmuia.ca/2018-05-16-net-namespaces-veth-nat/>
|
||||
# - iptables primer: <https://danielmiessler.com/study/iptables/>
|
||||
# create veth pair
|
||||
ip link add ${name}-veth-a type veth peer name ${name}-veth-b || echo "${name}-veth-{a,b} aleady exists"
|
||||
ip addr add ${hostVethIpv4}/24 dev ${name}-veth-a || echo "${name}-veth-a aleady has IP address"
|
||||
ip link set ${name}-veth-a up
|
||||
|
||||
# move veth-b into the namespace
|
||||
ip link set ${name}-veth-b netns ${name} || echo "${name}-veth-b was already moved into its netns"
|
||||
${in-ns} ip addr add ${netnsVethIpv4}/24 dev ${name}-veth-b || echo "${name}-veth-b aleady has IP address"
|
||||
${in-ns} ip link set ${name}-veth-b up
|
||||
|
||||
# make it so traffic originating from the host side of the veth
|
||||
# is sent over the veth no matter its destination.
|
||||
ip rule add from ${hostVethIpv4} lookup ${name} pref 50 || echo "${name} already has ip rules (pref 50)"
|
||||
|
||||
# for traffic originating at the host veth to the WAN, use the veth as our gateway
|
||||
# not sure if the metric 1002 matters.
|
||||
ip route add default via ${netnsVethIpv4} dev ${name}-veth-a proto kernel src ${hostVethIpv4} metric 1002 table ${name} || \
|
||||
echo "${name} already has default route"
|
||||
# give the default route lower priority
|
||||
ip rule add from all lookup local pref 100 || echo "${name}: already has ip rules (pref 100)"
|
||||
ip rule del from all lookup local pref 0 || echo "${name}: already removed ip rule of default lookup (pref 0)"
|
||||
|
||||
# in order to access DNS in this netns, we need to route it to the VPN's nameservers
|
||||
# - alternatively, we could fix DNS servers like 1.1.1.1.
|
||||
${in-ns} ${iptables} -A OUTPUT -t nat -p udp --dport 53 -m iprange --dst-range 127.0.0.53 \
|
||||
-j DNAT --to-destination ${dns}:53
|
||||
'' + (lib.concatStringsSep "\n" bridgeStatements);
|
||||
|
||||
# postShutdown = ''
|
||||
# ${in-ns} ip link del ${name}-veth-b || echo "couldn't delete ${name}-veth-b"
|
||||
# ip link del ${name}-veth-a || echo "couldn't delete ${name}-veth-a"
|
||||
# ip netns delete ${name} || echo "couldn't delete ${name}"
|
||||
# # restore rules/routes
|
||||
# ip rule del from ${veth-host-ip} lookup ${name} pref 50 || echo "couldn't delete init -> ${name} rule"
|
||||
# ip route del default via ${veth-local-ip} dev ${name}-veth-a proto kernel src ${veth-host-ip} metric 1002 table ${name} || echo "couldn't delete init > #{name} route"
|
||||
# ip rule add from all lookup local pref 0
|
||||
# ip rule del from all lookup local pref 100
|
||||
# '';
|
||||
|
||||
# specifically, we need to set these up before wireguard-wg-*,
|
||||
# whose unit files are BEFORE "network.target", and therefore
|
||||
# ordered ambiguously w.r.t. network-local-commands (a dep of "network.target").
|
||||
systemd.services.network-local-commands.wantedBy = [ "network-pre.target" ];
|
||||
systemd.services.network-local-commands.before = [ "network-pre.target" ];
|
||||
|
||||
# create a new routing table that we can use to proxy traffic out of the root namespace
|
||||
# through the wireguard namespaces, and to the WAN via VPN.
|
||||
# i think the numbers here aren't particularly important.
|
||||
networking.iproute2.rttablesExtraConfig = ''
|
||||
${builtins.toString routeTable} ${name}
|
||||
'';
|
||||
networking.iproute2.enable = true;
|
||||
};
|
||||
in
|
||||
{
|
||||
options = with lib; {
|
||||
sane.netns = mkOption {
|
||||
type = types.attrsOf netnsOpts;
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
|
||||
config = let
|
||||
configs = lib.mapAttrsToList mkNetNsConfig cfg;
|
||||
take = f: {
|
||||
networking.localCommands = f.networking.localCommands;
|
||||
networking.iproute2.rttablesExtraConfig = f.networking.iproute2.rttablesExtraConfig;
|
||||
networking.iproute2.enable = f.networking.iproute2.enable;
|
||||
systemd.services.network-local-commands = f.systemd.services.network-local-commands;
|
||||
};
|
||||
in take (sane-lib.mkTypedMerge take configs);
|
||||
}
|
@@ -231,7 +231,7 @@ let
|
||||
# only do this for the services which are *defined* by this program though (i.e. `scvCfg ? description`)
|
||||
# so as to avoid idioms like when sway adds `graphical-session.partOf = default`
|
||||
depends = svcCfg.depends
|
||||
++ lib.optionals (svcName != "dbus" && builtins.elem "user" config.sandbox.whitelistDbus) [
|
||||
++ lib.optionals (svcName != "dbus" && builtins.elem "user" config.sandbox.whitelistDbus && cfg.dbus.enabled) [
|
||||
"dbus"
|
||||
] ++ lib.optionals ((!builtins.elem "wayland" svcCfg.partOf) && config.sandbox.whitelistWayland) [
|
||||
"wayland"
|
||||
|
@@ -209,6 +209,7 @@ let
|
||||
# hence do that early:
|
||||
# TODO: consider moving XDG_RUNTIME_DIR to $HOME/.run
|
||||
fs.".config/environment.d/10-sane-baseline.conf".symlink.text = ''
|
||||
HOME=/home/${name}
|
||||
XDG_RUNTIME_DIR=/run/user/${name}
|
||||
'';
|
||||
fs.".config/environment.d/20-sane-nixos-users.conf".symlink.text =
|
||||
|
@@ -130,6 +130,53 @@ in with final; {
|
||||
# ];
|
||||
});
|
||||
|
||||
# bamf: required via pantheon.switchboard -> wingpanel -> gala
|
||||
# bamf = prev.bamf.overrideAttrs (upstream: {
|
||||
# # "You must have gtk-doc >= 1.0 installed to build documentation"
|
||||
# depsBuildBuild = (upstream.depsBuildBuild or []) ++ [
|
||||
# pkg-config #< to find gtk-doc
|
||||
# (buildPackages.python3.withPackages (ps: with ps; [ lxml ])) # Tests
|
||||
# ];
|
||||
# # nativeBuildInputs = [
|
||||
# # # (python3.withPackages (ps: with ps; [ lxml ])) # Tests
|
||||
# # autoreconfHook
|
||||
# # dbus
|
||||
# # docbook_xsl
|
||||
# # gnome.gnome-common
|
||||
# # gobject-introspection
|
||||
# # gtk-doc
|
||||
# # pkg-config
|
||||
# # vala
|
||||
# # which
|
||||
# # wrapGAppsHook3
|
||||
# # xorg.xorgserver
|
||||
# # ] ++ [
|
||||
# # nativeBuildInputs = lib.tail upstream.nativeBuildInputs ++ [
|
||||
# nativeBuildInputs = (
|
||||
# lib.filter (p:
|
||||
# !lib.hasPrefix python3.pname (p.name or p.pname or "") &&
|
||||
# # ... i can't figure out where it's getting libX11 from :|
|
||||
# (p.pname or "") != xorg.xorgserver.pname &&
|
||||
# (p.pname or "") != gnome.gnome-common.pname
|
||||
# )
|
||||
# upstream.nativeBuildInputs
|
||||
# ) ++ [
|
||||
# buildPackages.gettext #< for msgfmt
|
||||
# ];
|
||||
|
||||
# buildInputs = upstream.buildInputs ++ [
|
||||
# xorg.xorgserver #< upstream incorrectly places this in `nativeBuildInputs`
|
||||
# ];
|
||||
|
||||
# # nativeBuildInputs = upstream.nativeBuildInputs ++ [
|
||||
# # (python3.pythonOnBuildForHost.withPackages (ps: with ps; [ lxml ])) # Tests
|
||||
# # ];
|
||||
# configureFlags = [
|
||||
# "--enable-gtk-doc"
|
||||
# # "--enable-headless-tests" #< can't test when cross compiling
|
||||
# ];
|
||||
# });
|
||||
|
||||
# binutils = prev.binutils.override {
|
||||
# # fix that resulting binary files would specify build #!sh as their interpreter.
|
||||
# # dtrx is the primary beneficiary of this.
|
||||
@@ -463,6 +510,12 @@ in with final; {
|
||||
--replace-fail "disabled_plugins = []" "disabled_plugins = ['power']"
|
||||
'';
|
||||
});
|
||||
# gnome-settings-daemon43 = super.gnome-settings-daemon43.overrideAttrs (orig: {
|
||||
# postPatch = orig.postPatch + ''
|
||||
# substituteInPlace plugins/meson.build \
|
||||
# --replace-fail "disabled_plugins = []" "disabled_plugins = ['power']"
|
||||
# '';
|
||||
# });
|
||||
|
||||
# 2023/08/01: upstreaming is blocked on argyllcms, gnome-keyring, gnome-clocks, ibus, libavif, webp-pixbuf-loader (gnome-shell)
|
||||
# fixes: "gdbus-codegen not found or executable"
|
||||
@@ -698,12 +751,6 @@ in with final; {
|
||||
# ];
|
||||
# });
|
||||
|
||||
# upstreaming: <https://github.com/NixOS/nixpkgs/pull/317477>
|
||||
libvpx = prev.libvpx.overrideAttrs (upstream: {
|
||||
# fails building neon extensions for armv7l; see <https://github.com/NixOS/nixpkgs/issues/208746>
|
||||
configureFlags = builtins.map (lib.replaceStrings [ "armv7l-linux-gcc" ] [ "armv7-linux-gcc" ]) upstream.configureFlags;
|
||||
});
|
||||
|
||||
# 2024/05/31: upstreaming blocked on qtsvg, libgweather, appstream, glycin-loaders
|
||||
loupe = prev.loupe.overrideAttrs (upstream: {
|
||||
postPatch = (upstream.postPatch or "") + ''
|
||||
@@ -863,6 +910,30 @@ in with final; {
|
||||
# # buildInputs = lib.remove gnupg upstream.buildInputs;
|
||||
# });
|
||||
|
||||
pantheon = prev.pantheon.overrideScope (self: super: {
|
||||
# 2024/06/13: upstreaming is blocked by qtsvg/ffado
|
||||
switchboard-plug-network = super.switchboard-plug-network.overrideAttrs (upstream: {
|
||||
nativeBuildInputs = upstream.nativeBuildInputs ++ [
|
||||
buildPackages.gettext # <for msgfmt
|
||||
];
|
||||
});
|
||||
# 2024/06/13: upstreaming is unblocked; implemented on `pr-cross-switchboard-plugs-sound` branch
|
||||
switchboard-plug-sound = super.switchboard-plug-sound.overrideAttrs (upstream: {
|
||||
# depsBuildBuild = (upstream.depsBuildBuild or []) ++ [
|
||||
# pkg-config #< so that it can find the right gettext/msgfmt
|
||||
# ];
|
||||
# everything requires an extra `buildPackages` than if i patched this inside nixpkgs itself: not sure why!
|
||||
nativeBuildInputs = upstream.nativeBuildInputs ++ [
|
||||
buildPackages.gettext #< for msgfmt
|
||||
# gettext #< for msgfmt
|
||||
buildPackages.glib
|
||||
];
|
||||
env.PKG_CONFIG_GIO_2_0_GLIB_COMPILE_RESOURCES = "${lib.getDev buildPackages.buildPackages.glib}/bin/glib-compile-resources";
|
||||
|
||||
strictDeps = true;
|
||||
});
|
||||
});
|
||||
|
||||
# fixes (meson) "Program 'glib-mkenums mkenums' not found or not executable"
|
||||
# 2024/05/31: upstreaming is blocked on appstream, libgweather, qtsvg
|
||||
# phoc = mvToNativeInputs [ wayland-scanner glib ] prev.phoc;
|
||||
@@ -1142,17 +1213,6 @@ in with final; {
|
||||
# });
|
||||
# };
|
||||
|
||||
# 2024/05/31: upstreaming is unblocked
|
||||
# - problem is fixed in a newer version of the package anyway, just needs updating (repo migration)
|
||||
# fixes: "Run-time dependency scdoc found: NO (tried pkgconfig)"
|
||||
unl0kr = prev.unl0kr.overrideAttrs (upstream: {
|
||||
postPatch = (upstream.postPatch or "") + ''
|
||||
substituteInPlace meson.build \
|
||||
--replace-fail "scdoc = dependency('scdoc')" "" \
|
||||
--replace-fail "scdoc.get_pkgconfig_variable('scdoc')" "'scdoc'"
|
||||
'';
|
||||
});
|
||||
|
||||
# 2024/05/31: upstreaming is blocked on hdf5, thrift, others
|
||||
# visidata = prev.visidata.override {
|
||||
# # hdf5 / h5py don't cross-compile, but i don't use that file format anyway.
|
||||
|
@@ -3,19 +3,41 @@
|
||||
, python3
|
||||
, sane-data
|
||||
, static-nix-shell
|
||||
, symlinkJoin
|
||||
, writeShellScript
|
||||
}:
|
||||
|
||||
lib.makeScope newScope (self: with self; {
|
||||
mkFeed = callPackage ./template.nix {};
|
||||
feed-pkgs = lib.recurseIntoAttrs (lib.mapAttrs
|
||||
(name: feed-details: mkFeed {
|
||||
feedName = name;
|
||||
jsonPath = "modules/data/feeds/sources/${name}/default.json";
|
||||
inherit (feed-details) url;
|
||||
})
|
||||
sane-data.feeds
|
||||
);
|
||||
feed-pkgs = let
|
||||
byName = lib.mapAttrs
|
||||
(name: feed-details: mkFeed {
|
||||
feedName = name;
|
||||
jsonPath = "modules/data/feeds/sources/${name}/default.json";
|
||||
inherit (feed-details) url;
|
||||
})
|
||||
sane-data.feeds
|
||||
;
|
||||
in
|
||||
symlinkJoin {
|
||||
# this meta package exists primarily to link all the feed updaters
|
||||
# into a single package which can *actually* be updated.
|
||||
# it's not critical whether the actual package itself builds.
|
||||
name = "feed-pkgs";
|
||||
pname = "feed-pkgs";
|
||||
version = "20230112";
|
||||
paths = builtins.attrValues byName;
|
||||
passthru = byName // {
|
||||
updateScript = let
|
||||
update-all-feeds = writeShellScript "update-all-feeds" (
|
||||
lib.concatStringsSep "\n" (
|
||||
builtins.map (p: lib.concatStringsSep " " p.updateScript) (lib.attrValues byName)
|
||||
)
|
||||
);
|
||||
in
|
||||
[ update-all-feeds ];
|
||||
};
|
||||
};
|
||||
update-feed = static-nix-shell.mkPython3Bin {
|
||||
pname = "update";
|
||||
srcRoot = ./.;
|
||||
|
@@ -13,10 +13,9 @@ stdenv.mkDerivation {
|
||||
src = fetchurl {
|
||||
inherit url;
|
||||
};
|
||||
passthru.updateScript = {
|
||||
name = "feed-update-script";
|
||||
command = [ "${update-feed}/bin/update.py" url jsonPath ];
|
||||
};
|
||||
passthru.updateScript = [
|
||||
"${update-feed}/bin/update.py" url jsonPath
|
||||
];
|
||||
meta = {
|
||||
description = "metadata about any feeds available at ${feedName}";
|
||||
homepage = feedName;
|
||||
|
@@ -145,8 +145,8 @@ in (lib.makeScope newScope (self: with self; {
|
||||
extid = "webextension@metamask.io";
|
||||
pname = "ether-metamask";
|
||||
url = "https://github.com/MetaMask/metamask-extension/releases/download/v${version}/metamask-firefox-${version}.zip";
|
||||
version = "11.16.8";
|
||||
hash = "sha256-32KkO72afC9Cm0siiobkCZKmfZqm8/Z6SJK8KwNdeTw=";
|
||||
version = "11.16.9";
|
||||
hash = "sha256-IYRCR0jX2agMHj/Pnnc+q6X92yrhdIJF+uRtw7C2T2k=";
|
||||
};
|
||||
fx_cast = fetchVersionedAddon rec {
|
||||
extid = "fx_cast@matt.tf";
|
||||
|
@@ -2,7 +2,9 @@
|
||||
, fetchFromGitLab
|
||||
#v nixpkgs calls `.override` on the kernel to configure additional things
|
||||
, features ? {}
|
||||
, kernelPatches ? []
|
||||
, randstructSeed ? ""
|
||||
, structuredExtraConfig ? {}
|
||||
, ...
|
||||
}:
|
||||
buildLinux {
|
||||
@@ -21,5 +23,5 @@ buildLinux {
|
||||
autoModules = false;
|
||||
# preferBuiltin = false;
|
||||
|
||||
inherit features randstructSeed;
|
||||
inherit features kernelPatches randstructSeed structuredExtraConfig;
|
||||
}
|
||||
|
@@ -63,6 +63,9 @@ let
|
||||
CONFIG_DMIID=y
|
||||
CONFIG_MODULE_COMPRESS_ZSTD=y
|
||||
|
||||
CONFIG_DRM_LIMA=y
|
||||
CONFIG_DRM_MALI_DISPLAY=m
|
||||
|
||||
#
|
||||
# Extra sane-specific options
|
||||
#
|
||||
|
@@ -12,7 +12,7 @@ let
|
||||
hash = "sha256-MiVokKlpcJmfoGuWAMeW1En7gZ5hk0rCQArYm6P9XCc=";
|
||||
};
|
||||
overlay = import "${src}/overlay/overlay.nix";
|
||||
final = pkgs.appendOverlays [ overlay ];
|
||||
final = pkgs.extend overlay;
|
||||
in src.overrideAttrs (base: {
|
||||
# passthru only mobile-nixos' own packages -- not the whole nixpkgs-with-mobile-nixos-as-overlay:
|
||||
passthru = base.passthru // (overlay final pkgs);
|
||||
|
@@ -7,8 +7,8 @@ let
|
||||
src = fetchFromGitHub {
|
||||
owner = "nix-community";
|
||||
repo = "nixpkgs-wayland";
|
||||
rev = "021a0a37c336730956f5ce741c2a5c0e5c113b40";
|
||||
hash = "sha256-NiBJ7EgvGmDmXy1MG1r++afIzFJBmir2PQ4wmMNIaWw=";
|
||||
rev = "422bb5c5106008418f499ca591c0138f73e213f4";
|
||||
hash = "sha256-32ukRcPI2W5exf4A7/ISqoKp+sL1MxdMjFt3I+8XS5Y=";
|
||||
};
|
||||
flake = import "${src}/flake.nix";
|
||||
evaluated = flake.outputs {
|
||||
@@ -21,11 +21,11 @@ let
|
||||
};
|
||||
overlay = evaluated.overlay;
|
||||
|
||||
final = pkgs.appendOverlays [ overlay ];
|
||||
final = pkgs.extend overlay;
|
||||
in src.overrideAttrs (base: {
|
||||
# attributes required by update scripts
|
||||
pname = "nixpkgs-wayland";
|
||||
version = "0-unstable-2024-06-08";
|
||||
version = "0-unstable-2024-06-14";
|
||||
src = src;
|
||||
|
||||
# passthru only nixpkgs-wayland's own packages -- not the whole nixpkgs-with-nixpkgs-wayland-as-overlay:
|
||||
|
@@ -27,19 +27,25 @@
|
||||
}:
|
||||
let
|
||||
lock = {
|
||||
master.rev = "33605cdf028a6bfb96ce5d6e6e87d4779555f35f";
|
||||
master.sha256 = "sha256-Lp669vFtN0vaCyOmXiA1UWrBXyyTlxYu2cZhaD10gn4=";
|
||||
staging.rev = "33605cdf028a6bfb96ce5d6e6e87d4779555f35f";
|
||||
staging.sha256 = "sha256-Lp669vFtN0vaCyOmXiA1UWrBXyyTlxYu2cZhaD10gn4=";
|
||||
staging-next.rev = "33605cdf028a6bfb96ce5d6e6e87d4779555f35f";
|
||||
staging-next.sha256 = "sha256-Lp669vFtN0vaCyOmXiA1UWrBXyyTlxYu2cZhaD10gn4=";
|
||||
master.rev = "bac3e728035fee7d7fd3df57e7bb89298d1b1b2e";
|
||||
master.sha256 = "sha256-tW1Tzz/2SX8HiAXkQm6IbsRbzQuPH9W/ouoTt+bUGdk=";
|
||||
staging.rev = "bac3e728035fee7d7fd3df57e7bb89298d1b1b2e";
|
||||
staging.sha256 = "sha256-tW1Tzz/2SX8HiAXkQm6IbsRbzQuPH9W/ouoTt+bUGdk=";
|
||||
staging-next.rev = "bac3e728035fee7d7fd3df57e7bb89298d1b1b2e";
|
||||
staging-next.sha256 = "sha256-tW1Tzz/2SX8HiAXkQm6IbsRbzQuPH9W/ouoTt+bUGdk=";
|
||||
};
|
||||
lock' = lock."${variant}";
|
||||
unpatchedSrc = fetchzip {
|
||||
url = "https://github.com/NixOS/nixpkgs/archive/${lock'.rev}.tar.gz";
|
||||
inherit (lock') sha256;
|
||||
};
|
||||
unpatchedNixpkgs = import unpatchedSrc { inherit localSystem; };
|
||||
commonNixpkgsArgs = {
|
||||
inherit localSystem;
|
||||
# reset impurities
|
||||
config = {};
|
||||
overlays = [];
|
||||
};
|
||||
unpatchedNixpkgs = import unpatchedSrc commonNixpkgsArgs;
|
||||
|
||||
patchedSrc = unpatchedNixpkgs.applyPatches {
|
||||
name = "nixpkgs-patched-uninsane";
|
||||
@@ -56,8 +62,7 @@ let
|
||||
};
|
||||
|
||||
src = if doPatch then patchedSrc else { outPath = unpatchedSrc; };
|
||||
args = {
|
||||
inherit localSystem;
|
||||
args = commonNixpkgsArgs // {
|
||||
config = {
|
||||
allowUnfree = true; # NIXPKGS_ALLOW_UNFREE=1
|
||||
allowBroken = true; # NIXPKGS_ALLOW_BROKEN=1
|
||||
@@ -76,7 +81,7 @@ in
|
||||
src.overrideAttrs (base: {
|
||||
# attributes needed for update scripts
|
||||
pname = "nixpkgs";
|
||||
version = "24.05-unstable-2024-06-08";
|
||||
version = "24.05-unstable-2024-06-15";
|
||||
passthru = (base.passthru or {}) // nixpkgs // {
|
||||
src = unpatchedSrc // {
|
||||
inherit (lock') rev;
|
||||
|
@@ -24,17 +24,22 @@ let
|
||||
);
|
||||
in
|
||||
[
|
||||
# TODO: apply this once it's fixed for aarch64
|
||||
# (fetchpatch' {
|
||||
# title = "libvpx: fix cross compiling for armv7";
|
||||
# prUrl = "https://github.com/NixOS/nixpkgs/pull/317477";
|
||||
# hash = "sha256-5W/5/u2CXJJEgTjPx/do6SRZ6WEfhlAi/qXYS/Lsb14=";
|
||||
# title = "pantheon.switchboard-plug-sound: support cross compilation";
|
||||
# saneCommit = "86f85de8d008710a11b7b3653ec594438374059e";
|
||||
# hash = "sha256-fGuS46f9qSMRHvWZvTmcirKufIqlXHwwhckeK1RNejE=";
|
||||
# })
|
||||
|
||||
(fetchpatch' {
|
||||
title = "unl0kr: 2.0.0 -> 3.2.0";
|
||||
prUrl = "https://github.com/NixOS/nixpkgs/pull/319126";
|
||||
hash = "sha256-IfGayn+othMzp5Mc+0klBvUmykFwq95OKIJDvWL96d0=";
|
||||
})
|
||||
|
||||
(fetchpatch' {
|
||||
title = "sysvol: init at 0-unstable-2024-06-07";
|
||||
prUrl = "https://github.com/NixOS/nixpkgs/pull/318440";
|
||||
hash = "sha256-zVuZHGIFpXrXnpYM1v0IJ6zw5gwTgkTxq08QfBVSLpI=";
|
||||
hash = "sha256-OX1OP2m9LJYjVcryhpt520XJmdK1XS0KKaEBzMjdpNo=";
|
||||
})
|
||||
|
||||
(fetchpatch' {
|
||||
@@ -47,8 +52,8 @@ in
|
||||
|
||||
(fetchpatch' {
|
||||
title = "trust-dns: rebrand as hickory-dns";
|
||||
saneCommit = "a7613d50c58b5612a7b806ce1375d8bf0485ab55";
|
||||
hash = "sha256-N4DfNhCeg9etVeTPVzJ73CwiZzf43SozK8nrfXIm0uQ=";
|
||||
prUrl = "https://github.com/NixOS/nixpkgs/pull/316466";
|
||||
hash = "sha256-LJr+z7pgEXnPGqgsWLgMGmCJii1rh6nfIeEMHat4Xg4=";
|
||||
})
|
||||
|
||||
(fetchpatch' {
|
||||
|
34
pkgs/additional/sane-nix-files/default.nix
Normal file
34
pkgs/additional/sane-nix-files/default.nix
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
findutils,
|
||||
runCommandLocal,
|
||||
rsync,
|
||||
}:
|
||||
runCommandLocal "sane-nix-files" {
|
||||
nativeBuildInputs = [
|
||||
findutils
|
||||
rsync
|
||||
];
|
||||
|
||||
meta = {
|
||||
description = "top-level host configs for Colin's machines";
|
||||
longDescription = ''
|
||||
i like to ensure a copy of my config is present on all my machines,
|
||||
and this does that in a hermetic way.
|
||||
'';
|
||||
};
|
||||
} ''
|
||||
mkdir src
|
||||
pushd src
|
||||
|
||||
rsync -lptr ${../../../.}/ ./
|
||||
chmod u+w .
|
||||
for pat in $(cat .gitignore); do
|
||||
set +e
|
||||
chmod u+w -R "$pat" ; rm -rf "$pat"
|
||||
find $PWD -name "$pat" -exec 'chmod u+w -R {}; rm -rf {}' \;
|
||||
set -e
|
||||
done
|
||||
rsync -lptr ./ $out/
|
||||
|
||||
popd
|
||||
''
|
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p glib -p jq -p procps -p sway -p util-linux -p xdg-utils
|
||||
#!nix-shell -i bash -p bash -p glib -p jq -p procps -p sway -p util-linux -p xdg-utils
|
||||
|
||||
set -e
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p libnotify -p swappy -p sway-contrib.grimshot -p util-linux -p wl-clipboard
|
||||
#!nix-shell -i bash -p bash -p libnotify -p swappy -p sway-contrib.grimshot -p util-linux -p wl-clipboard
|
||||
|
||||
# loosely inspired by reddit user u/dragobich
|
||||
# - <https://www.reddit.com/r/hyprland/comments/12tal0f/comment/jh8j4sy/>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p duplicity
|
||||
#!nix-shell -i bash -p bash -p duplicity
|
||||
|
||||
# N.B. must be run as root
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p duplicity
|
||||
#!nix-shell -i bash -p bash -p duplicity
|
||||
|
||||
# N.B. must be run as root
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p nix
|
||||
#!nix-shell -i bash -p bash -p nix
|
||||
|
||||
# use like `eval $(sane-clone tuba)` to clone and cd into a tuba checkout
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p coreutils-full -p gnused
|
||||
#!nix-shell -i bash -p bash -p coreutils-full -p gnused
|
||||
|
||||
# processes a tab-separated "deadlines" file and alerts for any upcoming events.
|
||||
#
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p inotify-tools -p ncurses
|
||||
#!nix-shell -i bash -p bash -p inotify-tools -p ncurses
|
||||
# watches PWD for any changes underneath it and re-runs `cargo build --a>
|
||||
# optionally, provide your own build command as the first argument
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p findutils
|
||||
#!nix-shell -i bash -p bash -p findutils
|
||||
# find where a package stores its dotfiles/dotdir
|
||||
# e.g. `sane-find-dotfiles foo` might print `/home/colin/.foo`, `/home/colin/.local/share/foo`, etc.
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user