Compare commits

..

2 Commits

130 changed files with 1262 additions and 1968 deletions

View File

@@ -2,8 +2,6 @@
# .❄≡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:
@@ -31,7 +29,11 @@ you might specifically be interested in these files (elaborated further in #key-
## Using This Repo In Your Own Config
follow the instructions [here][NUR] to access my packages through the Nix User Repositories.
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.
[NUR]: https://nur.nix-community.org/
@@ -39,15 +41,19 @@ follow the instructions [here][NUR] to access my packages through the Nix User R
- `doc/`
- instructions for tasks i find myself doing semi-occasionally in this repo.
- `hosts/`
- configs which aren't factored with external use in mind.
- the bulk of config which isn'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 for anything besides packages, it's most likely for something in this directory.
- 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.
- `overlays/`
- exposed via the `overlays` output in `flake.nix`.
- predominantly a list of `callPackage` directives.
- `pkgs/`
- derivations for things not yet packaged in nixpkgs.
@@ -55,12 +61,13 @@ follow the instructions [here][NUR] to access my packages through the Nix User R
- 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
View File

@@ -2,6 +2,7 @@
- `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?
@@ -24,8 +25,6 @@
- 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
@@ -79,21 +78,22 @@
- 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/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
- cleanup waybar so that it's not invoking playerctl every 2 seconds
- 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,7 +103,6 @@
- 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:

View File

@@ -3,65 +3,7 @@
#
# the primary purpose of this file is so i can run `updateScript`s which expect
# the root to be `default.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
{ pkgs ? import <nixpkgs> {} }:
pkgs.appendOverlays [
(import ./overlays/all.nix)
]
);
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 Normal file
View File

@@ -0,0 +1,7 @@
{
"nodes": {
"root": {}
},
"root": "root",
"version": 7
}

603
flake.nix Normal file
View File

@@ -0,0 +1,603 @@
# 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 = {
crappy = deployApp "crappy" "crappy" "switch";
crappy-light = deployApp "crappy-light" "crappy" "switch";
crappy-min = deployApp "crappy-min" "crappy" "switch";
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'
nix run '.#deploy.crappy'
'');
};
preDeploy = {
# build the host and copy the runtime closure to that host, but don't activate it.
crappy = deployApp "crappy" "crappy" null;
crappy-light = deployApp "crappy-light" "crappy" null;
crappy-min = deployApp "crappy-min" "crappy" null;
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.crappy-min' -- "$@"
nix run '.#preDeploy.moby-light' -- "$@"
nix run '.#preDeploy.lappy-light' -- "$@"
nix run '.#preDeploy.desko-light' -- "$@"
nix run '.#preDeploy.crappy-light' -- "$@"
nix run '.#preDeploy.lappy' -- "$@"
nix run '.#preDeploy.servo' -- "$@"
nix run '.#preDeploy.moby' -- "$@"
nix run '.#preDeploy.desko' -- "$@"
nix run '.#preDeploy.crappy' -- "$@"
'');
};
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 "crappy-min"}
${checkHost "desko-light"}
${checkHost "moby-light"}
${checkHost "lappy-light"}
${checkHost "crappy-light"}
${checkHost "desko"}
${checkHost "lappy"}
${checkHost "servo"}
${checkHost "moby"}
${checkHost "crappy"}
${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 "crappy-light-next"}
${checkHost "desko-next"}
${checkHost "lappy-next"}
${checkHost "servo-next"}
${checkHost "moby-next"}
${checkHost "crappy-next"}
${checkHost "rescue-next"}
echo "desko: $RC_desko"
echo "lappy: $RC_lappy"
echo "servo: $RC_servo"
echo "moby: $RC_moby"
echo "crappy: $RC_crappy"
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 "crappy-next: $RC_crappy_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_crappy | $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";
};
};
};
}

View File

@@ -12,7 +12,6 @@
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;
@@ -22,12 +21,6 @@
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!

View File

@@ -35,11 +35,6 @@
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

View File

@@ -3,19 +3,9 @@
let
portOpts = with lib; types.submodule {
options = {
visibleTo.ovpns = mkOption {
visibleTo.ovpn = 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.
'';
};
};
};
@@ -23,7 +13,7 @@ in
{
options = with lib; {
sane.ports.ports = mkOption {
# add the `visibleTo.{doof,ovpns}` options
# add the `visibleTo.ovpn` option
type = types.attrsOf portOpts;
};
};
@@ -50,16 +40,18 @@ 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"; #< TODO: enable IPv6
networking.wireguard.interfaces.wg-doof = {
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 {
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"
# "2602:fce8:106::51/128" #< TODO: enable IPv6
"205.201.63.12/32"
"2602:fce8:106::51/128"
];
peers = [
{
@@ -71,24 +63,45 @@ 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 = {
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 {
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" ];
ips = [
"185.157.162.178/32"
];
peers = [
{
publicKey = "SkkEZDCBde22KTs/Hc7FWvDBfdOCQA4YtBEuC3n5KGs=";
@@ -106,11 +119,99 @@ 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);
};
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
# 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
};
}

View File

@@ -55,7 +55,7 @@ in
# protocol = [ "tcp" "udp" ];
# # visibleTo.lan = true;
# # visibleTo.wan = true;
# visibleTo.ovpns = true; # forward traffic from the VPN to the root NS
# visibleTo.ovpn = 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.ovpns = true;
# visibleTo.ovpn = true;
# description = "colin-stun-turn-over-tls";
# };
# }
@@ -76,7 +76,7 @@ in
# protocol = [ "tcp" "udp" ];
# # visibleTo.lan = true;
# # visibleTo.wan = true;
# visibleTo.ovpns = true;
# visibleTo.ovpn = true;
# description = "colin-turn-${builtins.toString count}-of-${builtins.toString numPorts}";
# };
# })

View File

@@ -50,11 +50,7 @@
ENABLE_CAPTCHA = true;
NOREPLY_ADDRESS = "noreply.anonymous.git@uninsane.org";
};
session = {
COOKIE_SECURE = true;
# keep me logged in for 30 days
SESSION_LIFE_TIME = 60 * 60 * 24 * 30;
};
session.COOKIE_SECURE = true;
repository = {
DEFAULT_BRANCH = "master";
ENABLE_PUSH_CREATE_USER = true;

View File

@@ -18,15 +18,13 @@ in
protocol = [ "tcp" ];
visibleTo.lan = true;
visibleTo.wan = true;
visibleTo.ovpns = true; # so that letsencrypt can procure a cert for the mx record
visibleTo.doof = true;
visibleTo.ovpn = true; # so that letsencrypt can procure a cert for the mx record
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";
};

View File

@@ -22,7 +22,8 @@
sane.ports.ports."50300" = {
protocol = [ "tcp" ];
# visibleTo.ovpns = true; #< not needed: it runs in the ovpns namespace
# not visible to WAN: i run this in a separate netns
visibleTo.ovpn = true;
description = "colin-soulseek";
};

View File

@@ -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.ovpns = true; #< not needed: it runs in the ovpns namespace
visibleTo.ovpn = true;
description = "colin-bittorrent";
};
}

View File

@@ -5,15 +5,13 @@ 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.ovpns = true;
visibleTo.doof = true;
visibleTo.ovpn = true;
description = "colin-dns-hosting";
};
@@ -101,7 +99,6 @@ in
listenAddrsIpv4 = [
nativeAddrs."servo.lan"
bindOvpn
bindDoof
];
};
lan = {

View File

@@ -9,7 +9,7 @@
./ids.nix
./machine-id.nix
./net
./nix.nix
./nix
./persist.nix
./polyunfill.nix
./programs

View File

@@ -195,7 +195,6 @@ 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)

View File

@@ -59,18 +59,14 @@
# 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 `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"
# to avoid switching so much during development
"nixpkgs-overlays=/home/colin/dev/nixos/hosts/common/nix/overlay"
];
# 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 = pkgs.sane-nix-files;
source = ../../..;
};
environment.etc."nix/registry.json" = lib.mkIf (config.sane.maxBuildCost < 3) {
enable = false;

View File

@@ -0,0 +1,4 @@
# 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

View File

@@ -50,7 +50,6 @@ in
"fd"
"file"
"forkstat" # monitor every spawned/forked process
"free"
# "fwupd"
"gawk"
"gdb" # to debug segfaults
@@ -85,7 +84,6 @@ in
"parted"
"pciutils"
"powertop"
"ps"
"pstree"
"ripgrep"
"s6-rc" # service manager
@@ -99,7 +97,6 @@ in
"usbutils" # lsusb
"util-linux" # lsblk, lscpu, etc
"valgrind"
"watch"
"wget"
"wirelesstools" # iwlist
# "xq" # jq for XML
@@ -297,7 +294,6 @@ 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
@@ -359,7 +355,7 @@ in
"gnome.gnome-disk-utility"
"gnome.nautilus" # file browser
# "gnome.totem" # video player, supposedly supports UPnP
# "handbrake" #< TODO: fix build
"handbrake"
"inkscape"
# "jellyfin-media-player"
"kdenlive"
@@ -819,8 +815,6 @@ 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?
@@ -1123,8 +1117,6 @@ in
"tmp"
];
watch.sandbox.enable = false; #< it executes the command it's given
wdisplays.sandbox.method = "bwrap";
wdisplays.sandbox.whitelistWayland = true;

View File

@@ -1,24 +1,36 @@
{ 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 sane-sysinfo
"/sys/devices" # needed by battery_estimate
# "/sys/devices/cpu"
# "/sys/devices/system"
];
sandbox.whitelistWayland = true;
suggestedPrograms = [
"sane-sysinfo"
"sane-battery-estimate"
"sane-weather"
];
fs.".config/conky/conky.conf".symlink.target = pkgs.substituteAll {
src = ./conky.conf;
bat = "sane-sysinfo";
bat = "sane-battery-estimate";
weather = "timeout 20 sane-weather";
};

View File

@@ -0,0 +1,183 @@
#!/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: 208⧗
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

View File

@@ -45,7 +45,6 @@
./flare-signal.nix
./fontconfig.nix
./fractal.nix
./free.nix
./frozen-bubble.nix
./fwupd.nix
./g4music.nix
@@ -94,17 +93,14 @@
./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
@@ -114,7 +110,6 @@
./sane-open.nix
./sane-screenshot.nix
./sane-scripts.nix
./sane-sysinfo.nix
./sane-theme.nix
./sanebox.nix
./schlock.nix
@@ -135,7 +130,6 @@
./swayidle.nix
./swaylock.nix
./swaynotificationcenter
./switchboard.nix
./sysvol.nix
./tangram.nix
./tor-browser.nix

View File

@@ -1,9 +0,0 @@
{ pkgs, ... }:
{
sane.programs.free = {
packageUnwrapped = pkgs.linkIntoOwnPackage pkgs.procps "bin/free";
sandbox.method = "bwrap";
sandbox.isolatePids = false;
};
}

View File

@@ -1,159 +0,0 @@
# 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 = {};
}
]

View File

@@ -1,132 +0,0 @@
# 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";
};
};
}

View File

@@ -1,36 +0,0 @@
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"])

View File

@@ -1,215 +0,0 @@
/* 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;
}

View File

@@ -1,6 +0,0 @@
{ pkgs, ... }:
{
sane.programs.pactl = {
packageUnwrapped = pkgs.linkIntoOwnPackage pkgs.pulseaudio "bin/pactl";
};
}

View File

@@ -1,8 +0,0 @@
{ pkgs, ... }:
{
sane.programs.ps = {
packageUnwrapped = pkgs.linkIntoOwnPackage pkgs.procps "bin/ps";
sandbox.method = "bwrap";
sandbox.isolatePids = false;
};
}

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash -p sane-open
#!nix-shell -i bash -p sane-open
# use:
# rofi-run-command <handler>.desktop [cmd [args ...]]

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash -p gnused -p rofi -p wtype
#!nix-shell -i bash -p gnused -p rofi -p wtype
# "bookmarking"/snippets inspired by Luke Smith:
# - <https://www.youtube.com/watch?v=d_11QaTlf1I>

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!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
#!nix-shell -i 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

View File

@@ -1,10 +0,0 @@
{ ... }:
{
sane.programs.sane-sysinfo = {
sandbox.method = "bwrap";
sandbox.extraPaths = [
"/sys/class/power_supply"
"/sys/devices"
];
};
}

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash -p jq -p sway -p util-linux
#!nix-shell -i bash -p jq -p sway -p util-linux
help() {
echo "queries the focused window and apply an appropriate display-wide scale."

View File

@@ -148,7 +148,6 @@ 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
@@ -162,10 +161,9 @@ 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"
"waybar" # used by sway config
"wdisplays" # like xrandr
"wireplumber" # used by sway config
"wl-clipboard"

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash -p feedbackd -p procps -p swaynotificationcenter -p util-linux
#!nix-shell -i bash -p feedbackd -p procps -p swaynotificationcenter -p util-linux
# this script does some really unusual indirection with the `start` action:
# IT'S INTENTIONAL.

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash -p s6 -p s6-rc
#!nix-shell -i 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.

View File

@@ -1,28 +0,0 @@
{ 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)
};
};
}

View File

@@ -59,7 +59,7 @@
partOf = [ "graphical-session" ];
# options:
# -p {bottom,left,right,top} to attach to the corresponding screen edge
# -p {0,1,2,3} to attach to top/right/bottom/left 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 top -t 1 -T 0 -m 22 -H 39 -W 256 -i 32 -P";
command = "sysvol -p 0 -t 1 -T 0 -m 22 -H 39 -W 256 -i 32 -P";
};
};
}

View File

@@ -15,15 +15,6 @@ 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.
@@ -143,6 +134,8 @@ 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";

View File

@@ -24,6 +24,4 @@ alternate=breezy-dark
#[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

View File

@@ -110,7 +110,7 @@ in
};
services.waybar = {
description = "waybar status/topbar for sway";
description = "swaybar graphical header bar/tray for sway";
partOf = [ "graphical-session" ];
# env G_MESSAGES_DEBUG=all

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash -p jq -p playerctl
#!nix-shell -i bash -p jq -p playerctl
status=$(playerctl status 2> /dev/null | tr 'A-Z' 'a-z')
if [ -z "$status" ]; then
status="inactive"

View File

@@ -115,7 +115,6 @@ in
programs.zsh = lib.mkIf cfg.enabled {
enable = true;
shellAliases = {
":fg" = "fg";
":q" = "exit";
# common typos
"cd.." = "cd ..";
@@ -187,7 +186,7 @@ in
};
function switch() {
~/nixos/scripts/deploy "$@"
nix run '.#deploy.self'
}
'';

View File

@@ -7,12 +7,9 @@ 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")
@@ -27,19 +24,6 @@ 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 = ''

View File

@@ -22,7 +22,6 @@
"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

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash
#!nix-shell -i bash
file="$1"
enc="$2"
nibbles="$3"

View File

@@ -128,41 +128,36 @@ 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}";
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";
# # };
# # 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";
};
# 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
# ];
# });
system.build.u-boot = pkgs.buildUBoot {
defconfig = "snow_defconfig";

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash -p gnused
#!nix-shell -i 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

View File

@@ -56,16 +56,6 @@
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
};

View File

@@ -1,5 +0,0 @@
# 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)]

View File

@@ -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/",
"velocity": 0.12
"url": "https://www.bunniestudios.com/blog/?feed=rss2",
"velocity": 0.108
}

View File

@@ -1,9 +1,9 @@
{
"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.",
"description": "Radiolab",
"is_podcast": true,
"site_name": "",
"site_url": "",
"title": "Radiolab",
"url": "https://feeds.simplecast.com/EmVW7VGp",
"velocity": 0.138
"url": "https://feeds.feedburner.com/radiolab",
"velocity": 0.136
}

View File

@@ -1,9 +1,9 @@
{
"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",
"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",
"is_podcast": true,
"site_name": "",
"site_url": "",
"title": "The Ezra Klein Show",
"url": "https://feeds.simplecast.com/82FI35Px",
"velocity": 0.257
"velocity": 0.264
}

View File

@@ -2,8 +2,8 @@
"description": "Long conversations with clever Nixers.",
"is_podcast": true,
"site_name": "",
"site_url": "https://feeds.transistor.fm",
"site_url": "",
"title": "Full Time Nix",
"url": "https://feeds.transistor.fm/full-time-nix",
"velocity": 0.048
"velocity": 0
}

View File

@@ -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": "Omny Studio",
"site_url": "https://www.omnycontent.com",
"site_name": "",
"site_url": "",
"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

View File

@@ -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": "I live like them already",
"site_name": "Idiomdrottning",
"site_url": "https://idiomdrottning.org",
"title": "Idiomdrottning",
"url": "https://idiomdrottning.org/blog",
"velocity": 0.867
"velocity": 0.402
}

View File

@@ -1,9 +1,9 @@
{
"description": null,
"description": "Kill the Newsletter! Inbox:\n joh91bv7am2pnznv@kill-the-newsletter.com \u2192\n https://kill-the-newsletter.com/feeds/joh91bv7am2pnznv.xml",
"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": 0.667
"velocity": 939.13
}

View File

@@ -2,8 +2,8 @@
"description": "The art, science, and history of processor design..",
"is_podcast": true,
"site_name": "",
"site_url": "https://feeds.transistor.fm",
"site_url": "",
"title": "Microarch Club",
"url": "https://feeds.transistor.fm/microarch-club",
"velocity": 0.08
"velocity": 0.083
}

View File

@@ -1,9 +1,9 @@
{
"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>",
"description": "<p>As long as there&rsquo;s been oppression, there&rsquo;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&mdash;and fight to be&mdash;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>",
"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.299
"velocity": 0.271
}

View File

@@ -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": "Omny Studio",
"site_url": "https://www.omnycontent.com",
"site_name": "",
"site_url": "",
"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.125
"velocity": 0.063
}

View File

@@ -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": "Omny Studio",
"site_url": "https://www.omnycontent.com",
"site_name": "",
"site_url": "",
"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.192
"velocity": 0.188
}

View File

@@ -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": "test220119a",
"site_url": "https://feeds.libsyn.com",
"site_name": "",
"site_url": "",
"title": "Origin Stories",
"url": "https://feeds.libsyn.com/65014/rss",
"velocity": 0.024

View File

@@ -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>\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>",
"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>",
"is_podcast": true,
"site_name": "The Linux Experiment Podcasts",
"site_url": "https://podcast.thelinuxexp.com",
"title": "Linux & Open Source News",
"title": "Linux + Open Source News, by TLE",
"url": "https://podcast.thelinuxexp.com/@tlenewspodcast/feed.xml",
"velocity": 0.147
"velocity": 0.145
}

View File

@@ -1,9 +1,9 @@
{
"description": "A Comic",
"is_podcast": false,
"site_name": "Poorly Drawn Lines | A Comic",
"site_name": "Poorly Drawn Lines",
"site_url": "https://poorlydrawnlines.com",
"title": "Poorly Drawn Lines",
"url": "https://poorlydrawnlines.com/feed/",
"velocity": 0.3
"velocity": 0.237
}

View File

@@ -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 Blogs",
"site_name": "Richard Carrier",
"site_url": "https://www.richardcarrier.info",
"title": "Richard Carrier Blogs",
"title": "Richard Carrier",
"url": "https://www.richardcarrier.info/feed",
"velocity": 0.131
"velocity": 0.141
}

View File

@@ -1,9 +1,9 @@
{
"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.&nbsp;</p>",
"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.",
"is_podcast": true,
"site_name": "",
"site_url": "",
"title": "Seattle Nice",
"url": "https://feeds.buzzsprout.com/1897925.rss",
"velocity": 0.101
"velocity": 0.099
}

View File

@@ -1,9 +1,9 @@
{
"description": "On Target Technology News",
"is_podcast": false,
"site_name": "SemiAccurate",
"site_name": "SemiAccurate - On Target Technology News",
"site_url": "https://semiaccurate.com",
"title": "SemiAccurate",
"url": "https://www.semiaccurate.com/feed/",
"velocity": 0.098
"velocity": 0.106
}

View File

@@ -1,9 +1,9 @@
{
"description": "Latest Saturday Morning Breakfast Cereal comics and news",
"is_podcast": false,
"site_name": "Saturday Morning Breakfast Cereal - Dave",
"site_name": "Saturday Morning Breakfast Cereal - Got You",
"site_url": "https://www.smbc-comics.com",
"title": "Saturday Morning Breakfast Cereal",
"url": "https://www.smbc-comics.com/comic/rss",
"velocity": 0.999
"velocity": 1.172
}

View File

@@ -1,9 +1,9 @@
{
"description": "<p>Tales From the Bridge is a podcast that discusses all things science fiction. Join Tristan, Kevin, James, Sam&nbsp; 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.&nbsp;<br /><br />Subscribe, follow, like and leave a review. We'd love to hear from you!&nbsp;</p>",
"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.&nbsp;<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>",
"is_podcast": true,
"site_name": "",
"site_url": "",
"title": "Tales From The Bridge",
"title": "Tales From The Bridge: All Things Sci-Fi",
"url": "https://feeds.buzzsprout.com/1795352.rss",
"velocity": 0.091
"velocity": 0.093
}

View File

@@ -1,9 +1,9 @@
{
"description": "{turnoff.us} is a webcomic that explores the worlds of programming, operating systems, and tech professional life.",
"description": "turnoff.us is a geek comic site. Comics about Programming Languages, Web, Cloud, Linux, etc.",
"is_podcast": false,
"site_name": "turnoff.us",
"site_url": "http://turnoff.us",
"title": "turnoff.us",
"title": "turnoff.us - geek comic site",
"url": "https://turnoff.us/feed.xml",
"velocity": 0.377
"velocity": 0.01
}

View File

@@ -1,9 +1,9 @@
{
"description": "systems | complexity | second-order effects",
"is_podcast": false,
"site_name": "Unintended Consequences",
"site_name": "Unintended Consequences - systems | complexity | second-order effects",
"site_url": "https://unintendedconsequenc.es",
"title": "Unintended Consequences",
"url": "https://unintendedconsequenc.es/feed/",
"velocity": 0.009
"velocity": 0.01
}

View File

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

View File

@@ -8,7 +8,6 @@
./ids.nix
./programs
./image.nix
./netns.nix
./persist
./ports.nix
./root-on-tmpfs.nix

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash
#!nix-shell -i bash
set -e

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash
#!nix-shell -i bash
set -e

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash
#!nix-shell -i bash
set -e
fspath="$1"

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash
#!nix-shell -i bash
set -e

View File

@@ -1,120 +0,0 @@
{ 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);
}

View File

@@ -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 && cfg.dbus.enabled) [
++ lib.optionals (svcName != "dbus" && builtins.elem "user" config.sandbox.whitelistDbus) [
"dbus"
] ++ lib.optionals ((!builtins.elem "wayland" svcCfg.partOf) && config.sandbox.whitelistWayland) [
"wayland"

View File

@@ -209,7 +209,6 @@ 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 =

View File

@@ -130,53 +130,6 @@ 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.
@@ -510,12 +463,6 @@ 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"
@@ -751,6 +698,12 @@ 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 "") + ''
@@ -910,30 +863,6 @@ 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;
@@ -1213,6 +1142,17 @@ 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.

View File

@@ -3,41 +3,19 @@
, python3
, sane-data
, static-nix-shell
, symlinkJoin
, writeShellScript
}:
lib.makeScope newScope (self: with self; {
mkFeed = callPackage ./template.nix {};
feed-pkgs = let
byName = lib.mapAttrs
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
;
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 = ./.;

View File

@@ -13,9 +13,10 @@ stdenv.mkDerivation {
src = fetchurl {
inherit url;
};
passthru.updateScript = [
"${update-feed}/bin/update.py" url jsonPath
];
passthru.updateScript = {
name = "feed-update-script";
command = [ "${update-feed}/bin/update.py" url jsonPath ];
};
meta = {
description = "metadata about any feeds available at ${feedName}";
homepage = feedName;

View File

@@ -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.9";
hash = "sha256-IYRCR0jX2agMHj/Pnnc+q6X92yrhdIJF+uRtw7C2T2k=";
version = "11.16.8";
hash = "sha256-32KkO72afC9Cm0siiobkCZKmfZqm8/Z6SJK8KwNdeTw=";
};
fx_cast = fetchVersionedAddon rec {
extid = "fx_cast@matt.tf";

View File

@@ -2,9 +2,7 @@
, fetchFromGitLab
#v nixpkgs calls `.override` on the kernel to configure additional things
, features ? {}
, kernelPatches ? []
, randstructSeed ? ""
, structuredExtraConfig ? {}
, ...
}:
buildLinux {
@@ -23,5 +21,5 @@ buildLinux {
autoModules = false;
# preferBuiltin = false;
inherit features kernelPatches randstructSeed structuredExtraConfig;
inherit features randstructSeed;
}

View File

@@ -12,7 +12,7 @@ let
hash = "sha256-MiVokKlpcJmfoGuWAMeW1En7gZ5hk0rCQArYm6P9XCc=";
};
overlay = import "${src}/overlay/overlay.nix";
final = pkgs.extend overlay;
final = pkgs.appendOverlays [ 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);

View File

@@ -7,8 +7,8 @@ let
src = fetchFromGitHub {
owner = "nix-community";
repo = "nixpkgs-wayland";
rev = "422bb5c5106008418f499ca591c0138f73e213f4";
hash = "sha256-32ukRcPI2W5exf4A7/ISqoKp+sL1MxdMjFt3I+8XS5Y=";
rev = "021a0a37c336730956f5ce741c2a5c0e5c113b40";
hash = "sha256-NiBJ7EgvGmDmXy1MG1r++afIzFJBmir2PQ4wmMNIaWw=";
};
flake = import "${src}/flake.nix";
evaluated = flake.outputs {
@@ -21,11 +21,11 @@ let
};
overlay = evaluated.overlay;
final = pkgs.extend overlay;
final = pkgs.appendOverlays [ overlay ];
in src.overrideAttrs (base: {
# attributes required by update scripts
pname = "nixpkgs-wayland";
version = "0-unstable-2024-06-14";
version = "0-unstable-2024-06-08";
src = src;
# passthru only nixpkgs-wayland's own packages -- not the whole nixpkgs-with-nixpkgs-wayland-as-overlay:

View File

@@ -27,25 +27,19 @@
}:
let
lock = {
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=";
master.rev = "33605cdf028a6bfb96ce5d6e6e87d4779555f35f";
master.sha256 = "sha256-Lp669vFtN0vaCyOmXiA1UWrBXyyTlxYu2cZhaD10gn4=";
staging.rev = "33605cdf028a6bfb96ce5d6e6e87d4779555f35f";
staging.sha256 = "sha256-Lp669vFtN0vaCyOmXiA1UWrBXyyTlxYu2cZhaD10gn4=";
staging-next.rev = "33605cdf028a6bfb96ce5d6e6e87d4779555f35f";
staging-next.sha256 = "sha256-Lp669vFtN0vaCyOmXiA1UWrBXyyTlxYu2cZhaD10gn4=";
};
lock' = lock."${variant}";
unpatchedSrc = fetchzip {
url = "https://github.com/NixOS/nixpkgs/archive/${lock'.rev}.tar.gz";
inherit (lock') sha256;
};
commonNixpkgsArgs = {
inherit localSystem;
# reset impurities
config = {};
overlays = [];
};
unpatchedNixpkgs = import unpatchedSrc commonNixpkgsArgs;
unpatchedNixpkgs = import unpatchedSrc { inherit localSystem; };
patchedSrc = unpatchedNixpkgs.applyPatches {
name = "nixpkgs-patched-uninsane";
@@ -62,7 +56,8 @@ let
};
src = if doPatch then patchedSrc else { outPath = unpatchedSrc; };
args = commonNixpkgsArgs // {
args = {
inherit localSystem;
config = {
allowUnfree = true; # NIXPKGS_ALLOW_UNFREE=1
allowBroken = true; # NIXPKGS_ALLOW_BROKEN=1
@@ -81,7 +76,7 @@ in
src.overrideAttrs (base: {
# attributes needed for update scripts
pname = "nixpkgs";
version = "24.05-unstable-2024-06-15";
version = "24.05-unstable-2024-06-08";
passthru = (base.passthru or {}) // nixpkgs // {
src = unpatchedSrc // {
inherit (lock') rev;

View File

@@ -24,22 +24,17 @@ let
);
in
[
# TODO: apply this once it's fixed for aarch64
# (fetchpatch' {
# title = "pantheon.switchboard-plug-sound: support cross compilation";
# saneCommit = "86f85de8d008710a11b7b3653ec594438374059e";
# hash = "sha256-fGuS46f9qSMRHvWZvTmcirKufIqlXHwwhckeK1RNejE=";
# title = "libvpx: fix cross compiling for armv7";
# prUrl = "https://github.com/NixOS/nixpkgs/pull/317477";
# hash = "sha256-5W/5/u2CXJJEgTjPx/do6SRZ6WEfhlAi/qXYS/Lsb14=";
# })
(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-OX1OP2m9LJYjVcryhpt520XJmdK1XS0KKaEBzMjdpNo=";
hash = "sha256-zVuZHGIFpXrXnpYM1v0IJ6zw5gwTgkTxq08QfBVSLpI=";
})
(fetchpatch' {
@@ -52,8 +47,8 @@ in
(fetchpatch' {
title = "trust-dns: rebrand as hickory-dns";
prUrl = "https://github.com/NixOS/nixpkgs/pull/316466";
hash = "sha256-LJr+z7pgEXnPGqgsWLgMGmCJii1rh6nfIeEMHat4Xg4=";
saneCommit = "a7613d50c58b5612a7b806ce1375d8bf0485ab55";
hash = "sha256-N4DfNhCeg9etVeTPVzJ73CwiZzf43SozK8nrfXIm0uQ=";
})
(fetchpatch' {

View File

@@ -1,34 +0,0 @@
{
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
''

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash -p glib -p jq -p procps -p sway -p util-linux -p xdg-utils
#!nix-shell -i bash -p glib -p jq -p procps -p sway -p util-linux -p xdg-utils
set -e

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash -p libnotify -p swappy -p sway-contrib.grimshot -p util-linux -p wl-clipboard
#!nix-shell -i 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/>

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash -p duplicity
#!nix-shell -i bash -p duplicity
# N.B. must be run as root

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash -p duplicity
#!nix-shell -i bash -p duplicity
# N.B. must be run as root

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash -p nix
#!nix-shell -i bash -p nix
# use like `eval $(sane-clone tuba)` to clone and cd into a tuba checkout

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash -p coreutils-full -p gnused
#!nix-shell -i bash -p coreutils-full -p gnused
# processes a tab-separated "deadlines" file and alerts for any upcoming events.
#

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash -p inotify-tools -p ncurses
#!nix-shell -i 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

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash -p findutils
#!nix-shell -i 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.

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash -p gocryptfs -p rsync
#!nix-shell -i bash -p gocryptfs -p rsync
# HOW TO USE
# ```sh

Some files were not shown because too many files have changed in this diff Show More