Compare commits
112 Commits
wip-doofne
...
save-geocl
Author | SHA1 | Date | |
---|---|---|---|
bcd467e60e | |||
304c8f8e3e | |||
5a09a2665b | |||
209545fc41 | |||
1e12566207 | |||
9a53cbc833 | |||
439bb5263f | |||
845dba3ca5 | |||
5e7fe850ec | |||
832338488d | |||
86ee95f607 | |||
5f5e55c98b | |||
7d59782005 | |||
62b541012b | |||
514197a17f | |||
143bdf672b | |||
a6c48eda71 | |||
a603c3e6bc | |||
1f48f41927 | |||
c0d9f05575 | |||
7f46b034f9 | |||
ba66378bc0 | |||
dcc8168aa0 | |||
f7d3c26d12 | |||
3d871e8d7c | |||
78f4cd9be2 | |||
f83bac3c2b | |||
58de5d661f | |||
599832d59c | |||
625cb0992b | |||
a02f221628 | |||
ad8bcfc09e | |||
815ce6287f | |||
0d1d56870f | |||
2445b882c2 | |||
12465e111e | |||
65a0914828 | |||
dab60e79c1 | |||
fe57f186cd | |||
78d66a8b09 | |||
b2955c9c9d | |||
b0e184b0f0 | |||
3cd97b522c | |||
c91681c77c | |||
d0d623da15 | |||
0db86d8c86 | |||
b74dfe7578 | |||
d1843b6b3d | |||
b482a1dfd6 | |||
5ba74a4055 | |||
b3b77e3e62 | |||
63bc58a56f | |||
efcf8639dc | |||
90b86dc7fc | |||
8bf8d31c5f | |||
2e44abc55d | |||
9e92069ba3 | |||
2a592a4a15 | |||
8ca357ea7f | |||
4f4c05a922 | |||
7c4be0f4e9 | |||
afea7fe5e7 | |||
294f0061bd | |||
4efe159933 | |||
b7f99c022b | |||
b3c5e53156 | |||
91c2b04ab4 | |||
27efb10a27 | |||
e4e32f46fe | |||
64b169069a | |||
c2c15e1ac3 | |||
0b3156c4c7 | |||
1c8551c842 | |||
2755d98b99 | |||
543108a5dd | |||
b32d02dc3f | |||
0bd92ef77e | |||
a7df4cc125 | |||
09a615ee62 | |||
8523b406ad | |||
6021da072c | |||
a49abbd123 | |||
f9091c0b0c | |||
bbf8fd5b20 | |||
be84747ffc | |||
478b443430 | |||
ded5f6560d | |||
c1b3629dcf | |||
5879499924 | |||
5a63f294c0 | |||
891a29feeb | |||
0863505877 | |||
0c922bd63a | |||
e04ec4c706 | |||
b0f9733ac8 | |||
e2babfc076 | |||
ef29b569e5 | |||
6f0a455d0b | |||
7d6a420c52 | |||
259143b87e | |||
fce426c318 | |||
9b794777b5 | |||
3ada668366 | |||
39a39e763d | |||
50353280d3 | |||
72b8211029 | |||
dbf719b59b | |||
57d7d3821f | |||
e86e9fc079 | |||
d708b78ebe | |||
075418eda1 | |||
9fc5b83b61 |
11
TODO.md
11
TODO.md
@@ -15,7 +15,7 @@
|
|||||||
- decrease s6 restart time?
|
- decrease s6 restart time?
|
||||||
- `ssh` access doesn't grant same linux capabilities as login
|
- `ssh` access doesn't grant same linux capabilities as login
|
||||||
- ringer (i.e. dino incoming call) doesn't prevent moby from sleeping
|
- ringer (i.e. dino incoming call) doesn't prevent moby from sleeping
|
||||||
- sysvol (volume overlay): when casting with `blast`, sysvol doesn't react to volume changes
|
- syshud (volume overlay): when casting with `blast`, syshud doesn't react to volume changes
|
||||||
- moby: kaslr is effectively disabled
|
- moby: kaslr is effectively disabled
|
||||||
- `dmesg | grep "KASLR disabled due to lack of seed"`
|
- `dmesg | grep "KASLR disabled due to lack of seed"`
|
||||||
- fix by adding `kaslrseed` to uboot script before `booti`
|
- fix by adding `kaslrseed` to uboot script before `booti`
|
||||||
@@ -26,6 +26,11 @@
|
|||||||
- `dmesg | grep 'hid_bpf: error while preloading HID BPF dispatcher: -22'`
|
- `dmesg | grep 'hid_bpf: error while preloading HID BPF dispatcher: -22'`
|
||||||
- `s6` is not re-entrant
|
- `s6` is not re-entrant
|
||||||
- so if the desktop crashes, the login process from `unl0kr` fails to re-launch the GUI
|
- so if the desktop crashes, the login process from `unl0kr` fails to re-launch the GUI
|
||||||
|
- swaync brightness slider does not work
|
||||||
|
- it reads brightness from /sys/class/backlight/....
|
||||||
|
- but to *set* the brightness it assumes systemd logind is running
|
||||||
|
<repo:ErikReider/SwayNotificationCenter:src/controlCenter/widgets/backlight/backlightUtil.vala>
|
||||||
|
no reason i can't just write to that file, or exec brightnessctl (if i learn vala)
|
||||||
|
|
||||||
## REFACTORING:
|
## REFACTORING:
|
||||||
- add import checks to my Python nix-shell scripts
|
- add import checks to my Python nix-shell scripts
|
||||||
@@ -126,11 +131,9 @@
|
|||||||
- add option to change audio output
|
- add option to change audio output
|
||||||
- fix colors (red alert) to match overall theme
|
- fix colors (red alert) to match overall theme
|
||||||
- moby: tune GPS
|
- moby: tune GPS
|
||||||
- run only geoclue, and not gpsd, to save power?
|
|
||||||
- tune QGPS setting in eg25-control, for less jitter?
|
- tune QGPS setting in eg25-control, for less jitter?
|
||||||
- direct mepo to prefer gpsd, with fallback to geoclue, for better accuracy?
|
|
||||||
- configure geoclue to do some smoothing?
|
- configure geoclue to do some smoothing?
|
||||||
- manually do smoothing, as some layer between mepo and geoclue/gpsd?
|
- manually do smoothing, as some layer between mepo and geoclue?
|
||||||
- moby: port `freshen-agps` timer service to s6 (maybe i want some `s6-cron` or something)
|
- moby: port `freshen-agps` timer service to s6 (maybe i want some `s6-cron` or something)
|
||||||
- moby: show battery state on ssh login
|
- moby: show battery state on ssh login
|
||||||
- moby: improve gPodder launch time
|
- moby: improve gPodder launch time
|
||||||
|
70
default.nix
70
default.nix
@@ -1,67 +1,5 @@
|
|||||||
# limited, non-flake interface to this repo.
|
{ ... }@args:
|
||||||
# this file exposes the same view into `pkgs` which the flake would see when evaluated.
|
|
||||||
#
|
|
||||||
# the primary purpose of this file is so i can run `updateScript`s which expect
|
|
||||||
# the root to be `default.nix`
|
|
||||||
{ }:
|
|
||||||
let
|
let
|
||||||
mkPkgs = args: (import ./pkgs/additional/nixpkgs args).extend
|
sane-nix-files = import ./pkgs/additional/sane-nix-files { };
|
||||||
(import ./overlays/all.nix);
|
in
|
||||||
inherit (mkPkgs {}) lib;
|
import "${sane-nix-files}/impure.nix" args
|
||||||
|
|
||||||
evalHost = { name, system, branch ? "master", variant ? null }:
|
|
||||||
let
|
|
||||||
pkgs = mkPkgs { inherit system; variant = branch; };
|
|
||||||
in pkgs.nixos (
|
|
||||||
[
|
|
||||||
(lib.optionalAttrs (variant == "light") {
|
|
||||||
sane.maxBuildCost = 2;
|
|
||||||
})
|
|
||||||
(lib.optionalAttrs (variant == "min") {
|
|
||||||
sane.maxBuildCost = 0;
|
|
||||||
})
|
|
||||||
(import ./hosts/instantiate.nix { hostName = name; })
|
|
||||||
(import ./modules)
|
|
||||||
pkgs.sops-nix.nixosModules.sops
|
|
||||||
]
|
|
||||||
);
|
|
||||||
mkFlavoredHost = args: let
|
|
||||||
host = evalHost args;
|
|
||||||
# expose the toplevel nixos system as the toplevel attribute itself,
|
|
||||||
# with nested aliases for other common build targets
|
|
||||||
in host.config.system.build.toplevel.overrideAttrs (base: {
|
|
||||||
passthru = (base.passthru or {}) // {
|
|
||||||
config = host.config;
|
|
||||||
fs = host.config.sane.fs;
|
|
||||||
img = host.config.system.build.img;
|
|
||||||
pkgs = host.config.system.build.pkgs;
|
|
||||||
programs = lib.mapAttrs (_: p: p.package) host.config.sane.programs;
|
|
||||||
toplevel = host.config.system.build.toplevel; #< self
|
|
||||||
};
|
|
||||||
});
|
|
||||||
mkHost = args: {
|
|
||||||
# TODO: swap order: $host-{next,staging}-{min,light}:
|
|
||||||
# then lexicographically-adjacent targets would also have the minimal difference in closure,
|
|
||||||
# and the order in which each target should be built is more evident
|
|
||||||
"${args.name}" = mkFlavoredHost args;
|
|
||||||
"${args.name}-next" = mkFlavoredHost args // { branch = "staging-next"; };
|
|
||||||
"${args.name}-staging" = mkFlavoredHost args // { branch = "staging"; };
|
|
||||||
"${args.name}-light" = mkFlavoredHost args // { variant = "light"; };
|
|
||||||
"${args.name}-light-next" = mkFlavoredHost args // { variant = "light"; branch = "staging-next"; };
|
|
||||||
"${args.name}-light-staging" = mkFlavoredHost args // { variant = "light"; branch = "staging"; };
|
|
||||||
"${args.name}-min" = mkFlavoredHost args // { variant = "min"; };
|
|
||||||
"${args.name}-min-next" = mkFlavoredHost args // { variant = "min"; branch = "staging-next"; };
|
|
||||||
"${args.name}-min-staging" = mkFlavoredHost args // { variant = "min"; branch = "staging-staging"; };
|
|
||||||
};
|
|
||||||
|
|
||||||
hosts = lib.foldl' (acc: host: acc // (mkHost host)) {} [
|
|
||||||
{ name = "crappy"; system = "armv7l-linux"; }
|
|
||||||
{ name = "desko"; system = "x86_64-linux"; }
|
|
||||||
{ name = "lappy"; system = "x86_64-linux"; }
|
|
||||||
{ name = "moby"; system = "aarch64-linux"; }
|
|
||||||
{ name = "rescue"; system = "x86_64-linux"; }
|
|
||||||
{ name = "servo"; system = "x86_64-linux"; }
|
|
||||||
];
|
|
||||||
in {
|
|
||||||
inherit hosts;
|
|
||||||
} // (mkPkgs {})
|
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
sane.programs.dino.config.autostart = false;
|
sane.programs.dino.config.autostart = false;
|
||||||
sane.programs.dissent.config.autostart = false;
|
sane.programs.dissent.config.autostart = false;
|
||||||
sane.programs.fractal.config.autostart = false;
|
sane.programs.fractal.config.autostart = false;
|
||||||
|
sane.programs.sway.config.mod = "Mod1"; #< alt key instead of Super
|
||||||
|
|
||||||
# sane.programs.guiApps.enableFor.user.colin = false;
|
# sane.programs.guiApps.enableFor.user.colin = false;
|
||||||
|
|
||||||
|
@@ -10,7 +10,6 @@
|
|||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./fs.nix
|
./fs.nix
|
||||||
./gps.nix
|
|
||||||
];
|
];
|
||||||
|
|
||||||
sane.hal.pine64.enable = true;
|
sane.hal.pine64.enable = true;
|
||||||
@@ -29,6 +28,7 @@
|
|||||||
sops.secrets.colin-passwd.neededForUsers = true;
|
sops.secrets.colin-passwd.neededForUsers = true;
|
||||||
|
|
||||||
sane.programs.sway.enableFor.user.colin = true;
|
sane.programs.sway.enableFor.user.colin = true;
|
||||||
|
sane.programs.sway.config.mod = "Mod1"; #< alt key instead of Super
|
||||||
sane.programs.blueberry.enableFor.user.colin = false; # bluetooth manager: doesn't cross compile!
|
sane.programs.blueberry.enableFor.user.colin = false; # bluetooth manager: doesn't cross compile!
|
||||||
sane.programs.fcitx5.enableFor.user.colin = false; # does not cross compile
|
sane.programs.fcitx5.enableFor.user.colin = false; # does not cross compile
|
||||||
sane.programs.mercurial.enableFor.user.colin = false; # does not cross compile
|
sane.programs.mercurial.enableFor.user.colin = false; # does not cross compile
|
||||||
|
@@ -1,68 +0,0 @@
|
|||||||
# pinephone GPS happens in EG25 modem
|
|
||||||
# serial control interface to modem is /dev/ttyUSB2
|
|
||||||
# after enabling GPS, readout is /dev/ttyUSB1
|
|
||||||
#
|
|
||||||
# minimal process to enable modem and GPS:
|
|
||||||
# - `echo 1 > /sys/class/modem-power/modem-power/device/powered`
|
|
||||||
# - `screen /dev/ttyUSB2 115200`
|
|
||||||
# - `AT+QGPSCFG="nmeasrc",1`
|
|
||||||
# - `AT+QGPS=1`
|
|
||||||
# this process is automated by my `eg25-control` program and services (`eg25-control-powered`, `eg25-control-gps`)
|
|
||||||
# - see the `modules/` directory further up this repository.
|
|
||||||
#
|
|
||||||
# now, something like `gpsd` can directly read from /dev/ttyUSB1,
|
|
||||||
# or geoclue can query the GPS directly through modem-manager
|
|
||||||
#
|
|
||||||
# initial GPS fix can take 15+ minutes.
|
|
||||||
# meanwhile, services like eg25-manager or eg25-control-freshen-agps can speed this up by uploading assisted GPS data to the modem.
|
|
||||||
#
|
|
||||||
# support/help:
|
|
||||||
# - geoclue, gnome-maps
|
|
||||||
# - irc: #gnome-maps on irc.gimp.org
|
|
||||||
# - Matrix: #gnome-maps:gnome.org (unclear if bridged to IRC)
|
|
||||||
#
|
|
||||||
# programs to pair this with:
|
|
||||||
# - `satellite-gtk`: <https://codeberg.org/tpikonen/satellite>
|
|
||||||
# - shows/tracks which satellites the GPS is connected to; useful to understand fix characteristics
|
|
||||||
# - `gnome-maps`: uses geoclue, has route planning
|
|
||||||
# - `mepo`: uses gpsd, minimalist, flaky, and buttons are kinda hard to activate on mobile
|
|
||||||
# - puremaps?
|
|
||||||
# - osmin?
|
|
||||||
#
|
|
||||||
# known/outstanding bugs:
|
|
||||||
# - `systemctl start eg25-control-gps` can the hang the whole system (2023/10/06)
|
|
||||||
# - i think it's actually `eg25-control-powered` which does this (started by the gps)
|
|
||||||
# - best guess is modem draws so much power at launch that other parts of the system see undervoltage
|
|
||||||
# - workaround is to hard power-cycle the system. the modem may not bring up after reboot: leave unpowered for 60s and boot again.
|
|
||||||
#
|
|
||||||
# future work:
|
|
||||||
# - integrate with [wigle](https://www.wigle.net/) for offline equivalent to Mozilla Location Services
|
|
||||||
|
|
||||||
{ config, lib, ... }:
|
|
||||||
{
|
|
||||||
# test gpsd with `gpspipe -w -n 10 2> /dev/null | grep -m 1 TPV | jq '.lat, .lon' | tr '\n' ' '`
|
|
||||||
# ^ should return <lat> <long>
|
|
||||||
services.gpsd.enable = true;
|
|
||||||
services.gpsd.devices = [ "/dev/ttyUSB1" ];
|
|
||||||
|
|
||||||
# test geoclue2 by building `geoclue2-with-demo-agent`
|
|
||||||
# and running "${geoclue2-with-demo-agent}/libexec/geoclue-2.0/demos/where-am-i"
|
|
||||||
# note that geoclue is dbus-activated, and auto-stops after 60s with no caller
|
|
||||||
services.geoclue2.enable = true;
|
|
||||||
services.geoclue2.appConfig.where-am-i = {
|
|
||||||
# this is the default "agent", shipped by geoclue package: allow it to use location
|
|
||||||
isAllowed = true;
|
|
||||||
isSystem = false;
|
|
||||||
# XXX: setting users != [] might be causing `where-am-i` to time out
|
|
||||||
users = [
|
|
||||||
# restrict to only one set of users. empty array (default) means "allow any user to access geolocation".
|
|
||||||
(builtins.toString config.users.users.colin.uid)
|
|
||||||
];
|
|
||||||
};
|
|
||||||
systemd.services.geoclue.after = lib.mkForce []; #< defaults to network-online, but not all my sources require network
|
|
||||||
users.users.geoclue.extraGroups = [
|
|
||||||
"dialout" # TODO: figure out if dialout is required. that's for /dev/ttyUSB1, but geoclue probably doesn't read that?
|
|
||||||
];
|
|
||||||
|
|
||||||
sane.programs.where-am-i.enableFor.user.colin = true;
|
|
||||||
}
|
|
@@ -36,7 +36,8 @@
|
|||||||
# - rb = received bytes
|
# - rb = received bytes
|
||||||
# - sp = sent packets
|
# - sp = sent packets
|
||||||
# - sb = sent bytes
|
# - sb = sent bytes
|
||||||
{ lib, ... }:
|
|
||||||
|
{ config, lib, ... }:
|
||||||
let
|
let
|
||||||
# TURN port range (inclusive).
|
# TURN port range (inclusive).
|
||||||
# default coturn behavior is to use the upper quarter of all ports. i.e. 49152 - 65535.
|
# default coturn behavior is to use the upper quarter of all ports. i.e. 49152 - 65535.
|
||||||
@@ -130,11 +131,11 @@ in
|
|||||||
"verbose"
|
"verbose"
|
||||||
# "Verbose" #< even MORE verbosity than "verbose" (it's TOO MUCH verbosity really)
|
# "Verbose" #< even MORE verbosity than "verbose" (it's TOO MUCH verbosity really)
|
||||||
"no-multicast-peers" # disables sending to IPv4 broadcast addresses (e.g. 224.0.0.0/3)
|
"no-multicast-peers" # disables sending to IPv4 broadcast addresses (e.g. 224.0.0.0/3)
|
||||||
# "listening-ip=10.0.1.5" "external-ip=185.157.162.178" #< 2024/04/25: works, if running in root namespace
|
# "listening-ip=${config.sane.netns.ovpns.hostVethIpv4}" "external-ip=${config.sane.netns.ovpns.netnsPubIpv4}" #< 2024/04/25: works, if running in root namespace
|
||||||
"listening-ip=185.157.162.178" "external-ip=185.157.162.178"
|
"listening-ip=${config.sane.netns.ovpns.netnsPubIpv4}" "external-ip=${config.sane.netns.ovpns.netnsPubIpv4}"
|
||||||
|
|
||||||
# old attempts:
|
# old attempts:
|
||||||
# "external-ip=185.157.162.178/10.0.1.5"
|
# "external-ip=${config.sane.netns.ovpns.netnsPubIpv4}/${config.sane.netns.ovpns.hostVethIpv4}"
|
||||||
# "listening-ip=10.78.79.51" # can be specified multiple times; omit for *
|
# "listening-ip=10.78.79.51" # can be specified multiple times; omit for *
|
||||||
# "external-ip=97.113.128.229/10.78.79.51"
|
# "external-ip=97.113.128.229/10.78.79.51"
|
||||||
# "external-ip=97.113.128.229"
|
# "external-ip=97.113.128.229"
|
||||||
|
@@ -51,54 +51,54 @@ lib.mkIf false
|
|||||||
{
|
{
|
||||||
"3478" = {
|
"3478" = {
|
||||||
protocol = [ "tcp" "udp" ];
|
protocol = [ "tcp" "udp" ];
|
||||||
|
visibleTo.doof = true;
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-xmpp-stun-turn";
|
description = "colin-xmpp-stun-turn";
|
||||||
};
|
};
|
||||||
"5222" = {
|
"5222" = {
|
||||||
protocol = [ "tcp" ];
|
protocol = [ "tcp" ];
|
||||||
|
visibleTo.doof = true;
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-xmpp-client-to-server";
|
description = "colin-xmpp-client-to-server";
|
||||||
};
|
};
|
||||||
"5223" = {
|
"5223" = {
|
||||||
protocol = [ "tcp" ];
|
protocol = [ "tcp" ];
|
||||||
|
visibleTo.doof = true;
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-xmpps-client-to-server"; # XMPP over TLS
|
description = "colin-xmpps-client-to-server"; # XMPP over TLS
|
||||||
};
|
};
|
||||||
"5269" = {
|
"5269" = {
|
||||||
protocol = [ "tcp" ];
|
protocol = [ "tcp" ];
|
||||||
visibleTo.wan = true;
|
visibleTo.doof = true;
|
||||||
description = "colin-xmpp-server-to-server";
|
description = "colin-xmpp-server-to-server";
|
||||||
};
|
};
|
||||||
"5270" = {
|
"5270" = {
|
||||||
protocol = [ "tcp" ];
|
protocol = [ "tcp" ];
|
||||||
visibleTo.wan = true;
|
visibleTo.doof = true;
|
||||||
description = "colin-xmpps-server-to-server"; # XMPP over TLS
|
description = "colin-xmpps-server-to-server"; # XMPP over TLS
|
||||||
};
|
};
|
||||||
"5280" = {
|
"5280" = {
|
||||||
protocol = [ "tcp" ];
|
protocol = [ "tcp" ];
|
||||||
|
visibleTo.doof = true;
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-xmpp-bosh";
|
description = "colin-xmpp-bosh";
|
||||||
};
|
};
|
||||||
"5281" = {
|
"5281" = {
|
||||||
protocol = [ "tcp" ];
|
protocol = [ "tcp" ];
|
||||||
|
visibleTo.doof = true;
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-xmpp-bosh-https";
|
description = "colin-xmpp-bosh-https";
|
||||||
};
|
};
|
||||||
"5349" = {
|
"5349" = {
|
||||||
protocol = [ "tcp" ];
|
protocol = [ "tcp" ];
|
||||||
|
visibleTo.doof = true;
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-xmpp-stun-turn-over-tls";
|
description = "colin-xmpp-stun-turn-over-tls";
|
||||||
};
|
};
|
||||||
"5443" = {
|
"5443" = {
|
||||||
protocol = [ "tcp" ];
|
protocol = [ "tcp" ];
|
||||||
|
visibleTo.doof = true;
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-xmpp-web-services"; # file uploads, websockets, admin
|
description = "colin-xmpp-web-services"; # file uploads, websockets, admin
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -109,8 +109,8 @@ lib.mkIf false
|
|||||||
numPorts = turnPortHigh - turnPortLow + 1;
|
numPorts = turnPortHigh - turnPortLow + 1;
|
||||||
in {
|
in {
|
||||||
protocol = [ "tcp" "udp" ];
|
protocol = [ "tcp" "udp" ];
|
||||||
|
visibleTo.doof = true;
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-xmpp-turn-${builtins.toString count}-of-${builtins.toString numPorts}";
|
description = "colin-xmpp-turn-${builtins.toString count}-of-${builtins.toString numPorts}";
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
@@ -8,14 +8,14 @@
|
|||||||
{
|
{
|
||||||
sane.ports.ports."143" = {
|
sane.ports.ports."143" = {
|
||||||
protocol = [ "tcp" ];
|
protocol = [ "tcp" ];
|
||||||
|
visibleTo.doof = true;
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-imap-imap.uninsane.org";
|
description = "colin-imap-imap.uninsane.org";
|
||||||
};
|
};
|
||||||
sane.ports.ports."993" = {
|
sane.ports.ports."993" = {
|
||||||
protocol = [ "tcp" ];
|
protocol = [ "tcp" ];
|
||||||
|
visibleTo.doof = true;
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-imaps-imap.uninsane.org";
|
description = "colin-imaps-imap.uninsane.org";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
# postfix config options: <https://www.postfix.org/postconf.5.html>
|
# postfix config options: <https://www.postfix.org/postconf.5.html>
|
||||||
|
|
||||||
{ lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
submissionOptions = {
|
submissionOptions = {
|
||||||
@@ -56,8 +56,7 @@ in
|
|||||||
|
|
||||||
sane.dns.zones."uninsane.org".inet = {
|
sane.dns.zones."uninsane.org".inet = {
|
||||||
MX."@" = "10 mx.uninsane.org.";
|
MX."@" = "10 mx.uninsane.org.";
|
||||||
# XXX: RFC's specify that the MX record CANNOT BE A CNAME
|
A."mx" = "%AOVPNS%"; #< XXX: RFC's specify that the MX record CANNOT BE A CNAME. TODO: use "%AOVPNS%?
|
||||||
A."mx" = "185.157.162.178";
|
|
||||||
|
|
||||||
# Sender Policy Framework:
|
# Sender Policy Framework:
|
||||||
# +mx => mail passes if it originated from the MX
|
# +mx => mail passes if it originated from the MX
|
||||||
|
@@ -12,6 +12,10 @@
|
|||||||
device = "/var/media";
|
device = "/var/media";
|
||||||
options = [ "rbind" ];
|
options = [ "rbind" ];
|
||||||
};
|
};
|
||||||
|
fileSystems."/var/export/pub" = {
|
||||||
|
device = "/var/www/sites/uninsane.org/share";
|
||||||
|
options = [ "rbind" ];
|
||||||
|
};
|
||||||
# fileSystems."/var/export/playground" = {
|
# fileSystems."/var/export/playground" = {
|
||||||
# device = config.fileSystems."/mnt/persist/ext".device;
|
# device = config.fileSystems."/mnt/persist/ext".device;
|
||||||
# fsType = "btrfs";
|
# fsType = "btrfs";
|
||||||
@@ -37,7 +41,8 @@
|
|||||||
wantedBy = [ "nfs.service" "sftpgo.service" ];
|
wantedBy = [ "nfs.service" "sftpgo.service" ];
|
||||||
file.text = ''
|
file.text = ''
|
||||||
- media/ read-only: Videos, Music, Books, etc
|
- media/ read-only: Videos, Music, Books, etc
|
||||||
- playground/ read-write: use it to share files with other users of this server
|
- playground/ read-write: use it to share files with other users of this server, inaccessible from the www
|
||||||
|
- pub/ read-only: content made to be shared with the www
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -27,13 +27,12 @@ in
|
|||||||
"21" = {
|
"21" = {
|
||||||
protocol = [ "tcp" ];
|
protocol = [ "tcp" ];
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
# visibleTo.wan = true;
|
|
||||||
description = "colin-FTP server";
|
description = "colin-FTP server";
|
||||||
};
|
};
|
||||||
"990" = {
|
"990" = {
|
||||||
protocol = [ "tcp" ];
|
protocol = [ "tcp" ];
|
||||||
|
visibleTo.doof = true;
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-FTPS server";
|
description = "colin-FTPS server";
|
||||||
};
|
};
|
||||||
} // (sane-lib.mapToAttrs
|
} // (sane-lib.mapToAttrs
|
||||||
@@ -41,8 +40,8 @@ in
|
|||||||
name = builtins.toString port;
|
name = builtins.toString port;
|
||||||
value = {
|
value = {
|
||||||
protocol = [ "tcp" ];
|
protocol = [ "tcp" ];
|
||||||
|
visibleTo.doof = true;
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-FTP server data port range";
|
description = "colin-FTP server data port range";
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
@@ -101,6 +100,13 @@ in
|
|||||||
debug = true;
|
debug = true;
|
||||||
tls_mode = 2; # 2 = "implicit FTPS": client negotiates TLS before any FTP command.
|
tls_mode = 2; # 2 = "implicit FTPS": client negotiates TLS before any FTP command.
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
# binding this means any doof client can connect (TLS only)
|
||||||
|
address = config.sane.netns.doof.hostVethIpv4;
|
||||||
|
port = 990;
|
||||||
|
debug = true;
|
||||||
|
tls_mode = 2; # 2 = "implicit FTPS": client negotiates TLS before any FTP command.
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
# active mode is susceptible to "bounce attacks", without much benefit over passive mode
|
# active mode is susceptible to "bounce attacks", without much benefit over passive mode
|
||||||
@@ -117,7 +123,7 @@ in
|
|||||||
banner = ''
|
banner = ''
|
||||||
Welcome, friends, to Colin's FTP server! Also available via NFS on the same host, but LAN-only.
|
Welcome, friends, to Colin's FTP server! Also available via NFS on the same host, but LAN-only.
|
||||||
|
|
||||||
Read-only access (LAN-restricted):
|
Read-only access (LAN clients see everything; WAN clients can only see /pub):
|
||||||
Username: "anonymous"
|
Username: "anonymous"
|
||||||
Password: "anonymous"
|
Password: "anonymous"
|
||||||
|
|
||||||
|
@@ -45,6 +45,8 @@ from hmac import compare_digest
|
|||||||
|
|
||||||
authFail = dict(username="")
|
authFail = dict(username="")
|
||||||
|
|
||||||
|
PERM_DENY = []
|
||||||
|
PERM_LIST = [ "list" ]
|
||||||
PERM_RO = [ "list", "download" ]
|
PERM_RO = [ "list", "download" ]
|
||||||
PERM_RW = [
|
PERM_RW = [
|
||||||
# read-only:
|
# read-only:
|
||||||
@@ -127,12 +129,14 @@ def getAuthResponse(ip: str, username: str, password: str) -> dict:
|
|||||||
return mkAuthOk(username, permissions = {
|
return mkAuthOk(username, permissions = {
|
||||||
"/": PERM_RW,
|
"/": PERM_RW,
|
||||||
"/playground": PERM_RW,
|
"/playground": PERM_RW,
|
||||||
|
"/pub": PERM_RO,
|
||||||
})
|
})
|
||||||
if isWireguard(ip):
|
if isWireguard(ip):
|
||||||
# allow any user from wireguard
|
# allow any user from wireguard
|
||||||
return mkAuthOk(username, permissions = {
|
return mkAuthOk(username, permissions = {
|
||||||
"/": PERM_RW,
|
"/": PERM_RW,
|
||||||
"/playground": PERM_RW,
|
"/playground": PERM_RW,
|
||||||
|
"/pub": PERM_RO,
|
||||||
})
|
})
|
||||||
if isLan(ip):
|
if isLan(ip):
|
||||||
if username == "anonymous":
|
if username == "anonymous":
|
||||||
@@ -140,6 +144,18 @@ def getAuthResponse(ip: str, username: str, password: str) -> dict:
|
|||||||
return mkAuthOk("anonymous", permissions = {
|
return mkAuthOk("anonymous", permissions = {
|
||||||
"/": PERM_RO,
|
"/": PERM_RO,
|
||||||
"/playground": PERM_RW,
|
"/playground": PERM_RW,
|
||||||
|
"/pub": PERM_RO,
|
||||||
|
})
|
||||||
|
if username == "anonymous":
|
||||||
|
# anonymous users from the www can have even more limited access.
|
||||||
|
# mostly because i need an easy way to test WAN connectivity :-)
|
||||||
|
return mkAuthOk("anonymous", permissions = {
|
||||||
|
# "/": PERM_DENY,
|
||||||
|
"/": PERM_LIST, #< REQUIRED, even for lftp to list a subdir
|
||||||
|
"/media": PERM_DENY,
|
||||||
|
"/playground": PERM_DENY,
|
||||||
|
"/pub": PERM_RO,
|
||||||
|
# "/README.md": PERM_RO, #< does not work
|
||||||
})
|
})
|
||||||
|
|
||||||
return authFail
|
return authFail
|
||||||
|
@@ -133,7 +133,7 @@
|
|||||||
sane.ports.ports."22" = {
|
sane.ports.ports."22" = {
|
||||||
protocol = [ "tcp" ];
|
protocol = [ "tcp" ];
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
visibleTo.wan = true;
|
visibleTo.doof = true;
|
||||||
description = "colin-git@git.uninsane.org";
|
description = "colin-git@git.uninsane.org";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
{ lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
lib.mkIf false #< TODO: re-enable once confident of sandboxing
|
|
||||||
{
|
{
|
||||||
sane.persist.sys.byStore.plaintext = [
|
sane.persist.sys.byStore.plaintext = [
|
||||||
# TODO: mode? we only need this to save Indexer creds ==> migrate to config?
|
# TODO: mode? we only need this to save Indexer creds ==> migrate to config?
|
||||||
@@ -13,7 +12,7 @@ lib.mkIf false #< TODO: re-enable once confident of sandboxing
|
|||||||
systemd.services.jackett.serviceConfig = {
|
systemd.services.jackett.serviceConfig = {
|
||||||
# run this behind the OVPN static VPN
|
# run this behind the OVPN static VPN
|
||||||
NetworkNamespacePath = "/run/netns/ovpns";
|
NetworkNamespacePath = "/run/netns/ovpns";
|
||||||
ExecStartPre = [ "${lib.getExe pkgs.sane-scripts.ip-check} --no-upnp --expect 185.157.162.178" ]; # abort if public IP is not as expected
|
ExecStartPre = [ "${lib.getExe pkgs.sane-scripts.ip-check} --no-upnp --expect ${config.sane.netns.ovpns.netnsPubIpv4}" ]; # abort if public IP is not as expected
|
||||||
|
|
||||||
# patch jackett to listen on the public interfaces
|
# patch jackett to listen on the public interfaces
|
||||||
# ExecStart = lib.mkForce "${pkgs.jackett}/bin/Jackett --NoUpdates --DataFolder /var/lib/jackett/.config/Jackett --ListenPublic";
|
# ExecStart = lib.mkForce "${pkgs.jackett}/bin/Jackett --NoUpdates --DataFolder /var/lib/jackett/.config/Jackett --ListenPublic";
|
||||||
@@ -25,8 +24,7 @@ lib.mkIf false #< TODO: re-enable once confident of sandboxing
|
|||||||
enableACME = true;
|
enableACME = true;
|
||||||
# inherit kTLS;
|
# inherit kTLS;
|
||||||
locations."/" = {
|
locations."/" = {
|
||||||
# proxyPass = "http://ovpns.uninsane.org:9117";
|
proxyPass = "http://${config.sane.netns.ovpns.netnsVethIpv4}:9117";
|
||||||
proxyPass = "http://10.0.1.6:9117";
|
|
||||||
recommendedProxySettings = true;
|
recommendedProxySettings = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@@ -4,12 +4,11 @@
|
|||||||
{ config, lib, ... }:
|
{ config, lib, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
ircServer = { name, additionalAddresses ? [], sasl ? true, port ? 6697 }: let
|
ircServer = { name, additionalAddresses ? [], ssl ? true, sasl ? true, port ? if ssl then 6697 else 6667 }: let
|
||||||
lowerName = lib.toLower name;
|
lowerName = lib.toLower name;
|
||||||
in {
|
in {
|
||||||
# XXX sasl: appservice doesn't support NickServ identification (only SASL, or PASS if sasl = false)
|
# XXX sasl: appservice doesn't support NickServ identification (only SASL, or PASS if sasl = false)
|
||||||
inherit name additionalAddresses sasl port;
|
inherit additionalAddresses name port sasl ssl;
|
||||||
ssl = true;
|
|
||||||
botConfig = {
|
botConfig = {
|
||||||
# bot has no presence in IRC channel; only real Matrix users
|
# bot has no presence in IRC channel; only real Matrix users
|
||||||
enabled = false;
|
enabled = false;
|
||||||
@@ -156,6 +155,10 @@ in
|
|||||||
# - #sxmo-offtopic
|
# - #sxmo-offtopic
|
||||||
};
|
};
|
||||||
"irc.rizon.net" = ircServer { name = "Rizon"; };
|
"irc.rizon.net" = ircServer { name = "Rizon"; };
|
||||||
|
"wigle.net" = ircServer {
|
||||||
|
name = "WiGLE";
|
||||||
|
ssl = false;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@@ -17,7 +17,6 @@ in
|
|||||||
sane.ports.ports."80" = {
|
sane.ports.ports."80" = {
|
||||||
protocol = [ "tcp" ];
|
protocol = [ "tcp" ];
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
visibleTo.wan = true;
|
|
||||||
visibleTo.ovpns = true; # so that letsencrypt can procure a cert for the mx record
|
visibleTo.ovpns = true; # so that letsencrypt can procure a cert for the mx record
|
||||||
visibleTo.doof = true;
|
visibleTo.doof = true;
|
||||||
description = "colin-http-uninsane.org";
|
description = "colin-http-uninsane.org";
|
||||||
@@ -25,7 +24,6 @@ in
|
|||||||
sane.ports.ports."443" = {
|
sane.ports.ports."443" = {
|
||||||
protocol = [ "tcp" ];
|
protocol = [ "tcp" ];
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
visibleTo.wan = true;
|
|
||||||
visibleTo.doof = true;
|
visibleTo.doof = true;
|
||||||
description = "colin-https-uninsane.org";
|
description = "colin-https-uninsane.org";
|
||||||
};
|
};
|
||||||
|
@@ -86,7 +86,7 @@ in
|
|||||||
sane.ports.ports."${builtins.toString altPort}" = {
|
sane.ports.ports."${builtins.toString altPort}" = {
|
||||||
protocol = [ "tcp" ];
|
protocol = [ "tcp" ];
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
visibleTo.wan = true;
|
visibleTo.doof = true;
|
||||||
description = "colin-ntfy.uninsane.org";
|
description = "colin-ntfy.uninsane.org";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -62,8 +62,8 @@ in
|
|||||||
sane.ports.ports = lib.mkMerge (lib.forEach portRange (port: {
|
sane.ports.ports = lib.mkMerge (lib.forEach portRange (port: {
|
||||||
"${builtins.toString port}" = {
|
"${builtins.toString port}" = {
|
||||||
protocol = [ "tcp" ];
|
protocol = [ "tcp" ];
|
||||||
|
visibleTo.doof = true;
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-notification-waiter-${builtins.toString (port - portLow + 1)}-of-${builtins.toString numPorts}";
|
description = "colin-notification-waiter-${builtins.toString (port - portLow + 1)}-of-${builtins.toString numPorts}";
|
||||||
};
|
};
|
||||||
}));
|
}));
|
||||||
|
@@ -61,42 +61,42 @@ in
|
|||||||
];
|
];
|
||||||
sane.ports.ports."5000" = {
|
sane.ports.ports."5000" = {
|
||||||
protocol = [ "tcp" ];
|
protocol = [ "tcp" ];
|
||||||
|
visibleTo.doof = true;
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-xmpp-prosody-fileshare-proxy65";
|
description = "colin-xmpp-prosody-fileshare-proxy65";
|
||||||
};
|
};
|
||||||
sane.ports.ports."5222" = {
|
sane.ports.ports."5222" = {
|
||||||
protocol = [ "tcp" ];
|
protocol = [ "tcp" ];
|
||||||
|
visibleTo.doof = true;
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-xmpp-client-to-server";
|
description = "colin-xmpp-client-to-server";
|
||||||
};
|
};
|
||||||
sane.ports.ports."5223" = {
|
sane.ports.ports."5223" = {
|
||||||
protocol = [ "tcp" ];
|
protocol = [ "tcp" ];
|
||||||
|
visibleTo.doof = true;
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-xmpps-client-to-server"; # XMPP over TLS
|
description = "colin-xmpps-client-to-server"; # XMPP over TLS
|
||||||
};
|
};
|
||||||
sane.ports.ports."5269" = {
|
sane.ports.ports."5269" = {
|
||||||
protocol = [ "tcp" ];
|
protocol = [ "tcp" ];
|
||||||
visibleTo.wan = true;
|
visibleTo.doof = true;
|
||||||
description = "colin-xmpp-server-to-server";
|
description = "colin-xmpp-server-to-server";
|
||||||
};
|
};
|
||||||
sane.ports.ports."5270" = {
|
sane.ports.ports."5270" = {
|
||||||
protocol = [ "tcp" ];
|
protocol = [ "tcp" ];
|
||||||
visibleTo.wan = true;
|
visibleTo.doof = true;
|
||||||
description = "colin-xmpps-server-to-server"; # XMPP over TLS
|
description = "colin-xmpps-server-to-server"; # XMPP over TLS
|
||||||
};
|
};
|
||||||
sane.ports.ports."5280" = {
|
sane.ports.ports."5280" = {
|
||||||
protocol = [ "tcp" ];
|
protocol = [ "tcp" ];
|
||||||
|
visibleTo.doof = true;
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-xmpp-bosh";
|
description = "colin-xmpp-bosh";
|
||||||
};
|
};
|
||||||
sane.ports.ports."5281" = {
|
sane.ports.ports."5281" = {
|
||||||
protocol = [ "tcp" ];
|
protocol = [ "tcp" ];
|
||||||
|
visibleTo.doof = true;
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-xmpp-prosody-https"; # necessary?
|
description = "colin-xmpp-prosody-https"; # necessary?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -32,7 +32,7 @@
|
|||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
locations."/" = {
|
locations."/" = {
|
||||||
proxyPass = "http://10.0.1.6:5030";
|
proxyPass = "http://${config.sane.netns.ovpns.netnsVethIpv4}:5030";
|
||||||
proxyWebsockets = true;
|
proxyWebsockets = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -71,7 +71,7 @@
|
|||||||
systemd.services.slskd.serviceConfig = {
|
systemd.services.slskd.serviceConfig = {
|
||||||
# run this behind the OVPN static VPN
|
# run this behind the OVPN static VPN
|
||||||
NetworkNamespacePath = "/run/netns/ovpns";
|
NetworkNamespacePath = "/run/netns/ovpns";
|
||||||
ExecStartPre = [ "${lib.getExe pkgs.sane-scripts.ip-check} --no-upnp --expect 185.157.162.178" ]; # abort if public IP is not as expected
|
ExecStartPre = [ "${lib.getExe pkgs.sane-scripts.ip-check} --no-upnp --expect ${config.sane.netns.ovpns.netnsPubIpv4}" ]; # abort if public IP is not as expected
|
||||||
|
|
||||||
Restart = lib.mkForce "always"; # exits "success" when it fails to connect to soulseek server
|
Restart = lib.mkForce "always"; # exits "success" when it fails to connect to soulseek server
|
||||||
RestartSec = "60s";
|
RestartSec = "60s";
|
||||||
|
@@ -82,7 +82,6 @@ let
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
lib.mkIf false #< TODO: re-enable once confident of sandboxing
|
|
||||||
{
|
{
|
||||||
sane.persist.sys.byStore.plaintext = [
|
sane.persist.sys.byStore.plaintext = [
|
||||||
# TODO: mode? we need this specifically for the stats tracking in .config/
|
# TODO: mode? we need this specifically for the stats tracking in .config/
|
||||||
@@ -106,8 +105,8 @@ lib.mkIf false #< TODO: re-enable once confident of sandboxing
|
|||||||
# DOCUMENTATION/options list: <https://github.com/transmission/transmission/blob/main/docs/Editing-Configuration-Files.md#options>
|
# DOCUMENTATION/options list: <https://github.com/transmission/transmission/blob/main/docs/Editing-Configuration-Files.md#options>
|
||||||
|
|
||||||
# message-level = 3; #< enable for debug logging. 0-3, default is 2.
|
# message-level = 3; #< enable for debug logging. 0-3, default is 2.
|
||||||
# 10.0.1.6 => allow rpc only from the root servo ns. it'll tunnel things to the net, if need be.
|
# ovpns.netnsVethIpv4 => allow rpc only from the root servo ns. it'll tunnel things to the net, if need be.
|
||||||
rpc-bind-address = "10.0.1.6";
|
rpc-bind-address = config.sane.netns.ovpns.netnsVethIpv4;
|
||||||
#rpc-host-whitelist = "bt.uninsane.org";
|
#rpc-host-whitelist = "bt.uninsane.org";
|
||||||
#rpc-whitelist = "*.*.*.*";
|
#rpc-whitelist = "*.*.*.*";
|
||||||
rpc-authentication-required = true;
|
rpc-authentication-required = true;
|
||||||
@@ -118,7 +117,7 @@ lib.mkIf false #< TODO: re-enable once confident of sandboxing
|
|||||||
rpc-whitelist-enabled = false;
|
rpc-whitelist-enabled = false;
|
||||||
|
|
||||||
# force behind ovpns in case the NetworkNamespace fails somehow
|
# force behind ovpns in case the NetworkNamespace fails somehow
|
||||||
bind-address-ipv4 = "185.157.162.178";
|
bind-address-ipv4 = config.sane.netns.ovpns.netnsPubIpv4;
|
||||||
port-forwarding-enabled = false;
|
port-forwarding-enabled = false;
|
||||||
|
|
||||||
# hopefully, make the downloads world-readable
|
# hopefully, make the downloads world-readable
|
||||||
@@ -160,7 +159,7 @@ lib.mkIf false #< TODO: re-enable once confident of sandboxing
|
|||||||
systemd.services.transmission.serviceConfig = {
|
systemd.services.transmission.serviceConfig = {
|
||||||
# run this behind the OVPN static VPN
|
# run this behind the OVPN static VPN
|
||||||
NetworkNamespacePath = "/run/netns/ovpns";
|
NetworkNamespacePath = "/run/netns/ovpns";
|
||||||
ExecStartPre = [ "${lib.getExe pkgs.sane-scripts.ip-check} --no-upnp --expect 185.157.162.178" ]; # abort if public IP is not as expected
|
ExecStartPre = [ "${lib.getExe pkgs.sane-scripts.ip-check} --no-upnp --expect ${config.sane.netns.ovpns.netnsPubIpv4}" ]; # abort if public IP is not as expected
|
||||||
|
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
RestartSec = "30s";
|
RestartSec = "30s";
|
||||||
@@ -190,7 +189,7 @@ lib.mkIf false #< TODO: re-enable once confident of sandboxing
|
|||||||
# inherit kTLS;
|
# inherit kTLS;
|
||||||
locations."/" = {
|
locations."/" = {
|
||||||
# proxyPass = "http://ovpns.uninsane.org:9091";
|
# proxyPass = "http://ovpns.uninsane.org:9091";
|
||||||
proxyPass = "http://10.0.1.6:9091";
|
proxyPass = "http://${config.sane.netns.ovpns.netnsVethIpv4}:9091";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -4,14 +4,12 @@
|
|||||||
let
|
let
|
||||||
dyn-dns = config.sane.services.dyn-dns;
|
dyn-dns = config.sane.services.dyn-dns;
|
||||||
nativeAddrs = lib.mapAttrs (_name: builtins.head) config.sane.dns.zones."uninsane.org".inet.A;
|
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
|
in
|
||||||
{
|
{
|
||||||
sane.ports.ports."53" = {
|
sane.ports.ports."53" = {
|
||||||
protocol = [ "udp" "tcp" ];
|
protocol = [ "udp" "tcp" ];
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
visibleTo.wan = true;
|
# visibleTo.wan = true;
|
||||||
visibleTo.ovpns = true;
|
visibleTo.ovpns = true;
|
||||||
visibleTo.doof = true;
|
visibleTo.doof = true;
|
||||||
description = "colin-dns-hosting";
|
description = "colin-dns-hosting";
|
||||||
@@ -41,6 +39,7 @@ in
|
|||||||
CNAME."native" = "%CNAMENATIVE%";
|
CNAME."native" = "%CNAMENATIVE%";
|
||||||
A."@" = "%ANATIVE%";
|
A."@" = "%ANATIVE%";
|
||||||
A."servo.wan" = "%AWAN%";
|
A."servo.wan" = "%AWAN%";
|
||||||
|
A."servo.doof" = "%ADOOF%";
|
||||||
A."servo.lan" = config.sane.hosts.by-name."servo".lan-ip;
|
A."servo.lan" = config.sane.hosts.by-name."servo".lan-ip;
|
||||||
A."servo.hn" = config.sane.hosts.by-name."servo".wg-home.ip;
|
A."servo.hn" = config.sane.hosts.by-name."servo".wg-home.ip;
|
||||||
|
|
||||||
@@ -48,9 +47,9 @@ in
|
|||||||
# it's best that we keep this identical, or a superset of, what org. lists as our NS.
|
# it's best that we keep this identical, or a superset of, what org. lists as our NS.
|
||||||
# so, org. can specify ns2/ns3 as being to the VPN, with no mention of ns1. we provide ns1 here.
|
# so, org. can specify ns2/ns3 as being to the VPN, with no mention of ns1. we provide ns1 here.
|
||||||
A."ns1" = "%ANATIVE%";
|
A."ns1" = "%ANATIVE%";
|
||||||
A."ns2" = "185.157.162.178";
|
A."ns2" = "%ADOOF%";
|
||||||
A."ns3" = "185.157.162.178";
|
A."ns3" = "%AOVPNS%";
|
||||||
A."ovpns" = "185.157.162.178";
|
A."ovpns" = "%AOVPNS%";
|
||||||
NS."@" = [
|
NS."@" = [
|
||||||
"ns1.uninsane.org."
|
"ns1.uninsane.org."
|
||||||
"ns2.uninsane.org."
|
"ns2.uninsane.org."
|
||||||
@@ -61,59 +60,64 @@ in
|
|||||||
services.trust-dns.settings.zones = [ "uninsane.org" ];
|
services.trust-dns.settings.zones = [ "uninsane.org" ];
|
||||||
|
|
||||||
|
|
||||||
networking.nat.enable = true;
|
networking.nat.enable = true; #< TODO: try removing this?
|
||||||
networking.nat.extraCommands = ''
|
# networking.nat.extraCommands = ''
|
||||||
# redirect incoming DNS requests from LAN addresses
|
# # redirect incoming DNS requests from LAN addresses
|
||||||
# to the LAN-specialized DNS service
|
# # to the LAN-specialized DNS service
|
||||||
# N.B.: use the `nixos-*` chains instead of e.g. PREROUTING
|
# # N.B.: use the `nixos-*` chains instead of e.g. PREROUTING
|
||||||
# because they get cleanly reset across activations or `systemctl restart firewall`
|
# # because they get cleanly reset across activations or `systemctl restart firewall`
|
||||||
# instead of accumulating cruft
|
# # instead of accumulating cruft
|
||||||
iptables -t nat -A nixos-nat-pre -p udp --dport 53 \
|
# iptables -t nat -A nixos-nat-pre -p udp --dport 53 \
|
||||||
-m iprange --src-range 10.78.76.0-10.78.79.255 \
|
# -m iprange --src-range 10.78.76.0-10.78.79.255 \
|
||||||
-j DNAT --to-destination :1053
|
# -j DNAT --to-destination :1053
|
||||||
iptables -t nat -A nixos-nat-pre -p tcp --dport 53 \
|
# iptables -t nat -A nixos-nat-pre -p tcp --dport 53 \
|
||||||
-m iprange --src-range 10.78.76.0-10.78.79.255 \
|
# -m iprange --src-range 10.78.76.0-10.78.79.255 \
|
||||||
-j DNAT --to-destination :1053
|
# -j DNAT --to-destination :1053
|
||||||
'';
|
# '';
|
||||||
sane.ports.ports."1053" = {
|
# sane.ports.ports."1053" = {
|
||||||
# because the NAT above redirects in nixos-nat-pre, LAN requests behave as though they arrived on the external interface at the redirected port.
|
# # because the NAT above redirects in nixos-nat-pre, LAN requests behave as though they arrived on the external interface at the redirected port.
|
||||||
# TODO: try nixos-nat-post instead?
|
# # TODO: try nixos-nat-post instead?
|
||||||
# TODO: or, don't NAT from port 53 -> port 1053, but rather nat from LAN addr to a loopback addr.
|
# # TODO: or, don't NAT from port 53 -> port 1053, but rather nat from LAN addr to a loopback addr.
|
||||||
# - this is complicated in that loopback is a different interface than eth0, so rewriting the destination address would cause the packets to just be dropped by the interface
|
# # - this is complicated in that loopback is a different interface than eth0, so rewriting the destination address would cause the packets to just be dropped by the interface
|
||||||
protocol = [ "udp" "tcp" ];
|
# protocol = [ "udp" "tcp" ];
|
||||||
visibleTo.lan = true;
|
# visibleTo.lan = true;
|
||||||
description = "colin-redirected-dns-for-lan-namespace";
|
# description = "colin-redirected-dns-for-lan-namespace";
|
||||||
};
|
# };
|
||||||
|
|
||||||
|
|
||||||
sane.services.trust-dns.enable = true;
|
sane.services.trust-dns.enable = true;
|
||||||
sane.services.trust-dns.instances = let
|
sane.services.trust-dns.instances = let
|
||||||
mkSubstitutions = flavor: {
|
mkSubstitutions = flavor: {
|
||||||
|
"%ADOOF%" = config.sane.netns.doof.netnsPubIpv4;
|
||||||
|
"%ANATIVE%" = nativeAddrs."servo.${flavor}";
|
||||||
|
"%AOVPNS%" = config.sane.netns.ovpns.netnsPubIpv4;
|
||||||
"%AWAN%" = "$(cat '${dyn-dns.ipPath}')";
|
"%AWAN%" = "$(cat '${dyn-dns.ipPath}')";
|
||||||
"%CNAMENATIVE%" = "servo.${flavor}";
|
"%CNAMENATIVE%" = "servo.${flavor}";
|
||||||
"%ANATIVE%" = nativeAddrs."servo.${flavor}";
|
|
||||||
"%AOVPNS%" = "185.157.162.178";
|
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
wan = {
|
doof = {
|
||||||
substitutions = mkSubstitutions "wan";
|
substitutions = mkSubstitutions "doof";
|
||||||
listenAddrsIpv4 = [
|
listenAddrsIpv4 = [
|
||||||
nativeAddrs."servo.lan"
|
config.sane.netns.doof.hostVethIpv4
|
||||||
bindOvpn
|
config.sane.netns.ovpns.hostVethIpv4
|
||||||
bindDoof
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
lan = {
|
|
||||||
substitutions = mkSubstitutions "lan";
|
|
||||||
listenAddrsIpv4 = [ nativeAddrs."servo.lan" ];
|
|
||||||
port = 1053;
|
|
||||||
};
|
|
||||||
hn = {
|
hn = {
|
||||||
substitutions = mkSubstitutions "hn";
|
substitutions = mkSubstitutions "hn";
|
||||||
listenAddrsIpv4 = [ nativeAddrs."servo.hn" ];
|
listenAddrsIpv4 = [ nativeAddrs."servo.hn" ];
|
||||||
port = 1053;
|
|
||||||
};
|
};
|
||||||
|
lan = {
|
||||||
|
substitutions = mkSubstitutions "lan";
|
||||||
|
listenAddrsIpv4 = [ nativeAddrs."servo.lan" ];
|
||||||
|
# port = 1053;
|
||||||
|
};
|
||||||
|
# wan = {
|
||||||
|
# substitutions = mkSubstitutions "wan";
|
||||||
|
# listenAddrsIpv4 = [
|
||||||
|
# nativeAddrs."servo.lan"
|
||||||
|
# ];
|
||||||
|
# };
|
||||||
# hn-resolver = {
|
# hn-resolver = {
|
||||||
# # don't need %AWAN% here because we forward to the hn instance.
|
# # don't need %AWAN% here because we forward to the hn instance.
|
||||||
# listenAddrsIpv4 = [ nativeAddrs."servo.hn" ];
|
# listenAddrsIpv4 = [ nativeAddrs."servo.hn" ];
|
||||||
@@ -154,9 +158,10 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
sane.services.dyn-dns.restartOnChange = [
|
sane.services.dyn-dns.restartOnChange = [
|
||||||
"trust-dns-wan.service"
|
"trust-dns-doof.service"
|
||||||
"trust-dns-lan.service"
|
|
||||||
"trust-dns-hn.service"
|
"trust-dns-hn.service"
|
||||||
|
"trust-dns-lan.service"
|
||||||
|
# "trust-dns-wan.service"
|
||||||
# "trust-dns-hn-resolver.service" # doesn't need restart because it doesn't know about WAN IP
|
# "trust-dns-hn-resolver.service" # doesn't need restart because it doesn't know about WAN IP
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@@ -574,10 +574,6 @@ in
|
|||||||
gawk.sandbox.wrapperType = "inplace"; # /share/gawk libraries refer to /libexec
|
gawk.sandbox.wrapperType = "inplace"; # /share/gawk libraries refer to /libexec
|
||||||
gawk.sandbox.autodetectCliPaths = "existingFile";
|
gawk.sandbox.autodetectCliPaths = "existingFile";
|
||||||
|
|
||||||
gdb.sandbox.enable = false; # gdb doesn't sandbox well. i don't know how you could.
|
|
||||||
# gdb.sandbox.method = "landlock"; # permission denied when trying to attach, even as root
|
|
||||||
gdb.sandbox.autodetectCliPaths = true;
|
|
||||||
|
|
||||||
geoclue2-with-demo-agent = {};
|
geoclue2-with-demo-agent = {};
|
||||||
|
|
||||||
# MS GitHub stores auth token in .config
|
# MS GitHub stores auth token in .config
|
||||||
@@ -1181,13 +1177,12 @@ in
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
hardware.opengl = lib.mkIf config.sane.programs.guiApps.enabled ({
|
hardware.graphics = lib.mkIf config.sane.programs.guiApps.enabled ({
|
||||||
enable = true;
|
enable = true;
|
||||||
driSupport = lib.mkDefault true;
|
|
||||||
} // (lib.optionalAttrs pkgs.stdenv.isx86_64 {
|
} // (lib.optionalAttrs pkgs.stdenv.isx86_64 {
|
||||||
# for 32 bit applications
|
# for 32 bit applications
|
||||||
# upstream nixpkgs forbids setting driSupport32Bit unless specifically x86_64 (so aarch64 isn't allowed)
|
# upstream nixpkgs forbids setting enable32Bit unless specifically x86_64 (so aarch64 isn't allowed)
|
||||||
driSupport32Bit = lib.mkDefault true;
|
enable32Bit = lib.mkDefault true;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
system.activationScripts.notifyActive = lib.mkIf config.sane.programs.guiApps.enabled {
|
system.activationScripts.notifyActive = lib.mkIf config.sane.programs.guiApps.enabled {
|
||||||
|
@@ -111,7 +111,7 @@ in
|
|||||||
'';
|
'';
|
||||||
});
|
});
|
||||||
|
|
||||||
fs.".config/bonsai/bonsai_tree.json".symlink.text = builtins.toJSON cfg.config.transitions;
|
fs.".config/bonsai/bonsai_tree.json".symlink.target = pkgs.writers.writeJSON "bonsai_tree.json" cfg.config.transitions;
|
||||||
|
|
||||||
sandbox.method = "bwrap";
|
sandbox.method = "bwrap";
|
||||||
sandbox.extraRuntimePaths = [
|
sandbox.extraRuntimePaths = [
|
||||||
|
@@ -66,6 +66,7 @@ end
|
|||||||
if vars.percent ~= nil then
|
if vars.percent ~= nil then
|
||||||
bat_args = bat_args .. " --percent-suffix '" .. vars.percent .. "'"
|
bat_args = bat_args .. " --percent-suffix '" .. vars.percent .. "'"
|
||||||
end
|
end
|
||||||
|
bat_args = bat_args .. " {bat}"
|
||||||
|
|
||||||
-- N.B.: `[[ <text> ]]` is Lua's multiline string literal
|
-- N.B.: `[[ <text> ]]` is Lua's multiline string literal
|
||||||
conky.text = [[
|
conky.text = [[
|
||||||
@@ -73,8 +74,8 @@ ${color1}${shadecolor 707070}${font sans-serif:size=50:style=Bold}${alignc}${exe
|
|||||||
${color2}${shadecolor a4d7d0}${font sans-serif:size=20}${alignc}${exec date +"%a %d %b"}${font}
|
${color2}${shadecolor a4d7d0}${font sans-serif:size=20}${alignc}${exec date +"%a %d %b"}${font}
|
||||||
|
|
||||||
|
|
||||||
${color1}${shadecolor}${font sans-serif:size=22:style=Bold}${alignc}${execp @bat@ ]] .. bat_args .. [[ }${font}
|
${color1}${shadecolor}${font sans-serif:size=22:style=Bold}${alignc}${execp sane-sysload ]] .. bat_args .. [[ }${font}
|
||||||
${color1}${shadecolor}${font sans-serif:size=20:style=Bold}${alignc}${texeci 600 @weather@ }${font}
|
${color1}${shadecolor}${font sans-serif:size=20:style=Bold}${alignc}${texeci 600 timeout 20 sane-weather }${font}
|
||||||
|
|
||||||
|
|
||||||
${color2}${shadecolor a4d7d0}${font sans-serif:size=16}${alignc}⇅ ${downspeedf wlan0}]] .. vars.kBps .. [[${font}
|
${color2}${shadecolor a4d7d0}${font sans-serif:size=16}${alignc}⇅ ${downspeedf wlan0}]] .. vars.kBps .. [[${font}
|
||||||
|
@@ -5,22 +5,18 @@
|
|||||||
sandbox.net = "clearnet"; #< for the scripts it calls (weather)
|
sandbox.net = "clearnet"; #< for the scripts it calls (weather)
|
||||||
sandbox.extraPaths = [
|
sandbox.extraPaths = [
|
||||||
"/sys/class/power_supply"
|
"/sys/class/power_supply"
|
||||||
"/sys/devices" # needed by sane-sysinfo
|
"/sys/devices" # needed by sane-sysload
|
||||||
# "/sys/devices/cpu"
|
# "/sys/devices/cpu"
|
||||||
# "/sys/devices/system"
|
# "/sys/devices/system"
|
||||||
];
|
];
|
||||||
sandbox.whitelistWayland = true;
|
sandbox.whitelistWayland = true;
|
||||||
|
|
||||||
suggestedPrograms = [
|
suggestedPrograms = [
|
||||||
"sane-sysinfo"
|
"sane-sysload"
|
||||||
"sane-weather"
|
"sane-weather"
|
||||||
];
|
];
|
||||||
|
|
||||||
fs.".config/conky/conky.conf".symlink.target = pkgs.substituteAll {
|
fs.".config/conky/conky.conf".symlink.target = ./conky.conf;
|
||||||
src = ./conky.conf;
|
|
||||||
bat = "sane-sysinfo";
|
|
||||||
weather = "timeout 20 sane-weather";
|
|
||||||
};
|
|
||||||
|
|
||||||
services.conky = {
|
services.conky = {
|
||||||
description = "conky dynamic desktop background";
|
description = "conky dynamic desktop background";
|
||||||
|
@@ -50,8 +50,11 @@
|
|||||||
./fwupd.nix
|
./fwupd.nix
|
||||||
./g4music.nix
|
./g4music.nix
|
||||||
./gajim.nix
|
./gajim.nix
|
||||||
|
./gdb.nix
|
||||||
./gdbus.nix
|
./gdbus.nix
|
||||||
./geary.nix
|
./geary.nix
|
||||||
|
./geoclue-demo-agent.nix
|
||||||
|
./geoclue2.nix
|
||||||
./git.nix
|
./git.nix
|
||||||
./gnome-clocks.nix
|
./gnome-clocks.nix
|
||||||
./gnome-feeds.nix
|
./gnome-feeds.nix
|
||||||
@@ -60,6 +63,7 @@
|
|||||||
./gnome-weather.nix
|
./gnome-weather.nix
|
||||||
./go2tv.nix
|
./go2tv.nix
|
||||||
./gpodder.nix
|
./gpodder.nix
|
||||||
|
./gpsd.nix
|
||||||
./grimshot.nix
|
./grimshot.nix
|
||||||
./gst-device-monitor.nix
|
./gst-device-monitor.nix
|
||||||
./gthumb.nix
|
./gthumb.nix
|
||||||
@@ -87,6 +91,7 @@
|
|||||||
./msmtp.nix
|
./msmtp.nix
|
||||||
./nautilus.nix
|
./nautilus.nix
|
||||||
./neovim.nix
|
./neovim.nix
|
||||||
|
./networkmanager_dmenu
|
||||||
./newsflash.nix
|
./newsflash.nix
|
||||||
./nheko.nix
|
./nheko.nix
|
||||||
./nicotine-plus.nix
|
./nicotine-plus.nix
|
||||||
@@ -98,8 +103,10 @@
|
|||||||
./objdump.nix
|
./objdump.nix
|
||||||
./obsidian.nix
|
./obsidian.nix
|
||||||
./offlineimap.nix
|
./offlineimap.nix
|
||||||
|
./ols.nix
|
||||||
./open-in-mpv.nix
|
./open-in-mpv.nix
|
||||||
./pactl.nix
|
./pactl.nix
|
||||||
|
./pidof.nix
|
||||||
./pipewire.nix
|
./pipewire.nix
|
||||||
./planify.nix
|
./planify.nix
|
||||||
./portfolio-filemanager.nix
|
./portfolio-filemanager.nix
|
||||||
@@ -114,9 +121,10 @@
|
|||||||
./sane-open.nix
|
./sane-open.nix
|
||||||
./sane-screenshot.nix
|
./sane-screenshot.nix
|
||||||
./sane-scripts.nix
|
./sane-scripts.nix
|
||||||
./sane-sysinfo.nix
|
./sane-sysload.nix
|
||||||
./sane-theme.nix
|
./sane-theme.nix
|
||||||
./sanebox.nix
|
./sanebox.nix
|
||||||
|
./satellite.nix
|
||||||
./schlock.nix
|
./schlock.nix
|
||||||
./seatd.nix
|
./seatd.nix
|
||||||
./sfeed.nix
|
./sfeed.nix
|
||||||
@@ -136,7 +144,7 @@
|
|||||||
./swaylock.nix
|
./swaylock.nix
|
||||||
./swaynotificationcenter
|
./swaynotificationcenter
|
||||||
./switchboard.nix
|
./switchboard.nix
|
||||||
./sysvol.nix
|
./syshud.nix
|
||||||
./tangram.nix
|
./tangram.nix
|
||||||
./tor-browser.nix
|
./tor-browser.nix
|
||||||
./tuba.nix
|
./tuba.nix
|
||||||
@@ -144,6 +152,7 @@
|
|||||||
./vlc.nix
|
./vlc.nix
|
||||||
./waybar
|
./waybar
|
||||||
./waylock.nix
|
./waylock.nix
|
||||||
|
./where-am-i.nix
|
||||||
./wike.nix
|
./wike.nix
|
||||||
./wine.nix
|
./wine.nix
|
||||||
./wireplumber.nix
|
./wireplumber.nix
|
||||||
|
@@ -55,7 +55,7 @@ in
|
|||||||
# - theme-demo
|
# - theme-demo
|
||||||
# - timeout-completed
|
# - timeout-completed
|
||||||
# - window-close
|
# - window-close
|
||||||
fs.".config/feedbackd/themes/proxied.json".symlink.text = builtins.toJSON {
|
fs.".config/feedbackd/themes/proxied.json".symlink.target = pkgs.writers.writeJSON "proxied.json" {
|
||||||
name = "proxied";
|
name = "proxied";
|
||||||
parent-theme = "default";
|
parent-theme = "default";
|
||||||
profiles = [
|
profiles = [
|
||||||
|
13
hosts/common/programs/gdb.nix
Normal file
13
hosts/common/programs/gdb.nix
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
sane.programs.gdb = {
|
||||||
|
sandbox.enable = false; # gdb doesn't sandbox well. i don't know how you could.
|
||||||
|
# sandbox.method = "landlock"; # permission denied when trying to attach, even as root
|
||||||
|
sandbox.autodetectCliPaths = true;
|
||||||
|
fs.".config/gdb/gdbinit".symlink.text = ''
|
||||||
|
# enable commands like `py-bt`, `py-list`, etc.
|
||||||
|
# for usage, see: <https://wiki.python.org/moin/DebuggingWithGdb>
|
||||||
|
source ${pkgs.python3}/share/gdb/libpython.py
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
16
hosts/common/programs/geoclue-demo-agent.nix
Normal file
16
hosts/common/programs/geoclue-demo-agent.nix
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{ config, pkgs, ... }:
|
||||||
|
{
|
||||||
|
sane.programs.geoclue-demo-agent = {
|
||||||
|
packageUnwrapped = pkgs.linkFarm "geoclue-demo-agent" [{
|
||||||
|
# bring the demo agent into a `bin/` directory so it can be invokable via PATH
|
||||||
|
name = "bin/geoclue-demo-agent";
|
||||||
|
path = "${config.sane.programs.geoclue2.packageUnwrapped}/libexec/geoclue-2.0/demos/agent";
|
||||||
|
}];
|
||||||
|
|
||||||
|
services.geoclue-agent = {
|
||||||
|
description = "geoclue 'demo' agent";
|
||||||
|
command = "geoclue-demo-agent";
|
||||||
|
partOf = [ "graphical-session" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
62
hosts/common/programs/geoclue2.nix
Normal file
62
hosts/common/programs/geoclue2.nix
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# geoclue location services daemon.
|
||||||
|
#
|
||||||
|
# SUPPORT:
|
||||||
|
# - irc: #gnome-maps on irc.gimp.org
|
||||||
|
# - Matrix: #gnome-maps:gnome.org (unclear if bridged to IRC)
|
||||||
|
# - forums: <https://discourse.gnome.org/c/platform>
|
||||||
|
# - git: <https://gitlab.freedesktop.org/geoclue/geoclue/>
|
||||||
|
# - D-Bus API docs: <https://www.freedesktop.org/software/geoclue/docs/>
|
||||||
|
#
|
||||||
|
# HOW TO TEST:
|
||||||
|
# - just invoke `where-am-i`: it should output the current latitude/longitude.
|
||||||
|
## more manual testing:
|
||||||
|
# - build `geoclue2-with-demo-agent`
|
||||||
|
# - run the service: `systemctl start geoclue` or "${geoclue2-with-demo-agent}/libexec/geoclue"
|
||||||
|
# - run "${geoclue2-with-demo-agent}/libexec/geoclue-2.0/demos/agent"
|
||||||
|
# - keep this running in the background
|
||||||
|
# - run "${geoclue2-with-demo-agent}/libexec/geoclue-2.0/demos/where-am-i"
|
||||||
|
#
|
||||||
|
# DATA FLOW:
|
||||||
|
# - geoclue2 does http calls into local `ols`, which either hits the local disk or queries https://wigle.net.
|
||||||
|
# - geoclue users like gnome-maps somehow depend on an "agent",
|
||||||
|
# a user service which launches the geoclue system service on-demand (via dbus activation).
|
||||||
|
#
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.sane.programs.geoclue2;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
sane.programs.geoclue2 = {
|
||||||
|
# packageUnwrapped = pkgs.rmDbusServices pkgs.geoclue2;
|
||||||
|
# packageUnwrapped = pkgs.geoclue2.override { withDemoAgent = true; };
|
||||||
|
packageUnwrapped = pkgs.geoclue2-with-demo-agent;
|
||||||
|
suggestedPrograms = [
|
||||||
|
"geoclue-demo-agent"
|
||||||
|
"ols" #< WiFi SSID -> lat/long lookups
|
||||||
|
"satellite" #< graphical view into GPS fix data
|
||||||
|
"where-am-i" #< handy debugging/testing tool
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
# sane.programs.geoclue2.enableFor.system = lib.mkIf (builtins.any (en: en) (builtins.attrValues cfg.enableFor.user)) true;
|
||||||
|
|
||||||
|
# prevent geoclue from modifying the GPS settings: i manage that myself, and trying to co-manage it with geoclue causes issues.
|
||||||
|
security.polkit.extraConfig = lib.optionalString cfg.enabled ''
|
||||||
|
polkit.addRule(function(action, subject) {
|
||||||
|
if (subject.user == "geoclue" && action.id == "org.freedesktop.ModemManager1.Device.Control") {
|
||||||
|
return polkit.Result.NO;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
'';
|
||||||
|
|
||||||
|
|
||||||
|
services.geoclue2 = lib.mkIf cfg.enabled {
|
||||||
|
enable = true;
|
||||||
|
geoProviderUrl = "http://127.0.0.1:8088/v1/geolocate"; #< ols
|
||||||
|
};
|
||||||
|
systemd.user.services = lib.mkIf cfg.enabled {
|
||||||
|
# nixos services.geoclue2 runs the agent as a user service by default, but i don't use systemd so that doesn't work.
|
||||||
|
# i manage the agent myself, in sane.programs.geoclue-demo-agent.
|
||||||
|
geoclue-agent.enable = false;
|
||||||
|
};
|
||||||
|
}
|
@@ -40,6 +40,7 @@ in
|
|||||||
alias.amend = "commit --amend --no-edit";
|
alias.amend = "commit --amend --no-edit";
|
||||||
alias.br = "branch";
|
alias.br = "branch";
|
||||||
alias.co = "checkout";
|
alias.co = "checkout";
|
||||||
|
alias.com = "commit";
|
||||||
alias.cp = "cherry-pick";
|
alias.cp = "cherry-pick";
|
||||||
alias.d = "difftool";
|
alias.d = "difftool";
|
||||||
alias.dif = "diff"; # common typo
|
alias.dif = "diff"; # common typo
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
# gnome feeds RSS viewer
|
# gnome feeds RSS viewer
|
||||||
{ config, lib, sane-lib, ... }:
|
{ config, lib, pkgs, sane-lib, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
feeds = sane-lib.feeds;
|
feeds = sane-lib.feeds;
|
||||||
all-feeds = config.sane.feeds;
|
all-feeds = config.sane.feeds;
|
||||||
wanted-feeds = feeds.filterByFormat ["text" "image"] all-feeds;
|
wanted-feeds = feeds.filterByFormat ["text" "image"] all-feeds;
|
||||||
in {
|
in {
|
||||||
sane.programs.gnome-feeds.fs.".config/org.gabmus.gfeeds.json".symlink.text = builtins.toJSON {
|
sane.programs.gnome-feeds.fs.".config/org.gabmus.gfeeds.json".symlink.target = pkgs.writers.writeJSON "org.gabmus.gfeeds.json" {
|
||||||
# feed format is a map from URL to a dict,
|
# feed format is a map from URL to a dict,
|
||||||
# with dict["tags"] a list of string tags.
|
# with dict["tags"] a list of string tags.
|
||||||
feeds = sane-lib.mapToAttrs (feed: {
|
feeds = sane-lib.mapToAttrs (feed: {
|
||||||
|
@@ -1,7 +1,14 @@
|
|||||||
|
# SUPPORT:
|
||||||
|
# - irc: #gnome-maps on irc.gimp.org
|
||||||
|
# - Matrix: #gnome-maps:gnome.org (unclear if bridged to IRC)
|
||||||
{ pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
{
|
{
|
||||||
sane.programs."gnome.gnome-maps" = {
|
sane.programs."gnome.gnome-maps" = {
|
||||||
packageUnwrapped = pkgs.rmDbusServices pkgs.gnome.gnome-maps;
|
packageUnwrapped = pkgs.rmDbusServices pkgs.gnome.gnome-maps;
|
||||||
|
suggestedPrograms = [
|
||||||
|
"geoclue2"
|
||||||
|
];
|
||||||
|
|
||||||
sandbox.method = "bwrap";
|
sandbox.method = "bwrap";
|
||||||
sandbox.whitelistDri = true; # for perf
|
sandbox.whitelistDri = true; # for perf
|
||||||
sandbox.whitelistDbus = [
|
sandbox.whitelistDbus = [
|
||||||
|
33
hosts/common/programs/gpsd.nix
Normal file
33
hosts/common/programs/gpsd.nix
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# test gpsd with `gpspipe -w -n 10 2> /dev/null | grep -m 1 TPV | jq '.lat, .lon' | tr '\n' ' '`
|
||||||
|
# ^ should return <lat> <long>
|
||||||
|
#
|
||||||
|
# TODO(2024/06/19): nixpkgs' gpsd service isn't sandboxed at ALL. i should sandbox that, or remove this integration.
|
||||||
|
#
|
||||||
|
# pinephone GPS happens in EG25 modem
|
||||||
|
# serial control interface to modem is /dev/ttyUSB2
|
||||||
|
# after enabling GPS, readout is /dev/ttyUSB1
|
||||||
|
#
|
||||||
|
# minimal process to enable modem and GPS:
|
||||||
|
# - `echo 1 > /sys/class/modem-power/modem-power/device/powered`
|
||||||
|
# - `screen /dev/ttyUSB2 115200`
|
||||||
|
# - `AT+QGPSCFG="nmeasrc",1`
|
||||||
|
# - `AT+QGPS=1`
|
||||||
|
# this process is automated by my `eg25-control` program and services (`eg25-control-powered`, `eg25-control-gps`)
|
||||||
|
# - see the `modules/` directory further up this repository.
|
||||||
|
#
|
||||||
|
# now, something like `gpsd` can directly read from /dev/ttyUSB1,
|
||||||
|
# or geoclue can query the GPS directly through modem-manager
|
||||||
|
#
|
||||||
|
# initial GPS fix can take 15+ minutes.
|
||||||
|
# meanwhile, services like eg25-manager or eg25-control-freshen-agps can speed this up by uploading assisted GPS data to the modem.
|
||||||
|
{ config, lib, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.sane.programs.gpsd;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
sane.programs.gpsd = {};
|
||||||
|
services.gpsd = lib.mkIf cfg.enabled {
|
||||||
|
enable = true;
|
||||||
|
devices = [ "/dev/ttyUSB1" ];
|
||||||
|
};
|
||||||
|
}
|
@@ -1,7 +1,7 @@
|
|||||||
# docs: <https://git.sr.ht/~mil/mepo>
|
# docs: <https://git.sr.ht/~mil/mepo>
|
||||||
# irc #mepo:irc.oftc.net
|
# irc #mepo:irc.oftc.net
|
||||||
|
#
|
||||||
{ config, lib, ... }:
|
{ config, lib, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
sane.programs.mepo = {
|
sane.programs.mepo = {
|
||||||
sandbox.method = "bwrap";
|
sandbox.method = "bwrap";
|
||||||
@@ -16,11 +16,11 @@
|
|||||||
{ type = "file"; path = ".cache/mepo/savestate"; }
|
{ type = "file"; path = ".cache/mepo/savestate"; }
|
||||||
];
|
];
|
||||||
|
|
||||||
# give mepo access to gpsd for location data, if that's enabled.
|
# enable geoclue2 and gpsd for location data.
|
||||||
# same with geoclue2.
|
suggestedPrograms = [
|
||||||
suggestedPrograms = lib.optional config.services.gpsd.enable "gpsd"
|
"geoclue2"
|
||||||
++ lib.optional config.services.geoclue2.enable "geoclue2-with-demo-agent"
|
# "gpsd" #< not required, and mepo only uses it if geoclue is unavailable
|
||||||
;
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
# programs.mepo = lib.mkIf config.sane.programs.mepo.enabled {
|
# programs.mepo = lib.mkIf config.sane.programs.mepo.enabled {
|
||||||
|
@@ -1,3 +1,19 @@
|
|||||||
|
# GPS:
|
||||||
|
# - enable: `mmcli --modem any --location-enable-gps-unmanaged`
|
||||||
|
# - or `mmcli -m any --location-enable-gps-nmea`
|
||||||
|
# - or use `s6-rc start eg25-control-gps`
|
||||||
|
# - verify GPS is enabled: `mmcli --modem any --location-status`
|
||||||
|
# - query GPS coordinates: `mmcli -m any --location-get`
|
||||||
|
# - monitor constellation info: `mmcli -m any --location-monitor`
|
||||||
|
# - i.e. which satellites are in view
|
||||||
|
# - or just `cat /dev/ttyUSB1`
|
||||||
|
#
|
||||||
|
# interactions, warnings:
|
||||||
|
# - Geoclue (`where-am-i`) toggles mmcli GPS on/off every 60s, often resetting it to the "off" state
|
||||||
|
# - see: <https://gitlab.freedesktop.org/geoclue/geoclue/-/issues/180>
|
||||||
|
# - the effect is that GPS data is effectively useless inside apps like gnome-maps
|
||||||
|
# i think the trick is to get "--location-enable-gps-unmanaged" gps working again
|
||||||
|
# or use gnss-share/gpsd (this may be what "unmanaged" means).
|
||||||
{ pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
{
|
{
|
||||||
sane.programs.mmcli = {
|
sane.programs.mmcli = {
|
||||||
|
44
hosts/common/programs/networkmanager_dmenu/config.ini
Normal file
44
hosts/common/programs/networkmanager_dmenu/config.ini
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
[dmenu]
|
||||||
|
dmenu_command = rofi -dmenu
|
||||||
|
# # Note that dmenu_command can contain arguments as well like:
|
||||||
|
# # `dmenu_command = rofi -dmenu -i -theme nmdm`
|
||||||
|
# # `dmenu_command = rofi -dmenu -width 30 -i`
|
||||||
|
# # `dmenu_command = dmenu -i -l 25 -b -nb #909090 -nf #303030`
|
||||||
|
# # `dmenu_command = fuzzel --dmenu`
|
||||||
|
rofi_highlight = True
|
||||||
|
compact = True
|
||||||
|
# pinentry = <Pinentry command> # (Default: None) e.g. `pinentry-gtk`
|
||||||
|
# wifi_chars = <string of 4 unicode characters representing 1-4 bars strength>
|
||||||
|
wifi_chars = ▂▄▆█
|
||||||
|
# wifi_icons = <characters representing signal strength as an icon>
|
||||||
|
wifi_icons =
|
||||||
|
# format = <Python style format string for the access point entries>
|
||||||
|
# # TODO: replace `{sec}` with a locked/unlocked icon
|
||||||
|
format = {icon} {name} [{signal}%%] [{sec}]
|
||||||
|
# # Available variables are:
|
||||||
|
# # * {name} - Access point name
|
||||||
|
# # * {sec} - Security type
|
||||||
|
# # * {signal} - Signal strength on a scale of 0-100
|
||||||
|
# # * {bars} - Bar-based display of signal strength (see wifi_chars)
|
||||||
|
# # * {icon} - Icon-based display of signal strength (see wifi_icons)
|
||||||
|
# # * {max_len_name} and {max_len_sec} are the maximum lengths of {name} / {sec}
|
||||||
|
# # respectively and may be useful for formatting.
|
||||||
|
# list_saved = <True or False> # (Default: False) list saved connections
|
||||||
|
|
||||||
|
[dmenu_passphrase]
|
||||||
|
# # Uses the -password flag for Rofi, -x for bemenu. For dmenu, sets -nb and
|
||||||
|
# # -nf to the same color or uses -P if the dmenu password patch is applied
|
||||||
|
# # https://tools.suckless.org/dmenu/patches/password/
|
||||||
|
# obscure = True
|
||||||
|
# obscure_color = #222222
|
||||||
|
|
||||||
|
[pinentry]
|
||||||
|
# description = <Pinentry description> (Default: Get network password)
|
||||||
|
# prompt = <Pinentry prompt> (Default: Password:)
|
||||||
|
|
||||||
|
[editor]
|
||||||
|
# terminal = <name of terminal program>
|
||||||
|
# gui_if_available = <True or False> (Default: True)
|
||||||
|
|
||||||
|
[nmdm]
|
||||||
|
# rescan_delay = <seconds> # (seconds to wait after a wifi rescan before redisplaying the results)
|
21
hosts/common/programs/networkmanager_dmenu/default.nix
Normal file
21
hosts/common/programs/networkmanager_dmenu/default.nix
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# source: <https://github.com/firecat53/networkmanager-dmenu>
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
sane.programs.networkmanager_dmenu = {
|
||||||
|
sandbox.method = "bwrap";
|
||||||
|
sandbox.isolatePids = false; #< so it can know that NetworkManager really is running... (?)
|
||||||
|
sandbox.whitelistDbus = [
|
||||||
|
"system"
|
||||||
|
];
|
||||||
|
sandbox.whitelistWayland = true;
|
||||||
|
sandbox.extraHomePaths = [
|
||||||
|
".cache/rofi"
|
||||||
|
".config/rofi"
|
||||||
|
];
|
||||||
|
suggestedPrograms = [
|
||||||
|
"pidof"
|
||||||
|
];
|
||||||
|
|
||||||
|
fs.".config/networkmanager-dmenu/config.ini".symlink.target = ./config.ini;
|
||||||
|
};
|
||||||
|
}
|
@@ -2,6 +2,9 @@
|
|||||||
{
|
{
|
||||||
sane.programs.nmcli = {
|
sane.programs.nmcli = {
|
||||||
packageUnwrapped = pkgs.networkmanager-split.nmcli;
|
packageUnwrapped = pkgs.networkmanager-split.nmcli;
|
||||||
# TODO: sandbox
|
sandbox.method = "bwrap";
|
||||||
|
sandbox.whitelistDbus = [
|
||||||
|
"system"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
7
hosts/common/programs/nwg-panel/common-settings.json
Normal file
7
hosts/common/programs/nwg-panel/common-settings.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"restart-on-display": true,
|
||||||
|
"restart-delay": 500,
|
||||||
|
"run-through-compositor": false,
|
||||||
|
"processes-background-only": true,
|
||||||
|
"processes-own-only": true
|
||||||
|
}
|
@@ -4,11 +4,14 @@
|
|||||||
# - add network/bluetooth indicator
|
# - add network/bluetooth indicator
|
||||||
# - <https://github.com/nwg-piotr/nwg-panel/issues/269>
|
# - <https://github.com/nwg-piotr/nwg-panel/issues/269>
|
||||||
# - add CPU/meminfo executor
|
# - add CPU/meminfo executor
|
||||||
# - use sane-sysinfo
|
# - use sane-sysload
|
||||||
{
|
{
|
||||||
components,
|
controlsSettingsComponents,
|
||||||
height,
|
height,
|
||||||
|
locker,
|
||||||
|
modulesRight,
|
||||||
playerctlChars,
|
playerctlChars,
|
||||||
|
mediaPrevNext,
|
||||||
windowIcon,
|
windowIcon,
|
||||||
windowTitle,
|
windowTitle,
|
||||||
workspaceHideEmpty,
|
workspaceHideEmpty,
|
||||||
@@ -49,9 +52,7 @@
|
|||||||
modules-center = [
|
modules-center = [
|
||||||
"clock"
|
"clock"
|
||||||
];
|
];
|
||||||
modules-right = [
|
modules-right = modulesRight;
|
||||||
"playerctl"
|
|
||||||
];
|
|
||||||
|
|
||||||
clock = {
|
clock = {
|
||||||
angle = 0.0;
|
angle = 0.0;
|
||||||
@@ -79,7 +80,7 @@
|
|||||||
battery-low-interval = 4; #< notify every N minutes when battery continues to remain low
|
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
|
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
|
# commands.battery = ""; #< optional action to perform when battery icon is clicked in the drop-down menu
|
||||||
components = components;
|
components = controlsSettingsComponents;
|
||||||
click-closes = false;
|
click-closes = false;
|
||||||
custom-items = [];
|
custom-items = [];
|
||||||
css-name = "controls-window";
|
css-name = "controls-window";
|
||||||
@@ -90,21 +91,20 @@
|
|||||||
menu.icon = "system-shutdown-symbolic";
|
menu.icon = "system-shutdown-symbolic";
|
||||||
menu.items = [
|
menu.items = [
|
||||||
{
|
{
|
||||||
# TODO: plumb through the configured locker instead of assuming `swaylock`
|
|
||||||
name = "Lock";
|
name = "Lock";
|
||||||
cmd = "swaylock -f -c 000000";
|
cmd = "s6-rc start ${locker}";
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "Logout";
|
|
||||||
cmd = "swaymsg exit";
|
|
||||||
}
|
}
|
||||||
|
# {
|
||||||
|
# name = "Logout";
|
||||||
|
# cmd = "swaymsg exit";
|
||||||
|
# }
|
||||||
{
|
{
|
||||||
name = "Reboot";
|
name = "Reboot";
|
||||||
cmd = "systemctl reboot";
|
cmd = "reboot";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
name = "Shutdown";
|
name = "Shutdown";
|
||||||
cmd = "systemctl -i poweroff";
|
cmd = "shutdown now";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
menu.name = "Exit";
|
menu.name = "Exit";
|
||||||
@@ -127,6 +127,23 @@
|
|||||||
interval = 2;
|
interval = 2;
|
||||||
label-css-name = "playerctl-label";
|
label-css-name = "playerctl-label";
|
||||||
scroll = false;
|
scroll = false;
|
||||||
|
show-cover = false; #< don't show the little music-note icon
|
||||||
|
show-previous = mediaPrevNext;
|
||||||
|
show-next = mediaPrevNext;
|
||||||
|
show-name = mediaPrevNext;
|
||||||
|
};
|
||||||
|
swaync = {
|
||||||
|
css-name = "swaync-label";
|
||||||
|
# interval = 1;
|
||||||
|
# icon-placement = "left";
|
||||||
|
# icon-size = 18;
|
||||||
|
# tooltip-text = "";
|
||||||
|
# on-left-click = "swaync-client -t";
|
||||||
|
# on-right-click = "";
|
||||||
|
# on-middle-click = "";
|
||||||
|
# on-scroll-up = "";
|
||||||
|
# on-scroll-down = "";
|
||||||
|
# always-show-icon = true;
|
||||||
};
|
};
|
||||||
sway-workspaces = {
|
sway-workspaces = {
|
||||||
angle = 0.0;
|
angle = 0.0;
|
||||||
@@ -143,6 +160,20 @@
|
|||||||
show-name = windowTitle;
|
show-name = windowTitle;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
executor-sysload = {
|
||||||
|
script = "sane-sysload {mem} {cpu}";
|
||||||
|
interval = 10;
|
||||||
|
css-name = "";
|
||||||
|
on-right-click = "";
|
||||||
|
icon-size = 16;
|
||||||
|
show-icon = false;
|
||||||
|
tooltip-text = "";
|
||||||
|
on-left-click = "";
|
||||||
|
on-middle-click = "";
|
||||||
|
on-scroll-up = "";
|
||||||
|
on-scroll-down = "";
|
||||||
|
};
|
||||||
|
|
||||||
# unused modules:
|
# unused modules:
|
||||||
brightness-slider = {};
|
brightness-slider = {};
|
||||||
dwl-tags = {};
|
dwl-tags = {};
|
||||||
|
@@ -23,7 +23,8 @@ in
|
|||||||
# what looks good:
|
# what looks good:
|
||||||
# - 15px on moby
|
# - 15px on moby
|
||||||
# - 24px on lappy
|
# - 24px on lappy
|
||||||
default = lib.min 24 (cfg.config.fontSize - 1);
|
# there's about 10px padding total around this (above + below)
|
||||||
|
default = lib.min 24 (cfg.config.height - 11);
|
||||||
};
|
};
|
||||||
fontSize = mkOption {
|
fontSize = mkOption {
|
||||||
type = types.int;
|
type = types.int;
|
||||||
@@ -36,10 +37,18 @@ in
|
|||||||
height of the top bar in px.
|
height of the top bar in px.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
locker = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = config.sane.programs.swayidle.config.actions.lock.service;
|
||||||
|
description = ''
|
||||||
|
s6 service to start which can lock the screen
|
||||||
|
'';
|
||||||
|
};
|
||||||
battery = mkEnableOption' true "display battery status";
|
battery = mkEnableOption' true "display battery status";
|
||||||
brightness = mkEnableOption' true "display backlight level and slider";
|
brightness = mkEnableOption' true "display backlight level and slider";
|
||||||
mediaTitle = mkEnableOption' true "display title of current song/media";
|
mediaTitle = mkEnableOption' true "display title of current song/media";
|
||||||
mediaPrevNext = mkEnableOption' true "display prev/next button in media";
|
mediaPrevNext = mkEnableOption' true "display prev/next button in media";
|
||||||
|
sysload = mkEnableOption' true "display system load info (cpu/memory)";
|
||||||
windowIcon = mkEnableOption' true "display icon of active window";
|
windowIcon = mkEnableOption' true "display icon of active window";
|
||||||
windowTitle = mkEnableOption' true "display title of active window";
|
windowTitle = mkEnableOption' true "display title of active window";
|
||||||
workspaceNumbers = mkOption {
|
workspaceNumbers = mkOption {
|
||||||
@@ -66,8 +75,16 @@ in
|
|||||||
# XXX(2024/06/13): wlr-randr does not cross compile
|
# XXX(2024/06/13): wlr-randr does not cross compile
|
||||||
wlr-randr = null; #< only used if not on sway/hyprland; or if using dwl
|
wlr-randr = null; #< only used if not on sway/hyprland; or if using dwl
|
||||||
}).overrideAttrs (base: {
|
}).overrideAttrs (base: {
|
||||||
patches = (base.patches or []) ++ lib.optionals (!cfg.config.mediaPrevNext) [
|
# patches = (base.patches or []) ++ lib.optionals (!cfg.config.mediaPrevNext) [
|
||||||
./playerctl-no-prev-next.diff
|
# ./playerctl-no-prev-next.diff
|
||||||
|
# ];
|
||||||
|
patches = (base.patches or []) ++ [
|
||||||
|
(pkgs.fetchpatch {
|
||||||
|
# upstreaming: <https://github.com/nwg-piotr/nwg-panel/pull/309>
|
||||||
|
url = "https://git.uninsane.org/colin/nwg-panel/commit/a714e4100c409feb02c454874d030d192bfb0ae5.patch";
|
||||||
|
name = "playerctl: add settings to control which elements are displayed";
|
||||||
|
hash = "sha256-OofS46wAI3EDE3JbYs/Nn+Vkw9TP1mwSFvk+vBERg2s=";
|
||||||
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
# - disable the drop-down chevron by the controls.
|
# - disable the drop-down chevron by the controls.
|
||||||
@@ -75,17 +92,22 @@ in
|
|||||||
# - disable brightness indicator for same reason.
|
# - disable brightness indicator for same reason.
|
||||||
# - *leave* the volume indicator: one *could* remove it, however on desko that would leave the controls pane empty
|
# - *leave* the volume indicator: one *could* remove it, however on desko that would leave the controls pane empty
|
||||||
# making the dropdown inaccessible
|
# making the dropdown inaccessible
|
||||||
|
# also, remove padding from the items. i can manage that in css and the python padding prevents that.
|
||||||
postPatch = (base.postPatch or "") + ''
|
postPatch = (base.postPatch or "") + ''
|
||||||
|
substituteInPlace nwg_panel/modules/controls.py --replace-fail \
|
||||||
|
'self.box.pack_start(box, False, False, 6)' \
|
||||||
|
'self.box.pack_start(box, False, False, 0)'
|
||||||
|
|
||||||
substituteInPlace nwg_panel/modules/controls.py --replace-fail \
|
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)' \
|
||||||
'# box.pack_start(self.pan_image, False, False, 4)'
|
'# box.pack_start(self.pan_image, False, False, 0)'
|
||||||
substituteInPlace nwg_panel/modules/controls.py --replace-fail \
|
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)' \
|
||||||
'# box.pack_start(self.bri_image, False, False, 4)'
|
'# box.pack_start(self.bri_image, False, False, 0)'
|
||||||
|
|
||||||
# substituteInPlace nwg_panel/modules/controls.py --replace-fail \
|
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)' \
|
||||||
# '# box.pack_start(self.vol_image, False, False, 4)'
|
'box.pack_start(self.vol_image, False, False, 0)'
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# XXX(2024/06/13) the bluetooth stuff doesn't cross compile, so disable it
|
# XXX(2024/06/13) the bluetooth stuff doesn't cross compile, so disable it
|
||||||
@@ -102,11 +124,12 @@ in
|
|||||||
src = ./style.css;
|
src = ./style.css;
|
||||||
inherit (cfg.config) fontSize clockFontSize;
|
inherit (cfg.config) fontSize clockFontSize;
|
||||||
};
|
};
|
||||||
|
fs.".config/nwg-panel/common-settings.json".symlink.target = ./common-settings.json;
|
||||||
fs.".config/nwg-panel/config".symlink.target = pkgs.writers.writeJSON "config" (import ./config.nix {
|
fs.".config/nwg-panel/config".symlink.target = pkgs.writers.writeJSON "config" (import ./config.nix {
|
||||||
inherit (cfg.config) height windowIcon windowTitle workspaceHideEmpty workspaceNumbers;
|
inherit (cfg.config) locker height mediaPrevNext windowIcon windowTitle workspaceHideEmpty workspaceNumbers;
|
||||||
# component order matters, mostly for the drop-down.
|
# component order matters, mostly for the drop-down.
|
||||||
# default for most tools (e.g. swaync) is brightness control above volume.
|
# default for most tools (e.g. swaync) is brightness control above volume.
|
||||||
components =
|
controlsSettingsComponents =
|
||||||
lib.optionals cfg.config.brightness [
|
lib.optionals cfg.config.brightness [
|
||||||
"brightness"
|
"brightness"
|
||||||
] ++ [
|
] ++ [
|
||||||
@@ -116,6 +139,11 @@ in
|
|||||||
"battery"
|
"battery"
|
||||||
]
|
]
|
||||||
;
|
;
|
||||||
|
modulesRight = [
|
||||||
|
"playerctl"
|
||||||
|
] ++ lib.optionals cfg.config.sysload [
|
||||||
|
"executor-sysload"
|
||||||
|
];
|
||||||
playerctlChars = if cfg.config.mediaTitle then 60 else 0;
|
playerctlChars = if cfg.config.mediaTitle then 60 else 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -1,8 +1,16 @@
|
|||||||
|
commit 7aa759990b38b09abf9010dfe58e4cbdc1493282 (HEAD -> dev-sane)
|
||||||
|
Author: Colin <colin@uninsane.org>
|
||||||
|
Date: 2024-06-15 21:41:46 +0000
|
||||||
|
|
||||||
|
playerctl: remove backward/forward/music-note icons
|
||||||
|
|
||||||
|
these aren't worth the space cost on narrow devices (moby)
|
||||||
|
|
||||||
diff --git a/nwg_panel/modules/playerctl.py b/nwg_panel/modules/playerctl.py
|
diff --git a/nwg_panel/modules/playerctl.py b/nwg_panel/modules/playerctl.py
|
||||||
index 9b53b4b..c4d96ae 100644
|
index ff48d4c..43ae221 100644
|
||||||
--- a/nwg_panel/modules/playerctl.py
|
--- a/nwg_panel/modules/playerctl.py
|
||||||
+++ b/nwg_panel/modules/playerctl.py
|
+++ b/nwg_panel/modules/playerctl.py
|
||||||
@@ -180,15 +180,6 @@ class Playerctl(Gtk.EventBox):
|
@@ -211,15 +211,6 @@ class Playerctl(Gtk.EventBox):
|
||||||
if self.settings["angle"] != 0.0:
|
if self.settings["angle"] != 0.0:
|
||||||
button_box.set_orientation(Gtk.Orientation.VERTICAL)
|
button_box.set_orientation(Gtk.Orientation.VERTICAL)
|
||||||
|
|
||||||
@@ -18,7 +26,7 @@ index 9b53b4b..c4d96ae 100644
|
|||||||
self.play_pause_btn = Gtk.Button()
|
self.play_pause_btn = Gtk.Button()
|
||||||
if self.settings["button-css-name"]:
|
if self.settings["button-css-name"]:
|
||||||
self.play_pause_btn.set_property("name", 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):
|
@@ -229,15 +220,6 @@ class Playerctl(Gtk.EventBox):
|
||||||
self.play_pause_btn.connect("clicked", self.launch, self.PlayerOps.PLAY_PAUSE)
|
self.play_pause_btn.connect("clicked", self.launch, self.PlayerOps.PLAY_PAUSE)
|
||||||
button_box.pack_start(self.play_pause_btn, False, False, 1)
|
button_box.pack_start(self.play_pause_btn, False, False, 1)
|
||||||
|
|
||||||
@@ -31,6 +39,21 @@ index 9b53b4b..c4d96ae 100644
|
|||||||
- btn.connect("clicked", self.launch, self.PlayerOps.NEXT)
|
- btn.connect("clicked", self.launch, self.PlayerOps.NEXT)
|
||||||
- button_box.pack_start(btn, False, False, 1)
|
- button_box.pack_start(btn, False, False, 1)
|
||||||
-
|
-
|
||||||
self.label = AutoScrollLabel(self.settings["scroll"],
|
self.num_players_lbl = Gtk.Label.new("")
|
||||||
self.settings["chars"],
|
if self.settings["label-css-name"]:
|
||||||
self.settings["interval"])
|
self.num_players_lbl.set_property("name", self.settings["label-css-name"])
|
||||||
|
@@ -257,13 +239,9 @@ class Playerctl(Gtk.EventBox):
|
||||||
|
self.box.pack_start(button_box, False, False, 2)
|
||||||
|
if self.settings["show-cover"]:
|
||||||
|
self.box.pack_start(self.cover_img, False, False, 0)
|
||||||
|
- self.box.pack_start(self.num_players_lbl, False, False, 0)
|
||||||
|
- self.box.pack_start(self.label, False, False, 5)
|
||||||
|
else:
|
||||||
|
if self.settings["show-cover"]:
|
||||||
|
self.box.pack_start(self.cover_img, False, False, 2)
|
||||||
|
- self.box.pack_start(self.num_players_lbl, False, False, 0)
|
||||||
|
- self.box.pack_start(self.label, False, False, 2)
|
||||||
|
self.box.pack_start(button_box, False, False, 10)
|
||||||
|
|
||||||
|
def launch(self, button, op):
|
||||||
|
|
||||||
|
@@ -20,35 +20,61 @@
|
|||||||
font-size: @fontSize@px;
|
font-size: @fontSize@px;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
|
||||||
margin: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#task-box {
|
|
||||||
padding-left: 4px;
|
|
||||||
padding-right: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#task-box-focused {
|
#task-box-focused {
|
||||||
background-color: @accent-g2;
|
background-color: @accent-g2;
|
||||||
padding-left: 4px;
|
|
||||||
padding-right: 4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#playerctl-button {
|
#playerctl-button {
|
||||||
background-color: rgba(0, 0, 0, 0.08);
|
background-color: rgba(0, 0, 0, 0.08);
|
||||||
background-image: none;
|
background-image: none;
|
||||||
border: none;
|
border: none;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
margin: -1;
|
/* remove the 1px gap between buttons, since that causes color stripes if the background is a different color */
|
||||||
|
margin-left: -1;
|
||||||
|
margin-right: -1;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
/* prevent the buttons from pushing the whole bar down */
|
||||||
|
padding-top: 0px;
|
||||||
|
padding-bottom: 0px;
|
||||||
|
margin-top: 0px;
|
||||||
|
margin-bottom: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#panel-top {
|
#panel-top {
|
||||||
background: @accent-g1;
|
background: @accent-g1;
|
||||||
color: @fg1;
|
color: @fg1;
|
||||||
}
|
}
|
||||||
|
/* fix up the top bar sections so that the clock can be centered, even without forcing it to take 1/3rd of the bar */
|
||||||
|
/* pair with `homogenous = false` in config. on overflow, the clock may be rendered on top of the left portion of the bar */
|
||||||
|
/* and the right portion of the bar will render on top of all */
|
||||||
|
#panel-top > box > box > box > #left-box {
|
||||||
|
margin-left: 0px;
|
||||||
|
margin-right: -16384px;
|
||||||
|
}
|
||||||
|
#panel-top > box > box > box > #center-box {
|
||||||
|
margin-left: 0px;
|
||||||
|
margin-right: 0px;
|
||||||
|
}
|
||||||
|
#panel-top > box > box > box > box {
|
||||||
|
/* this is the *parent* of #right-box, which is uniquely under an unnamed "helper box" */
|
||||||
|
/* i have to address this parent, because otherwise only the controls are visible and the executors (including playerctl) */
|
||||||
|
/* are packed in a fill mode that pushes them off the visible section of the bar */
|
||||||
|
margin-left: -16384px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#right-box > widget > * {
|
||||||
|
/* TODO: tune this for moby */
|
||||||
|
padding-right: 3px;
|
||||||
|
padding-left: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#swaync-label {
|
||||||
|
/* move the notification count closer to the bell icon */
|
||||||
|
margin-left: -3px;
|
||||||
|
/* TODO: this should be main font size -1 */
|
||||||
|
font-size: 14px;
|
||||||
|
color: @accent-r2;
|
||||||
|
}
|
||||||
|
|
||||||
/* increase the size of each workspace icon */
|
/* increase the size of each workspace icon */
|
||||||
#sway-workspaces-item > label {
|
#sway-workspaces-item > label {
|
||||||
|
45
hosts/common/programs/ols.nix
Normal file
45
hosts/common/programs/ols.nix
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
# OLS: Offline Location Service: <https://codeberg.org/tpikonen/ols>
|
||||||
|
# fields {wifi SSID,cell tower} -> lat/long queries from geoclue
|
||||||
|
# satisfies queries via https://wigle.net, by learning about map tiles
|
||||||
|
# and caching those on-disk so that repeat queries may be serviced offline.
|
||||||
|
#
|
||||||
|
# it listens on localhost:8088, and one can validate its operation with a query like (substitute macAddresses for something real):
|
||||||
|
# - WiFi: curl -d '{"wifiAccessPoints":[{"macAddress":"01:23:45:67:89:ab","signalStrength":-78},{"macAddress":"cd:ef:01:23:45:56","signalStrength":-76}]}' http://127.0.0.1:8088/v1/geolocate
|
||||||
|
# - Cell: curl -d '{"cellTowers":[{ "radioType": "lte", "mobileCountryCode": 310, "mobileNetworkCode": 260, "locationAreaCode": NNNNN, "cellId": MMMMMMMM }]}' http://127.0.0.1:8088/v1/geolocate
|
||||||
|
#
|
||||||
|
## wigle docs:
|
||||||
|
# - IRC: #wigle on WiGLE.net:6667
|
||||||
|
# - API: <https://api.wigle.net/swagger>
|
||||||
|
# API return codes:
|
||||||
|
# - 429: "too many queries today."
|
||||||
|
#
|
||||||
|
# rate limiting:
|
||||||
|
# - as a new user you'll be limited to something ridiculous like 5 queries per day.
|
||||||
|
# supposedly this improves "based on history and participation".
|
||||||
|
# - source: <https://api.wigle.net/swagger#/Network%20search%20and%20information%20tools/search_2>
|
||||||
|
# - "API for some functions is limited on a daily basis for all users for the time being, but if you'd like increased access, please email us (include your username and usecase) at WiGLE-admin@wigle.net."
|
||||||
|
# - source: <https://wigle.net/account>
|
||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
sane.programs.ols = {
|
||||||
|
packageUnwrapped = pkgs.python3Packages.ols;
|
||||||
|
|
||||||
|
fs.".config/ols/cell.db".symlink.target = pkgs.runCommandLocal "cell.db" {
|
||||||
|
nativeBuildInputs = [ pkgs.python3Packages.ols ];
|
||||||
|
} ''
|
||||||
|
cellid-ols-import -o "$out" "${pkgs.opencellid}"
|
||||||
|
'';
|
||||||
|
|
||||||
|
persist.byStore.private = [
|
||||||
|
".local/share/ols"
|
||||||
|
];
|
||||||
|
|
||||||
|
secrets.".config/ols/ols.toml" = ../../../secrets/common/ols.toml.bin;
|
||||||
|
|
||||||
|
services.ols = {
|
||||||
|
description = "ols: Offline Location Service";
|
||||||
|
command = "ols 2>&1"; # XXX: it logs to stderr, and my s6 infrastructure apparently doesn't handle that
|
||||||
|
partOf = [ "graphical-session" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
8
hosts/common/programs/pidof.nix
Normal file
8
hosts/common/programs/pidof.nix
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
sane.programs.pidof = {
|
||||||
|
packageUnwrapped = pkgs.linkIntoOwnPackage pkgs.procps "bin/pidof";
|
||||||
|
sandbox.method = "bwrap";
|
||||||
|
sandbox.isolatePids = false;
|
||||||
|
};
|
||||||
|
}
|
@@ -116,6 +116,7 @@ in
|
|||||||
|
|
||||||
fs.".config/rofi/config.rasi".symlink.target = ./config.rasi;
|
fs.".config/rofi/config.rasi".symlink.target = ./config.rasi;
|
||||||
fs."Apps".symlink.target = ".local/share/applications/rofi-applications.desktop";
|
fs."Apps".symlink.target = ".local/share/applications/rofi-applications.desktop";
|
||||||
|
fs."WiFi".symlink.target = ".local/share/applications/networkmanager_dmenu.desktop";
|
||||||
persist.byStore.cryptClearOnBoot = [
|
persist.byStore.cryptClearOnBoot = [
|
||||||
# this gets us a few things:
|
# this gets us a few things:
|
||||||
# - file browser remembers its last directory
|
# - file browser remembers its last directory
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{ ... }:
|
{ ... }:
|
||||||
{
|
{
|
||||||
sane.programs.sane-sysinfo = {
|
sane.programs.sane-sysload = {
|
||||||
sandbox.method = "bwrap";
|
sandbox.method = "bwrap";
|
||||||
sandbox.extraPaths = [
|
sandbox.extraPaths = [
|
||||||
"/sys/class/power_supply"
|
"/sys/class/power_supply"
|
@@ -44,19 +44,19 @@ in
|
|||||||
# XXX: /run/current-system symlink can't be cached without forcing regular mass rebuilds:
|
# XXX: /run/current-system symlink can't be cached without forcing regular mass rebuilds:
|
||||||
# mount it as if it were a directory instead.
|
# mount it as if it were a directory instead.
|
||||||
"/run/current-system" = "";
|
"/run/current-system" = "";
|
||||||
} // lib.optionalAttrs config.hardware.opengl.enable {
|
} // lib.optionalAttrs config.hardware.graphics.enable {
|
||||||
"/run/opengl-driver" = let
|
"/run/opengl-driver" = let
|
||||||
gl = config.hardware.opengl;
|
gl = config.hardware.graphics;
|
||||||
# from: <repo:nixos/nixpkgs:nixos/modules/hardware/opengl.nix>
|
# from: <repo:nixos/nixpkgs:nixos/modules/hardware/graphics.nix>
|
||||||
package = pkgs.buildEnv {
|
package = pkgs.buildEnv {
|
||||||
name = "opengl-drivers";
|
name = "opengl-drivers";
|
||||||
paths = [ gl.package ] ++ gl.extraPackages;
|
paths = [ gl.package ] ++ gl.extraPackages;
|
||||||
};
|
};
|
||||||
in "${package}";
|
in "${package}";
|
||||||
} // lib.optionalAttrs (config.hardware.opengl.enable && config.hardware.opengl.driSupport32Bit) {
|
} // lib.optionalAttrs (config.hardware.graphics.enable && config.hardware.graphics.enable32Bit) {
|
||||||
"/run/opengl-driver-32" = let
|
"/run/opengl-driver-32" = let
|
||||||
gl = config.hardware.opengl;
|
gl = config.hardware.graphics;
|
||||||
# from: <repo:nixos/nixpkgs:nixos/modules/hardware/opengl.nix>
|
# from: <repo:nixos/nixpkgs:nixos/modules/hardware/graphics.nix>
|
||||||
package = pkgs.buildEnv {
|
package = pkgs.buildEnv {
|
||||||
name = "opengl-drivers-32bit";
|
name = "opengl-drivers-32bit";
|
||||||
paths = [ gl.package32 ] ++ gl.extraPackages32;
|
paths = [ gl.package32 ] ++ gl.extraPackages32;
|
||||||
|
53
hosts/common/programs/satellite.nix
Normal file
53
hosts/common/programs/satellite.nix
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
# satellite-gtk: <https://codeberg.org/tpikonen/satellite>
|
||||||
|
# - presents GPS tracking *details* in a graphical way
|
||||||
|
# - shows which satellites are in view, their SNR, and the subset currently being used for triangulation
|
||||||
|
# - shows fix coordinates (time, lat, long, altitude, speed)
|
||||||
|
#
|
||||||
|
### how to read the bargraph (example):
|
||||||
|
#
|
||||||
|
# 14 | XXXXXXXXXXXXX 26
|
||||||
|
# 76 | =========== 23
|
||||||
|
# 15 | XXXXXXXX 16
|
||||||
|
# =
|
||||||
|
# +----------------|
|
||||||
|
# 0 30
|
||||||
|
#
|
||||||
|
# ^ this view means:
|
||||||
|
# - GPS is receiving from sats 14, 76, 15 (by PRN) -- this comes from GSGSV NMEA data (Satellites in-View)
|
||||||
|
# - sat 14 and 15 (shaded solid) are "active" -- this comes from GSGSA NMEA data ("Satellites Active")
|
||||||
|
# - i believe "active" means "this sat was used in the most recent solution"
|
||||||
|
#
|
||||||
|
### text fields
|
||||||
|
# - Modes (GP,GL,GA) ...
|
||||||
|
# one letter each, indicating the mode for GPS, GLONASS, Galileo sats:
|
||||||
|
# - N = no fix
|
||||||
|
# - A = autonomous
|
||||||
|
# - D = differential mode
|
||||||
|
# - E = estimated (dead reckoning)
|
||||||
|
# - etc
|
||||||
|
# - Active / in use sats
|
||||||
|
# - A/U, where A = number of satellites used in the previous fix,
|
||||||
|
# U = number of satellites mentioned in latest GNS + GGA messages
|
||||||
|
# - Receiving sats
|
||||||
|
# shows the count of sats with non-zero SNR, from GSV messages
|
||||||
|
# - Visible sats
|
||||||
|
# shows the count of sats from GSV messages
|
||||||
|
# - Age of update / fix
|
||||||
|
# - Sys. Time
|
||||||
|
# - Latitude
|
||||||
|
# - Longitude
|
||||||
|
# - Altitude
|
||||||
|
# - Geoidal separation
|
||||||
|
# - Speed
|
||||||
|
# - True Course
|
||||||
|
# - PDOP/HDOP/VDOP
|
||||||
|
# - shows how sensitive the reported location is to measurement error (low values are better)
|
||||||
|
# - HDOP = horizontal sensitivity, VDOP = vertical sensitivity, PDOP = positional (d) sensitivity
|
||||||
|
# - 1-2 => excellent fix
|
||||||
|
# - >10 => low confidence fix; recommended to discard the fix
|
||||||
|
# - <https://en.wikipedia.org/wiki/Dilution_of_precision_(navigation)>
|
||||||
|
#
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
sane.programs.satellite = {};
|
||||||
|
}
|
@@ -148,6 +148,7 @@ in
|
|||||||
"fontconfig"
|
"fontconfig"
|
||||||
# "gnome.gnome-bluetooth" # XXX(2023/05/14): broken
|
# "gnome.gnome-bluetooth" # XXX(2023/05/14): broken
|
||||||
# "gnome.gnome-control-center" # XXX(2023/06/28): depends on webkitgtk4_1
|
# "gnome.gnome-control-center" # XXX(2023/06/28): depends on webkitgtk4_1
|
||||||
|
"networkmanager_dmenu"
|
||||||
"nwg-panel"
|
"nwg-panel"
|
||||||
"pipewire"
|
"pipewire"
|
||||||
"playerctl" # for waybar & particularly to have playerctld running
|
"playerctl" # for waybar & particularly to have playerctld running
|
||||||
@@ -163,7 +164,7 @@ in
|
|||||||
"swayidle" # enable if you need it
|
"swayidle" # enable if you need it
|
||||||
"swaynotificationcenter" # notification daemon
|
"swaynotificationcenter" # notification daemon
|
||||||
"switchboard" # network/bluetooth/sound control panel
|
"switchboard" # network/bluetooth/sound control panel
|
||||||
"sysvol" # volume notifier
|
"syshud" # volume notifier
|
||||||
"unl0kr" # greeter
|
"unl0kr" # greeter
|
||||||
# "waybar"
|
# "waybar"
|
||||||
"wdisplays" # like xrandr
|
"wdisplays" # like xrandr
|
||||||
@@ -198,6 +199,7 @@ in
|
|||||||
sandbox.whitelistAudio = true; # it runs playerctl directly
|
sandbox.whitelistAudio = true; # it runs playerctl directly
|
||||||
sandbox.whitelistDbus = [ "system" "user" ]; # to e.g. launch apps
|
sandbox.whitelistDbus = [ "system" "user" ]; # to e.g. launch apps
|
||||||
sandbox.whitelistDri = true;
|
sandbox.whitelistDri = true;
|
||||||
|
sandbox.whitelistS6 = true; #< for Super+L to start the screen locker service
|
||||||
sandbox.whitelistX = true; # sway invokes xwayland itself
|
sandbox.whitelistX = true; # sway invokes xwayland itself
|
||||||
sandbox.whitelistWayland = true;
|
sandbox.whitelistWayland = true;
|
||||||
sandbox.extraRuntimePaths = [
|
sandbox.extraRuntimePaths = [
|
||||||
@@ -227,7 +229,7 @@ in
|
|||||||
'';
|
'';
|
||||||
|
|
||||||
fs.".config/sway/config".symlink.target = pkgs.substituteAll {
|
fs.".config/sway/config".symlink.target = pkgs.substituteAll {
|
||||||
src = ./sway-config;
|
src = ./config;
|
||||||
inherit (cfg.config)
|
inherit (cfg.config)
|
||||||
extra_lines
|
extra_lines
|
||||||
font
|
font
|
||||||
|
@@ -32,6 +32,7 @@ in
|
|||||||
};
|
};
|
||||||
sandbox.method = "bwrap";
|
sandbox.method = "bwrap";
|
||||||
sandbox.whitelistS6 = true;
|
sandbox.whitelistS6 = true;
|
||||||
|
sandbox.isolatePids = false; #< XXX: not sure why, but swaync segfaults under load without this!
|
||||||
};
|
};
|
||||||
|
|
||||||
sane.programs.swaync-fbcli = {
|
sane.programs.swaync-fbcli = {
|
||||||
@@ -61,6 +62,8 @@ in
|
|||||||
name of entry in /sys/class/backlight which indicates the primary backlight.
|
name of entry in /sys/class/backlight which indicates the primary backlight.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
enableBacklight = mkEnableOption "include a backlight slider in the swaync dropdown (requires an active session with systemd-logind)";
|
||||||
|
enableMpris = (mkEnableOption "show the currently playing media in the swaync dropdown, and navigation buttons") // { default = true; };
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
default = {};
|
default = {};
|
||||||
@@ -116,27 +119,14 @@ in
|
|||||||
env.GNOTIFICATION_BACKEND = "freedesktop";
|
env.GNOTIFICATION_BACKEND = "freedesktop";
|
||||||
|
|
||||||
fs.".config/swaync/style.css".symlink.target = ./style.css;
|
fs.".config/swaync/style.css".symlink.target = ./style.css;
|
||||||
fs.".config/swaync/config.json".symlink.text = builtins.toJSON {
|
fs.".config/swaync/config.json".symlink.target = pkgs.writers.writeJSON "config.json" {
|
||||||
"$schema" = "/etc/xdg/swaync/configSchema.json";
|
"$schema" = "/etc/xdg/swaync/configSchema.json";
|
||||||
positionX = "right";
|
control-center-height = 600;
|
||||||
positionY = "top";
|
|
||||||
layer = "overlay";
|
|
||||||
control-center-layer = "top";
|
control-center-layer = "top";
|
||||||
layer-shell = true;
|
|
||||||
cssPriority = "user"; # "application"|"user". "user" in order to override the system gtk theme.
|
|
||||||
control-center-margin-top = 0;
|
|
||||||
control-center-margin-bottom = 0;
|
control-center-margin-bottom = 0;
|
||||||
control-center-margin-right = 0;
|
|
||||||
control-center-margin-left = 0;
|
control-center-margin-left = 0;
|
||||||
notification-2fa-action = true;
|
control-center-margin-right = 0;
|
||||||
notification-inline-replies = false;
|
control-center-margin-top = 0;
|
||||||
notification-icon-size = 64;
|
|
||||||
notification-body-image-height = 100;
|
|
||||||
notification-body-image-width = 200;
|
|
||||||
timeout = 30;
|
|
||||||
timeout-low = 5;
|
|
||||||
timeout-critical = 0;
|
|
||||||
fit-to-screen = true; #< have notification center take full vertical screen space
|
|
||||||
# control-center-width:
|
# control-center-width:
|
||||||
# pinephone native display is 720 x 1440
|
# pinephone native display is 720 x 1440
|
||||||
# - for compositor scale=2.0 => 360
|
# - for compositor scale=2.0 => 360
|
||||||
@@ -144,14 +134,28 @@ in
|
|||||||
# - for compositor scale=1.6 => 450
|
# - for compositor scale=1.6 => 450
|
||||||
# if it's set to something wider than the screen, then it overflows and items aren't visible.
|
# if it's set to something wider than the screen, then it overflows and items aren't visible.
|
||||||
control-center-width = 360;
|
control-center-width = 360;
|
||||||
control-center-height = 600;
|
cssPriority = "user"; # "application"|"user". "user" in order to override the system gtk theme.
|
||||||
notification-window-width = 360;
|
fit-to-screen = true; #< have notification center take full vertical screen space
|
||||||
keyboard-shortcuts = true;
|
|
||||||
image-visibility = "when-available";
|
|
||||||
transition-time = 100;
|
|
||||||
hide-on-clear = true; #< hide control center when clicking "clear all"
|
|
||||||
hide-on-action = true;
|
hide-on-action = true;
|
||||||
|
hide-on-clear = true; #< hide control center when clicking "clear all"
|
||||||
|
image-visibility = "when-available";
|
||||||
|
keyboard-shortcuts = true;
|
||||||
|
layer = "overlay";
|
||||||
|
layer-shell = true;
|
||||||
|
notification-2fa-action = true;
|
||||||
|
notification-body-image-height = 100;
|
||||||
|
notification-body-image-width = 200;
|
||||||
|
notification-icon-size = 64;
|
||||||
|
notification-inline-replies = false;
|
||||||
|
notification-window-width = 360;
|
||||||
|
positionX = "right";
|
||||||
|
positionY = "top";
|
||||||
script-fail-notify = true;
|
script-fail-notify = true;
|
||||||
|
timeout = 30;
|
||||||
|
timeout-critical = 0;
|
||||||
|
timeout-low = 5;
|
||||||
|
transition-time = 100;
|
||||||
|
|
||||||
inherit scripts;
|
inherit scripts;
|
||||||
widgets = [
|
widgets = [
|
||||||
# what to show in the notification center (and in which order).
|
# what to show in the notification center (and in which order).
|
||||||
@@ -164,9 +168,13 @@ in
|
|||||||
"dnd"
|
"dnd"
|
||||||
"inhibitors"
|
"inhibitors"
|
||||||
"buttons-grid"
|
"buttons-grid"
|
||||||
|
] ++ lib.optionals cfg.config.enableBacklight [
|
||||||
"backlight"
|
"backlight"
|
||||||
|
] ++ [
|
||||||
"volume"
|
"volume"
|
||||||
|
] ++ lib.optionals cfg.config.enableMpris [
|
||||||
"mpris"
|
"mpris"
|
||||||
|
] ++ [
|
||||||
"notifications"
|
"notifications"
|
||||||
];
|
];
|
||||||
widget-config = {
|
widget-config = {
|
||||||
@@ -228,7 +236,10 @@ in
|
|||||||
depends = [ "sound" ]; #< TODO: else it will NEVER see the pulse socket in its sandbox
|
depends = [ "sound" ]; #< TODO: else it will NEVER see the pulse socket in its sandbox
|
||||||
partOf = [ "graphical-session" ];
|
partOf = [ "graphical-session" ];
|
||||||
|
|
||||||
command = "env G_MESSAGES_DEBUG=all swaync";
|
# N.B.: G_MESSAGES_DEBUG=all breaks DND mode:
|
||||||
|
# messages are still hidden, but are not silent!
|
||||||
|
# command = "env G_MESSAGES_DEBUG=all SWAYNC_DEBUG=1 swaync";
|
||||||
|
command = "swaync";
|
||||||
readiness.waitDbus = "org.freedesktop.Notifications";
|
readiness.waitDbus = "org.freedesktop.Notifications";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@@ -24,7 +24,7 @@
|
|||||||
# - SWAYNC_SUMMARY
|
# - SWAYNC_SUMMARY
|
||||||
|
|
||||||
# rules to use for testing. trigger with:
|
# rules to use for testing. trigger with:
|
||||||
# - `notify-send --app-id=foo subject body` (etc)
|
# - `notify-send --app-name=foo subject body` (etc)
|
||||||
# should also be possible to trigger via any messaging app
|
# should also be possible to trigger via any messaging app
|
||||||
fbcli-test-im = {
|
fbcli-test-im = {
|
||||||
body = "test:message";
|
body = "test:message";
|
||||||
|
@@ -17,7 +17,12 @@ log() {
|
|||||||
checkActive() {
|
checkActive() {
|
||||||
# simulate a dry-run start. if no actions would be performed, then the service is up.
|
# simulate a dry-run start. if no actions would be performed, then the service is up.
|
||||||
# alternative is s6-svstat, but that doesn't support oneshots
|
# alternative is s6-svstat, but that doesn't support oneshots
|
||||||
test -z "$(s6-rc -n 0 -b start "$service")" && echo true || echo false
|
local s6Output=$(s6-rc -n 0 -b start "$service")
|
||||||
|
if [ -z "$s6Output" ]; then
|
||||||
|
echo true
|
||||||
|
else
|
||||||
|
echo false
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
startService() {
|
startService() {
|
||||||
log "startService: $service"
|
log "startService: $service"
|
||||||
|
@@ -1,3 +1,6 @@
|
|||||||
|
# BUGS
|
||||||
|
# - switchboard-plug-sound errors because
|
||||||
|
# GLib-GIO-ERROR **: Settings schema 'org.gnome.settings-daemon.plugins.media-keys' is not installed
|
||||||
{ pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
{
|
{
|
||||||
sane.programs.switchboard = {
|
sane.programs.switchboard = {
|
||||||
@@ -24,5 +27,9 @@
|
|||||||
];
|
];
|
||||||
xorg = pkgs.buildPackages.xorg; #< cross compilation fix (TODO: upstream)
|
xorg = pkgs.buildPackages.xorg; #< cross compilation fix (TODO: upstream)
|
||||||
};
|
};
|
||||||
|
sandbox.method = "bwrap";
|
||||||
|
sandbox.whitelistWayland = true;
|
||||||
|
sandbox.whitelistDbus = [ "system" ]; #< to speak with NetworkManager
|
||||||
|
sandbox.whitelistAudio = true; #< even with this, the sound plugin doesn't seem to work...
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -1,11 +1,15 @@
|
|||||||
{ ... }:
|
{ ... }:
|
||||||
{
|
{
|
||||||
sane.programs.sysvol = {
|
sane.programs.syshud = {
|
||||||
sandbox.method = "bwrap";
|
sandbox.method = "bwrap";
|
||||||
sandbox.whitelistAudio = true;
|
sandbox.whitelistAudio = true;
|
||||||
sandbox.whitelistWayland = true;
|
sandbox.whitelistWayland = true;
|
||||||
|
sandbox.extraPaths = [
|
||||||
|
"/sys/class/backlight" #< crashes if unable to access this directory
|
||||||
|
# "/sys/devices" #< only if you want it to actually show when the backlight changes
|
||||||
|
];
|
||||||
|
|
||||||
fs.".config/sys64/volume.css".symlink.text = ''
|
fs.".config/sys64/hud.css".symlink.text = ''
|
||||||
window {
|
window {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
@@ -53,8 +57,8 @@
|
|||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
services."sysvol" = {
|
services."syshud" = {
|
||||||
description = "sysvol: volume monitor/notifier";
|
description = "syshud: volume monitor/notifier";
|
||||||
depends = [ "sound" ]; #< specifically wireplumber-pulse
|
depends = [ "sound" ]; #< specifically wireplumber-pulse
|
||||||
partOf = [ "graphical-session" ];
|
partOf = [ "graphical-session" ];
|
||||||
|
|
||||||
@@ -67,7 +71,7 @@
|
|||||||
# -{H,W} N to set the height/width of the notifier, in px.
|
# -{H,W} N to set the height/width of the notifier, in px.
|
||||||
# -i N to set the size of the volume icon
|
# -i N to set the size of the volume icon
|
||||||
# -P to hide percentage text
|
# -P to hide percentage text
|
||||||
command = "sysvol -p top -t 1 -T 0 -m 22 -H 39 -W 256 -i 32 -P";
|
command = "syshud -p top -t 1 -T 0 -m 22 -H 39 -W 256 -i 32 -P";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
11
hosts/common/programs/where-am-i.nix
Normal file
11
hosts/common/programs/where-am-i.nix
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{ config, pkgs, ... }:
|
||||||
|
{
|
||||||
|
sane.programs.where-am-i = {
|
||||||
|
# packageUnwrapped = pkgs.linkIntoOwnPackage config.sane.programs.geoclue2.packageUnwrapped "libexec/geoclue-2.0/demos/where-am-i";
|
||||||
|
packageUnwrapped = pkgs.linkFarm "where-am-i" [{
|
||||||
|
# bring the `where-am-i` tool into a `bin/` directory so it can be invokable via PATH
|
||||||
|
name = "bin/where-am-i";
|
||||||
|
path = "${config.sane.programs.geoclue2.packageUnwrapped}/libexec/geoclue-2.0/demos/where-am-i";
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
}
|
@@ -1,13 +1,17 @@
|
|||||||
{ config, lib, sane-lib, ... }:
|
{ config, lib, sane-lib, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
keysForHost = hostName: let
|
hostKeys = lib.mapAttrsToList
|
||||||
hostCfg = config.sane.hosts.by-name."${hostName}";
|
(hostName: hostCfg:
|
||||||
in {
|
# generate `root@servo`, `colin@servo`, `root@servo-hn`, `colin@servo-hn`, ... as a single attrset:
|
||||||
"root@${hostName}" = hostCfg.ssh.host_pubkey;
|
lib.foldl' (acc: alias: acc // {
|
||||||
"colin@${hostName}" = lib.mkIf (hostCfg.ssh.user_pubkey != null && hostCfg.ssh.authorized) hostCfg.ssh.user_pubkey;
|
"root@${alias}" = hostCfg.ssh.host_pubkey;
|
||||||
};
|
"colin@${alias}" = lib.mkIf (hostCfg.ssh.user_pubkey != null && hostCfg.ssh.authorized) hostCfg.ssh.user_pubkey;
|
||||||
hostKeys = builtins.map keysForHost (builtins.attrNames config.sane.hosts.by-name);
|
})
|
||||||
|
{}
|
||||||
|
hostCfg.names
|
||||||
|
)
|
||||||
|
config.sane.hosts.by-name;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
sane.ssh.pubkeys = lib.mkMerge (hostKeys ++ [
|
sane.ssh.pubkeys = lib.mkMerge (hostKeys ++ [
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
# trampoline from flake.nix into the specific host definition, while doing a tiny bit of common setup
|
# trampoline from flake.nix into the specific host definition, while doing a tiny bit of common setup
|
||||||
|
|
||||||
# args from flake-level `import`
|
# args from flake-level `import`
|
||||||
{ hostName }:
|
{ hostName, variant }:
|
||||||
|
|
||||||
# module args
|
# module args
|
||||||
{ ... }:
|
{ lib, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
@@ -14,4 +14,14 @@
|
|||||||
];
|
];
|
||||||
|
|
||||||
networking.hostName = hostName;
|
networking.hostName = hostName;
|
||||||
|
system.name = if variant == null then
|
||||||
|
hostName
|
||||||
|
else
|
||||||
|
"${hostName}-${variant}"
|
||||||
|
;
|
||||||
|
|
||||||
|
sane = lib.mkMerge [
|
||||||
|
(lib.mkIf (variant == "min") { maxBuildCost = 0; })
|
||||||
|
(lib.mkIf (variant == "light") { maxBuildCost = 2; })
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
@@ -45,6 +45,9 @@
|
|||||||
actions.screenoff.delay = 300;
|
actions.screenoff.delay = 300;
|
||||||
actions.screenoff.enable = true;
|
actions.screenoff.enable = true;
|
||||||
};
|
};
|
||||||
|
sane.programs.swaynotificationcenter.config = {
|
||||||
|
enableMpris = false; #< consumes too much screen real-estate
|
||||||
|
};
|
||||||
|
|
||||||
sane.programs.waybar.config = {
|
sane.programs.waybar.config = {
|
||||||
fontSize = 14;
|
fontSize = 14;
|
||||||
@@ -63,6 +66,7 @@
|
|||||||
windowTitle = false;
|
windowTitle = false;
|
||||||
mediaPrevNext = false;
|
mediaPrevNext = false;
|
||||||
mediaTitle = false;
|
mediaTitle = false;
|
||||||
|
sysload = false;
|
||||||
workspaceNumbers = [ "1" "2" "3" "4" "5" ];
|
workspaceNumbers = [ "1" "2" "3" "4" "5" ];
|
||||||
workspaceHideEmpty = false;
|
workspaceHideEmpty = false;
|
||||||
};
|
};
|
||||||
|
@@ -80,6 +80,7 @@ in
|
|||||||
protocol = [ "udp" ];
|
protocol = [ "udp" ];
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
visibleTo.wan = cfg.visibleToWan;
|
visibleTo.wan = cfg.visibleToWan;
|
||||||
|
visibleTo.doof = cfg.visibleToWan;
|
||||||
description = "colin-wireguard";
|
description = "colin-wireguard";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
62
impure.nix
Normal file
62
impure.nix
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# this entry-point exposes all packages, hosts, etc, but with no purity guarnatees.
|
||||||
|
# the intended way to use this is to first copy every .nix file and dependency in this repo to the nix store, then enter this file.
|
||||||
|
# entering this file *before* copying anything into the nix store can cause interesting
|
||||||
|
# race conditions or eval failures.
|
||||||
|
#
|
||||||
|
# see default.nix for a wrapper around this with better purity guarantees.
|
||||||
|
{ }:
|
||||||
|
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 (
|
||||||
|
[
|
||||||
|
(import ./hosts/instantiate.nix { hostName = name; inherit variant; })
|
||||||
|
(import ./modules)
|
||||||
|
pkgs.sops-nix.nixosModules.sops
|
||||||
|
]
|
||||||
|
);
|
||||||
|
mkFlavoredHost = args: let
|
||||||
|
host = evalHost args;
|
||||||
|
# expose the toplevel nixos system as the toplevel attribute itself,
|
||||||
|
# with nested aliases for other common build targets
|
||||||
|
in host.config.system.build.toplevel.overrideAttrs (base: {
|
||||||
|
passthru = (base.passthru or {}) // {
|
||||||
|
config = host.config;
|
||||||
|
fs = host.config.sane.fs;
|
||||||
|
img = host.config.system.build.img;
|
||||||
|
pkgs = host.config.system.build.pkgs;
|
||||||
|
programs = lib.mapAttrs (_: p: p.package) host.config.sane.programs;
|
||||||
|
toplevel = host.config.system.build.toplevel; #< self
|
||||||
|
};
|
||||||
|
});
|
||||||
|
mkHost = args: {
|
||||||
|
# TODO: swap order: $host-{next,staging}-{min,light}:
|
||||||
|
# then lexicographically-adjacent targets would also have the minimal difference in closure,
|
||||||
|
# and the order in which each target should be built is more evident
|
||||||
|
"${args.name}" = mkFlavoredHost args;
|
||||||
|
"${args.name}-next" = mkFlavoredHost (args // { branch = "staging-next"; });
|
||||||
|
"${args.name}-staging" = mkFlavoredHost (args // { branch = "staging"; });
|
||||||
|
"${args.name}-light" = mkFlavoredHost (args // { variant = "light"; });
|
||||||
|
"${args.name}-light-next" = mkFlavoredHost (args // { variant = "light"; branch = "staging-next"; });
|
||||||
|
"${args.name}-light-staging" = mkFlavoredHost (args // { variant = "light"; branch = "staging"; });
|
||||||
|
"${args.name}-min" = mkFlavoredHost (args // { variant = "min"; });
|
||||||
|
"${args.name}-min-next" = mkFlavoredHost (args // { variant = "min"; branch = "staging-next"; });
|
||||||
|
"${args.name}-min-staging" = mkFlavoredHost (args // { variant = "min"; branch = "staging-staging"; });
|
||||||
|
};
|
||||||
|
|
||||||
|
hosts = lib.foldl' (acc: host: acc // (mkHost host)) {} [
|
||||||
|
{ name = "crappy"; system = "armv7l-linux"; }
|
||||||
|
{ name = "desko"; system = "x86_64-linux"; }
|
||||||
|
{ name = "lappy"; system = "x86_64-linux"; }
|
||||||
|
{ name = "moby"; system = "aarch64-linux"; }
|
||||||
|
{ name = "rescue"; system = "x86_64-linux"; }
|
||||||
|
{ name = "servo"; system = "x86_64-linux"; }
|
||||||
|
];
|
||||||
|
in {
|
||||||
|
inherit hosts;
|
||||||
|
} // (mkPkgs {})
|
5
integrations/nix-update/default.nix
Normal file
5
integrations/nix-update/default.nix
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# this is the entry point for `nix-update`, used when i update the packages in this repo.
|
||||||
|
# nix-update needs to work on the actual out-of-store source,
|
||||||
|
# which means it can't call through the hermetic `default.nix` at the top of this repo,
|
||||||
|
# but rather needs the in-place `impure.nix` entry point.
|
||||||
|
import ../../impure.nix
|
@@ -26,9 +26,10 @@ let
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
mkNetNsConfig = name: opts: with opts; {
|
mkNetNsConfig = name: opts: with opts; {
|
||||||
networking.localCommands = let
|
systemd.services."netns-${name}" = let
|
||||||
iptables = "${pkgs.iptables}/bin/iptables";
|
ip = lib.getExe' pkgs.iproute2 "ip";
|
||||||
in-ns = "ip netns exec ${name}";
|
iptables = lib.getExe pkgs.iptables;
|
||||||
|
in-ns = "${ip} netns exec ${name}";
|
||||||
bridgePort = port: proto: ''
|
bridgePort = port: proto: ''
|
||||||
${in-ns} ${iptables} -A PREROUTING -t nat -p ${proto} --dport ${port} -m iprange --dst-range ${netnsPubIpv4} \
|
${in-ns} ${iptables} -A PREROUTING -t nat -p ${proto} --dport ${port} -m iprange --dst-range ${netnsPubIpv4} \
|
||||||
-j DNAT --to-destination ${hostVethIpv4}
|
-j DNAT --to-destination ${hostVethIpv4}
|
||||||
@@ -41,55 +42,61 @@ let
|
|||||||
config.sane.ports.ports
|
config.sane.ports.ports
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
in ''
|
in {
|
||||||
ip netns add ${name} || (test -e /run/netns/${name} && echo "${name} already exists")
|
description = "create a network namespace which will selectively bridge traffic with the init namespace";
|
||||||
|
# specifically, we need to set these up before wireguard-wg-*,
|
||||||
|
wantedBy = [ "network-pre.target" ];
|
||||||
|
before = [ "network-pre.target" ];
|
||||||
|
serviceConfig.Type = "oneshot";
|
||||||
|
serviceConfig.RemainAfterExit = true;
|
||||||
|
script = ''
|
||||||
|
${ip} netns add ${name} || (test -e /run/netns/${name} && echo "${name} already exists")
|
||||||
# DOCS:
|
# DOCS:
|
||||||
# - some of this approach is described here: <https://josephmuia.ca/2018-05-16-net-namespaces-veth-nat/>
|
# - some of this approach is described here: <https://josephmuia.ca/2018-05-16-net-namespaces-veth-nat/>
|
||||||
# - iptables primer: <https://danielmiessler.com/study/iptables/>
|
# - iptables primer: <https://danielmiessler.com/study/iptables/>
|
||||||
# create veth pair
|
# create veth pair
|
||||||
ip link add ${name}-veth-a type veth peer name ${name}-veth-b || echo "${name}-veth-{a,b} aleady exists"
|
${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} addr add ${hostVethIpv4}/24 dev ${name}-veth-a || echo "${name}-veth-a aleady has IP address"
|
||||||
ip link set ${name}-veth-a up
|
${ip} link set ${name}-veth-a up
|
||||||
|
|
||||||
# move veth-b into the namespace
|
# move veth-b into the namespace
|
||||||
ip link set ${name}-veth-b netns ${name} || echo "${name}-veth-b was already moved into its netns"
|
${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} 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
|
${in-ns} ${ip} link set ${name}-veth-b up
|
||||||
|
|
||||||
# make it so traffic originating from the host side of the veth
|
# make it so traffic originating from the host side of the veth
|
||||||
# is sent over the veth no matter its destination.
|
# 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)"
|
${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
|
# for traffic originating at the host veth to the WAN, use the veth as our gateway
|
||||||
# not sure if the metric 1002 matters.
|
# 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} || \
|
${ip} route add default via ${netnsVethIpv4} dev ${name}-veth-a proto kernel src ${hostVethIpv4} metric 1002 table ${name} || \
|
||||||
echo "${name} already has default route"
|
echo "${name} already has default route"
|
||||||
# give the default route lower priority
|
# 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 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)"
|
${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
|
# 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.
|
# - 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 \
|
${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
|
-j DNAT --to-destination ${dns}:53
|
||||||
'' + (lib.concatStringsSep "\n" bridgeStatements);
|
'' + (lib.concatStringsSep "\n" bridgeStatements);
|
||||||
|
preStop = ''
|
||||||
|
${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 ${hostVethIpv4} lookup ${name} pref 50 || echo "couldn't delete init -> ${name} rule"
|
||||||
|
${ip} route del default via ${netnsVethIpv4} dev ${name}-veth-a proto kernel src ${hostVethIpv4} metric 1002 table ${name} || echo "couldn't delete init > ${name} route"
|
||||||
|
# FIXME: if there are other net namespaces active, changing the prefs here may break those!
|
||||||
|
${ip} rule add from all lookup local pref 0
|
||||||
|
${ip} rule del from all lookup local pref 100
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
# postShutdown = ''
|
# for some reason network-pre doesn't actually get run before network.target by default??
|
||||||
# ${in-ns} ip link del ${name}-veth-b || echo "couldn't delete ${name}-veth-b"
|
systemd.targets.network-pre.wantedBy = [ "network.target" ];
|
||||||
# ip link del ${name}-veth-a || echo "couldn't delete ${name}-veth-a"
|
systemd.targets.network-pre.before = [ "network.target" ];
|
||||||
# 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
|
# 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.
|
# through the wireguard namespaces, and to the WAN via VPN.
|
||||||
@@ -114,7 +121,8 @@ in
|
|||||||
networking.localCommands = f.networking.localCommands;
|
networking.localCommands = f.networking.localCommands;
|
||||||
networking.iproute2.rttablesExtraConfig = f.networking.iproute2.rttablesExtraConfig;
|
networking.iproute2.rttablesExtraConfig = f.networking.iproute2.rttablesExtraConfig;
|
||||||
networking.iproute2.enable = f.networking.iproute2.enable;
|
networking.iproute2.enable = f.networking.iproute2.enable;
|
||||||
systemd.services.network-local-commands = f.systemd.services.network-local-commands;
|
systemd.services = f.systemd.services;
|
||||||
|
systemd.targets.network-pre = f.systemd.targets.network-pre;
|
||||||
};
|
};
|
||||||
in take (sane-lib.mkTypedMerge take configs);
|
in take (sane-lib.mkTypedMerge take configs);
|
||||||
}
|
}
|
||||||
|
@@ -96,7 +96,13 @@ let
|
|||||||
} // extraConfig
|
} // extraConfig
|
||||||
);
|
);
|
||||||
configPath = "/var/lib/trust-dns/${flavor}-config.toml";
|
configPath = "/var/lib/trust-dns/${flavor}-config.toml";
|
||||||
sedArgs = lib.mapAttrsToList (key: value: ''-e "s/${key}/${value}/g"'') substitutions;
|
sedArgs = builtins.map (key: ''-e "s/${key}/${substitutions."${key}"}/g"'') (
|
||||||
|
# HACK: %ANATIVE% often expands to one of the other subtitutions (e.g. %AWAN%)
|
||||||
|
# so we must expand it *first*.
|
||||||
|
lib.sortOn
|
||||||
|
(k: if k == "%ANATIVE%" then 0 else 1)
|
||||||
|
(builtins.attrNames substitutions)
|
||||||
|
);
|
||||||
subs = lib.concatStringsSep " " sedArgs;
|
subs = lib.concatStringsSep " " sedArgs;
|
||||||
in {
|
in {
|
||||||
description = "trust-dns Domain Name Server (serving ${flavor})";
|
description = "trust-dns Domain Name Server (serving ${flavor})";
|
||||||
|
@@ -127,14 +127,12 @@ let
|
|||||||
FirewallMark = fwmark;
|
FirewallMark = fwmark;
|
||||||
};
|
};
|
||||||
wireguardPeers = [{
|
wireguardPeers = [{
|
||||||
wireguardPeerConfig = {
|
|
||||||
AllowedIPs = [
|
AllowedIPs = [
|
||||||
"0.0.0.0/0"
|
"0.0.0.0/0"
|
||||||
"::/0"
|
"::/0"
|
||||||
];
|
];
|
||||||
Endpoint = endpoint;
|
Endpoint = endpoint;
|
||||||
PublicKey = publicKey;
|
PublicKey = publicKey;
|
||||||
};
|
|
||||||
}];
|
}];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -149,10 +147,10 @@ let
|
|||||||
# Domains = ~.: system DNS queries are sent to this link's DNS server
|
# Domains = ~.: system DNS queries are sent to this link's DNS server
|
||||||
# networkConfig.Domains = "~.";
|
# networkConfig.Domains = "~.";
|
||||||
routes = [{
|
routes = [{
|
||||||
routeConfig.Table = id;
|
Table = id;
|
||||||
routeConfig.Scope = "link";
|
Scope = "link";
|
||||||
routeConfig.Destination = "0.0.0.0/0";
|
Destination = "0.0.0.0/0";
|
||||||
routeConfig.Source = addrV4;
|
Source = addrV4;
|
||||||
}];
|
}];
|
||||||
# RequiredForOnline => should `systemd-networkd-wait-online` fail if this network can't come up?
|
# RequiredForOnline => should `systemd-networkd-wait-online` fail if this network can't come up?
|
||||||
linkConfig.RequiredForOnline = false;
|
linkConfig.RequiredForOnline = false;
|
||||||
|
@@ -2,17 +2,18 @@
|
|||||||
, fetchFromGitHub
|
, fetchFromGitHub
|
||||||
, lib
|
, lib
|
||||||
, makeWrapper
|
, makeWrapper
|
||||||
|
, nix-update-script
|
||||||
, pulseaudio
|
, pulseaudio
|
||||||
}:
|
}:
|
||||||
buildGoModule rec {
|
buildGoModule rec {
|
||||||
pname = "blast-ugjka";
|
pname = "blast-ugjka";
|
||||||
version = "0.6.2";
|
version = "0.7.0";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "ugjka";
|
owner = "ugjka";
|
||||||
repo = "blast";
|
repo = "blast";
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
hash = "sha256-Y9Jj+UrrsyRfihHAdC354jb1385xqLIufB0DoikrXYM=";
|
hash = "sha256-yMwMG0y2ehq2dBMlv9hF+i0TgmMjW3ojBVGiqEUSrhU=";
|
||||||
};
|
};
|
||||||
|
|
||||||
vendorHash = "sha256-yPwLilMiDR1aSeuk8AEmuYPsHPRWqiByGLwgkdI5t+s=";
|
vendorHash = "sha256-yPwLilMiDR1aSeuk8AEmuYPsHPRWqiByGLwgkdI5t+s=";
|
||||||
@@ -26,10 +27,12 @@ buildGoModule rec {
|
|||||||
--suffix PATH : ${lib.makeBinPath [ pulseaudio ]}
|
--suffix PATH : ${lib.makeBinPath [ pulseaudio ]}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
passthru.updateScript = nix-update-script { };
|
||||||
|
|
||||||
meta = with lib; {
|
meta = with lib; {
|
||||||
description = "blast your linux audio to DLNA receivers";
|
description = "blast your linux audio to DLNA receivers";
|
||||||
# license = licenses.mit; # MIT + NoAI
|
# license = licenses.mit; # MIT + NoAI
|
||||||
inherit (src.meta) homepage;
|
homepage = "https://github.com/ugjka/blast";
|
||||||
maintainers = with maintainers; [ colinsane ];
|
maintainers = with maintainers; [ colinsane ];
|
||||||
platforms = platforms.unix;
|
platforms = platforms.unix;
|
||||||
};
|
};
|
||||||
|
@@ -8,6 +8,15 @@
|
|||||||
#
|
#
|
||||||
# this script downloads assisted GPS (AGPS) data via the system's default gateway (i.e. WiFi)
|
# this script downloads assisted GPS (AGPS) data via the system's default gateway (i.e. WiFi)
|
||||||
# and shares that with the modem. this quickens the process of acquiring a GPS fix.
|
# and shares that with the modem. this quickens the process of acquiring a GPS fix.
|
||||||
|
# AGPS data includes an almanac and "ephemeris" [Wikipedia-GPS_signals#Navigation_message]
|
||||||
|
# - Almanac: valid for 2 weeks; status & low-res orbital info for *all* satellites.
|
||||||
|
# - used to know which GPS signals to *search* for.
|
||||||
|
# - every sat broadcasts the global almanac over 12.5min cycles.
|
||||||
|
# - Ephemeris: valid for 4 hours; precise orbital info for each satellite.
|
||||||
|
# - takes 30s to learn this info w/o AGPS data.
|
||||||
|
# - every sat broadcasts *its own* ephemeris over 30s cycles.
|
||||||
|
#
|
||||||
|
# [Wikipedia-GPS_signals#Navigation_message]: https://en.wikipedia.org/wiki/GPS_signals#Navigation_message
|
||||||
#
|
#
|
||||||
# the script may also configure other parts of the modem as `eg25-manager` does.
|
# the script may also configure other parts of the modem as `eg25-manager` does.
|
||||||
# these options are less tested: see `--help` for more.
|
# these options are less tested: see `--help` for more.
|
||||||
|
@@ -145,8 +145,8 @@ in (lib.makeScope newScope (self: with self; {
|
|||||||
extid = "webextension@metamask.io";
|
extid = "webextension@metamask.io";
|
||||||
pname = "ether-metamask";
|
pname = "ether-metamask";
|
||||||
url = "https://github.com/MetaMask/metamask-extension/releases/download/v${version}/metamask-firefox-${version}.zip";
|
url = "https://github.com/MetaMask/metamask-extension/releases/download/v${version}/metamask-firefox-${version}.zip";
|
||||||
version = "11.16.9";
|
version = "11.16.13";
|
||||||
hash = "sha256-IYRCR0jX2agMHj/Pnnc+q6X92yrhdIJF+uRtw7C2T2k=";
|
hash = "sha256-aiWFfGGbjFfKEJSe2wnCfxSABs6ELQ2h0x90IAF3wec=";
|
||||||
};
|
};
|
||||||
fx_cast = fetchVersionedAddon rec {
|
fx_cast = fetchVersionedAddon rec {
|
||||||
extid = "fx_cast@matt.tf";
|
extid = "fx_cast@matt.tf";
|
||||||
@@ -173,8 +173,8 @@ in (lib.makeScope newScope (self: with self; {
|
|||||||
extid = "@ublacklist";
|
extid = "@ublacklist";
|
||||||
pname = "ublacklist";
|
pname = "ublacklist";
|
||||||
url = "https://github.com/iorate/ublacklist/releases/download/v${version}/ublacklist-v${version}-firefox.zip";
|
url = "https://github.com/iorate/ublacklist/releases/download/v${version}/ublacklist-v${version}-firefox.zip";
|
||||||
version = "8.7.1";
|
version = "8.8.1";
|
||||||
hash = "sha256-FvZ2IFlvoAYMmZFXTkGtCZ+44MmXioA271DXvNY96j8=";
|
hash = "sha256-b9XiA62Hc32enn04DfUJDVW+Wab5zKgUFwO+oFeTT/w=";
|
||||||
};
|
};
|
||||||
ublock-origin = fetchVersionedAddon rec {
|
ublock-origin = fetchVersionedAddon rec {
|
||||||
extid = "uBlock0@raymondhill.net";
|
extid = "uBlock0@raymondhill.net";
|
||||||
|
@@ -1,13 +1,14 @@
|
|||||||
{ buildLinux
|
{ lib
|
||||||
|
, buildLinux
|
||||||
, fetchFromGitLab
|
, fetchFromGitLab
|
||||||
#v nixpkgs calls `.override` on the kernel to configure additional things
|
#v nixpkgs calls `.override` on the kernel to configure additional things
|
||||||
, features ? {}
|
, features ? {}
|
||||||
, kernelPatches ? []
|
, kernelPatches ? null
|
||||||
, randstructSeed ? ""
|
, randstructSeed ? ""
|
||||||
, structuredExtraConfig ? {}
|
, structuredExtraConfig ? {}
|
||||||
, ...
|
, ...
|
||||||
}:
|
}:
|
||||||
buildLinux {
|
buildLinux ({
|
||||||
src = fetchFromGitLab {
|
src = fetchFromGitLab {
|
||||||
owner = "exynos5-mainline";
|
owner = "exynos5-mainline";
|
||||||
repo = "linux";
|
repo = "linux";
|
||||||
@@ -23,5 +24,9 @@ buildLinux {
|
|||||||
autoModules = false;
|
autoModules = false;
|
||||||
# preferBuiltin = false;
|
# preferBuiltin = false;
|
||||||
|
|
||||||
inherit features kernelPatches randstructSeed structuredExtraConfig;
|
inherit features randstructSeed structuredExtraConfig;
|
||||||
}
|
} // lib.optionalAttrs (builtins.isList kernelPatches) {
|
||||||
|
# callPackage mucks with `kernelPatches`: only forward this argument if it's a list,
|
||||||
|
# as expected by `buildLinux`
|
||||||
|
inherit kernelPatches;
|
||||||
|
})
|
||||||
|
@@ -7,8 +7,8 @@ let
|
|||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "nix-community";
|
owner = "nix-community";
|
||||||
repo = "nixpkgs-wayland";
|
repo = "nixpkgs-wayland";
|
||||||
rev = "422bb5c5106008418f499ca591c0138f73e213f4";
|
rev = "d0eb8a2eb4b9e30e10b95ed5d99f3501c1b3367d";
|
||||||
hash = "sha256-32ukRcPI2W5exf4A7/ISqoKp+sL1MxdMjFt3I+8XS5Y=";
|
hash = "sha256-WA75k8/SJkHd+qaLUJFy4uGM95wDn/18wv+awR0kTbo=";
|
||||||
};
|
};
|
||||||
flake = import "${src}/flake.nix";
|
flake = import "${src}/flake.nix";
|
||||||
evaluated = flake.outputs {
|
evaluated = flake.outputs {
|
||||||
@@ -25,7 +25,7 @@ let
|
|||||||
in src.overrideAttrs (base: {
|
in src.overrideAttrs (base: {
|
||||||
# attributes required by update scripts
|
# attributes required by update scripts
|
||||||
pname = "nixpkgs-wayland";
|
pname = "nixpkgs-wayland";
|
||||||
version = "0-unstable-2024-06-14";
|
version = "0-unstable-2024-06-21";
|
||||||
src = src;
|
src = src;
|
||||||
|
|
||||||
# passthru only nixpkgs-wayland's own packages -- not the whole nixpkgs-with-nixpkgs-wayland-as-overlay:
|
# passthru only nixpkgs-wayland's own packages -- not the whole nixpkgs-with-nixpkgs-wayland-as-overlay:
|
||||||
|
@@ -27,12 +27,12 @@
|
|||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
lock = {
|
lock = {
|
||||||
master.rev = "bac3e728035fee7d7fd3df57e7bb89298d1b1b2e";
|
master.rev = "124ae37067e998cc9286daccf1f222d651c6bef5";
|
||||||
master.sha256 = "sha256-tW1Tzz/2SX8HiAXkQm6IbsRbzQuPH9W/ouoTt+bUGdk=";
|
master.sha256 = "sha256-7GVAIzW3dgQrUpqrcOlZct8KnT+O9isobOvM/08fYIU=";
|
||||||
staging.rev = "bac3e728035fee7d7fd3df57e7bb89298d1b1b2e";
|
staging.rev = "124ae37067e998cc9286daccf1f222d651c6bef5";
|
||||||
staging.sha256 = "sha256-tW1Tzz/2SX8HiAXkQm6IbsRbzQuPH9W/ouoTt+bUGdk=";
|
staging.sha256 = "sha256-7GVAIzW3dgQrUpqrcOlZct8KnT+O9isobOvM/08fYIU=";
|
||||||
staging-next.rev = "bac3e728035fee7d7fd3df57e7bb89298d1b1b2e";
|
staging-next.rev = "124ae37067e998cc9286daccf1f222d651c6bef5";
|
||||||
staging-next.sha256 = "sha256-tW1Tzz/2SX8HiAXkQm6IbsRbzQuPH9W/ouoTt+bUGdk=";
|
staging-next.sha256 = "sha256-7GVAIzW3dgQrUpqrcOlZct8KnT+O9isobOvM/08fYIU=";
|
||||||
};
|
};
|
||||||
lock' = lock."${variant}";
|
lock' = lock."${variant}";
|
||||||
unpatchedSrc = fetchzip {
|
unpatchedSrc = fetchzip {
|
||||||
@@ -81,7 +81,7 @@ in
|
|||||||
src.overrideAttrs (base: {
|
src.overrideAttrs (base: {
|
||||||
# attributes needed for update scripts
|
# attributes needed for update scripts
|
||||||
pname = "nixpkgs";
|
pname = "nixpkgs";
|
||||||
version = "24.05-unstable-2024-06-15";
|
version = "24.05-unstable-2024-06-21";
|
||||||
passthru = (base.passthru or {}) // nixpkgs // {
|
passthru = (base.passthru or {}) // nixpkgs // {
|
||||||
src = unpatchedSrc // {
|
src = unpatchedSrc // {
|
||||||
inherit (lock') rev;
|
inherit (lock') rev;
|
||||||
|
@@ -30,6 +30,14 @@ in
|
|||||||
# hash = "sha256-fGuS46f9qSMRHvWZvTmcirKufIqlXHwwhckeK1RNejE=";
|
# hash = "sha256-fGuS46f9qSMRHvWZvTmcirKufIqlXHwwhckeK1RNejE=";
|
||||||
# })
|
# })
|
||||||
|
|
||||||
|
(fetchpatch' {
|
||||||
|
# xsimd is required by scipy, which is required by ols
|
||||||
|
title = "xsimd: fix cross compilation";
|
||||||
|
# prUrl = "https://github.com/NixOS/nixpkgs/pull/321253";
|
||||||
|
prUrl = "https://github.com/NixOS/nixpkgs/pull/321288";
|
||||||
|
hash = "sha256-jeRM/dfnljX0i3lHsg8bPfQXO3+Wx9M+hSypJiG9MfE=";
|
||||||
|
})
|
||||||
|
|
||||||
(fetchpatch' {
|
(fetchpatch' {
|
||||||
title = "unl0kr: 2.0.0 -> 3.2.0";
|
title = "unl0kr: 2.0.0 -> 3.2.0";
|
||||||
prUrl = "https://github.com/NixOS/nixpkgs/pull/319126";
|
prUrl = "https://github.com/NixOS/nixpkgs/pull/319126";
|
||||||
@@ -37,9 +45,9 @@ in
|
|||||||
})
|
})
|
||||||
|
|
||||||
(fetchpatch' {
|
(fetchpatch' {
|
||||||
title = "sysvol: init at 0-unstable-2024-06-07";
|
title = "syshud: init at 0-unstable-2024-06-20";
|
||||||
prUrl = "https://github.com/NixOS/nixpkgs/pull/318440";
|
prUrl = "https://github.com/NixOS/nixpkgs/pull/318440";
|
||||||
hash = "sha256-OX1OP2m9LJYjVcryhpt520XJmdK1XS0KKaEBzMjdpNo=";
|
hash = "sha256-jVw5pC+f8Z68S/X9EvMB6nbwvoiR03qI7ALeLtkmN24=";
|
||||||
})
|
})
|
||||||
|
|
||||||
(fetchpatch' {
|
(fetchpatch' {
|
||||||
|
32
pkgs/additional/opencellid/default.nix
Normal file
32
pkgs/additional/opencellid/default.nix
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
{ stdenv
|
||||||
|
, lib
|
||||||
|
, fetchurl
|
||||||
|
# database downloads are limited per API key, so please consider supplying your own API key if using this package
|
||||||
|
, apiKey ? "pk.758ba60a9bf5fc060451153c3e2542dc"
|
||||||
|
}:
|
||||||
|
|
||||||
|
stdenv.mkDerivation {
|
||||||
|
pname = "opencellid";
|
||||||
|
version = "0-unstable-2024-06-20";
|
||||||
|
|
||||||
|
src = fetchurl {
|
||||||
|
# this is a live url. updated daily? TODO: add an update script for this.
|
||||||
|
# the API key should allow for at least 2 downloads per day
|
||||||
|
url = "https://opencellid.org/ocid/downloads?token=${apiKey}&type=full&file=cell_towers.csv.gz";
|
||||||
|
hash = "sha256-uY9nHY/LHPJSqMjvIpRgiW++fzucRn1JwPdNXE63bq8=";
|
||||||
|
};
|
||||||
|
|
||||||
|
unpackPhase = ''
|
||||||
|
gunzip "$src" --stdout > cell_towers.csv
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
cp cell_towers.csv $out
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
description = "100M-ish csv database of known celltower positions";
|
||||||
|
homepage = "https://opencellid.org";
|
||||||
|
maintainers = with maintainers; [ colinsane ];
|
||||||
|
};
|
||||||
|
}
|
@@ -1,34 +1,54 @@
|
|||||||
{
|
{ stdenv ? null }:
|
||||||
findutils,
|
with builtins;
|
||||||
runCommandLocal,
|
let
|
||||||
rsync,
|
src = filterSource
|
||||||
}:
|
(path: type:
|
||||||
runCommandLocal "sane-nix-files" {
|
let name = baseNameOf path;
|
||||||
nativeBuildInputs = [
|
in !(
|
||||||
findutils
|
# mimic .gitignore
|
||||||
rsync
|
(name == ".working")
|
||||||
];
|
|| (name == "result")
|
||||||
|
|| (match "^result-.*" name != null)
|
||||||
|
))
|
||||||
|
../../../.
|
||||||
|
;
|
||||||
|
|
||||||
meta = {
|
fakeDeriv = {
|
||||||
description = "top-level host configs for Colin's machines";
|
# in the bootstrap path, we don't have enough available to actually
|
||||||
longDescription = ''
|
# link these files into a derivation.
|
||||||
i like to ensure a copy of my config is present on all my machines,
|
# but that's ok, because the caller immediately `import`s it anyway,
|
||||||
and this does that in a hermetic way.
|
# so just yield something importable.
|
||||||
'';
|
outPath = src;
|
||||||
|
};
|
||||||
|
realDeriv = stdenv.mkDerivation {
|
||||||
|
name = "sane-nix-files";
|
||||||
|
inherit src;
|
||||||
|
installPhase = ''
|
||||||
|
ln -s "$src" "$out"
|
||||||
|
'';
|
||||||
|
dontFixup = true;
|
||||||
};
|
};
|
||||||
} ''
|
|
||||||
mkdir src
|
|
||||||
pushd src
|
|
||||||
|
|
||||||
rsync -lptr ${../../../.}/ ./
|
# alternative implementation which always returns a real derivation,
|
||||||
chmod u+w .
|
# but requires a pre-compiled statically-linked `sln` or `cp` implementation.
|
||||||
for pat in $(cat .gitignore); do
|
# self = derivation {
|
||||||
set +e
|
# name = "sane-nix-files";
|
||||||
chmod u+w -R "$pat" ; rm -rf "$pat"
|
# system = "x86_64-linux";
|
||||||
find $PWD -name "$pat" -exec 'chmod u+w -R {}; rm -rf {}' \;
|
|
||||||
set -e
|
|
||||||
done
|
|
||||||
rsync -lptr ./ $out/
|
|
||||||
|
|
||||||
popd
|
# # builder = "${./sln}";
|
||||||
''
|
# # args = [
|
||||||
|
# # src
|
||||||
|
# # self.outPath
|
||||||
|
# # ];
|
||||||
|
|
||||||
|
# builder = "/bin/sh";
|
||||||
|
# args = [
|
||||||
|
# "-c"
|
||||||
|
# "${./sln} ${src} $out"
|
||||||
|
# ];
|
||||||
|
# };
|
||||||
|
in
|
||||||
|
if stdenv == null then
|
||||||
|
fakeDeriv
|
||||||
|
else
|
||||||
|
realDeriv
|
||||||
|
@@ -35,6 +35,9 @@ configureKeyboardFor_application() {
|
|||||||
# io.github.lainsce.Notejot.desktop)
|
# io.github.lainsce.Notejot.desktop)
|
||||||
# setKeyboard showIfRoom
|
# setKeyboard showIfRoom
|
||||||
# ;;
|
# ;;
|
||||||
|
networkmanager_dmenu.desktop)
|
||||||
|
setKeyboard showIfRoom
|
||||||
|
;;
|
||||||
org.gnome.Epiphany.desktop)
|
org.gnome.Epiphany.desktop)
|
||||||
setKeyboard showIfRoom
|
setKeyboard showIfRoom
|
||||||
;;
|
;;
|
||||||
|
@@ -12,6 +12,7 @@ usageDescription() {
|
|||||||
echo "sane-vpn up [REGION]"
|
echo "sane-vpn up [REGION]"
|
||||||
echo "sane-vpn down [REGION]"
|
echo "sane-vpn down [REGION]"
|
||||||
echo "sane-vpn do [REGION [COMMAND ...] ]"
|
echo "sane-vpn do [REGION [COMMAND ...] ]"
|
||||||
|
echo "sane-vpn do -- [COMMAND ...]"
|
||||||
echo "sane-vpn dns-fix"
|
echo "sane-vpn dns-fix"
|
||||||
echo "sane-vpn help"
|
echo "sane-vpn help"
|
||||||
}
|
}
|
||||||
@@ -63,7 +64,7 @@ canonicalizeRegion() {
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ -z "$region" ] || [ "$region" = "default" ]; then
|
if [ -z "$region" ] || [ "$region" = "default" ] || [ "$region" = "-" ] || [ "$region" = "--" ]; then
|
||||||
debug "canonicalizing default region to '$defaultVpn'"
|
debug "canonicalizing default region to '$defaultVpn'"
|
||||||
region="$defaultVpn"
|
region="$defaultVpn"
|
||||||
fi
|
fi
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
{ static-nix-shell }:
|
{ static-nix-shell }:
|
||||||
static-nix-shell.mkPython3Bin {
|
static-nix-shell.mkPython3Bin {
|
||||||
pname = "sane-sysinfo";
|
pname = "sane-sysload";
|
||||||
srcRoot = ./.;
|
srcRoot = ./.;
|
||||||
}
|
}
|
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env nix-shell
|
#!/usr/bin/env nix-shell
|
||||||
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ])"
|
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ])"
|
||||||
"""
|
"""
|
||||||
usage: sane-sysinfo [options...]
|
usage: sane-sysload [options...] formatstr
|
||||||
|
|
||||||
pretty-prints a battery estimate (icon to indicate state, and a duration estimate)
|
pretty-prints a battery estimate (icon to indicate state, and a duration estimate)
|
||||||
|
|
||||||
@@ -11,10 +11,24 @@ options:
|
|||||||
--hour-suffix <string>: use the provided string as an hours suffix
|
--hour-suffix <string>: use the provided string as an hours suffix
|
||||||
--icon-suffix <string>: use the provided string as an icon suffix
|
--icon-suffix <string>: use the provided string as an icon suffix
|
||||||
--percent-suffix <string>: use the provided string when displaying percents
|
--percent-suffix <string>: use the provided string when displaying percents
|
||||||
|
|
||||||
|
formatstr is a Python format string.
|
||||||
|
variables available for formatting:
|
||||||
|
- {bat_icon}
|
||||||
|
- {bat_time}
|
||||||
|
- {cpu_icon}
|
||||||
|
- {cpu_pct}
|
||||||
|
- {mem_icon}
|
||||||
|
- {mem_pct}
|
||||||
|
and some presets, encapsulating the above:
|
||||||
|
- {bat}
|
||||||
|
- {cpu}
|
||||||
|
- {mem}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
|
import time
|
||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
@@ -24,6 +38,7 @@ logger = logging.getLogger(__name__)
|
|||||||
# these icons may only render in nerdfonts
|
# these icons may only render in nerdfonts
|
||||||
ICON_BAT_CHG = ["", "", "", ""]
|
ICON_BAT_CHG = ["", "", "", ""]
|
||||||
ICON_BAT_DIS = ["", "", "", ""]
|
ICON_BAT_DIS = ["", "", "", ""]
|
||||||
|
ICON_CPU=""
|
||||||
ICON_MEM="☵"
|
ICON_MEM="☵"
|
||||||
SUFFIX_ICON = " " # thin space
|
SUFFIX_ICON = " " # thin space
|
||||||
SUFFIX_PERCENT = "%"
|
SUFFIX_PERCENT = "%"
|
||||||
@@ -72,6 +87,9 @@ class Formatter:
|
|||||||
def render_charge_icon(self, direction: ChargeDirection, percentage: float) -> str:
|
def render_charge_icon(self, direction: ChargeDirection, percentage: float) -> str:
|
||||||
return f"{self._choose_icon(direction, percentage)}{self.suffix_icon}"
|
return f"{self._choose_icon(direction, percentage)}{self.suffix_icon}"
|
||||||
|
|
||||||
|
def render_cpu_icon(self) -> str:
|
||||||
|
return f"{ICON_CPU}{self.suffix_icon}"
|
||||||
|
|
||||||
def render_mem_icon(self) -> str:
|
def render_mem_icon(self) -> str:
|
||||||
return f"{ICON_MEM}{self.suffix_icon}"
|
return f"{ICON_MEM}{self.suffix_icon}"
|
||||||
|
|
||||||
@@ -137,6 +155,83 @@ class MemInfo:
|
|||||||
logger.debug(f"/proc/meminfo: {entry}={v}")
|
logger.debug(f"/proc/meminfo: {entry}={v}")
|
||||||
return v
|
return v
|
||||||
|
|
||||||
|
class ProcStat:
|
||||||
|
"""
|
||||||
|
reads vaues from /proc/stat, mostly CPU-related.
|
||||||
|
"""
|
||||||
|
# /proc/stat format is documented here: <https://www.linuxhowtos.org/System/procstat.htm>
|
||||||
|
# these are AGGREGATES SINCE SYSTEM BOOT
|
||||||
|
# to measure current CPU usage, need to take multiple samples
|
||||||
|
# cpu <user> <system> <nice> <idle> <iowait> <irg> <softirq> 0 0 0
|
||||||
|
# (what are the last three fields?)
|
||||||
|
# where:
|
||||||
|
# measurements are in units of jiffies or USER_HZ
|
||||||
|
# user: normal processes executing in user mode
|
||||||
|
# nice: niced processes executing in user mode
|
||||||
|
# system: processes executing in kernel mode
|
||||||
|
# idle: twiddling thumbs
|
||||||
|
# iowait: waiting for I/O to complete
|
||||||
|
# irq: servicing interrupts
|
||||||
|
# softirq: servicing softirqs
|
||||||
|
def __init__(self, entries=None):
|
||||||
|
if entries is not None:
|
||||||
|
self.entries = entries
|
||||||
|
return
|
||||||
|
|
||||||
|
# else, read from procfs...
|
||||||
|
try:
|
||||||
|
lines = open("/proc/stat").readlines()
|
||||||
|
except Exception as e:
|
||||||
|
logger.info(f"failed to open /proc/stat: {e}")
|
||||||
|
lines = []
|
||||||
|
|
||||||
|
self.entries = {}
|
||||||
|
for l in lines:
|
||||||
|
pieces = l.strip().split(" ")
|
||||||
|
name, values = pieces[0], [p for p in pieces[1:] if p]
|
||||||
|
if name:
|
||||||
|
self.entries[name] = [int(v) for v in values]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def sample(seconds: float = 1.0):
|
||||||
|
sample1 = ProcStat()
|
||||||
|
time.sleep(seconds)
|
||||||
|
sample2 = ProcStat()
|
||||||
|
return sample2 - sample1
|
||||||
|
|
||||||
|
def __sub__(self, other: 'ProcStat') -> 'ProcStat':
|
||||||
|
entries = {}
|
||||||
|
for k in self.entries:
|
||||||
|
entries[k] = [i - j for i, j in zip(self.entries[k], other.entries[k])]
|
||||||
|
return ProcStat(entries)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def cpu_user(self) -> int:
|
||||||
|
return self.entries["cpu"][0]
|
||||||
|
@property
|
||||||
|
def cpu_system(self) -> int:
|
||||||
|
return self.entries["cpu"][1]
|
||||||
|
@property
|
||||||
|
def cpu_nice(self) -> int:
|
||||||
|
return self.entries["cpu"][2]
|
||||||
|
@property
|
||||||
|
def cpu_idle(self) -> int:
|
||||||
|
return self.entries["cpu"][3]
|
||||||
|
@property
|
||||||
|
def cpu_iowait(self) -> int:
|
||||||
|
return self.entries["cpu"][4]
|
||||||
|
@property
|
||||||
|
def cpu_irq(self) -> int:
|
||||||
|
return self.entries["cpu"][5]
|
||||||
|
@property
|
||||||
|
def cpu_softirq(self) -> int:
|
||||||
|
return self.entries["cpu"][6]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def cpu_total(self) -> int:
|
||||||
|
# TODO: not sure if i'm supposed to include irq stuff here?
|
||||||
|
return self.cpu_user + self.cpu_system + self.cpu_nice + self.cpu_idle + self.cpu_iowait + self.cpu_irq + self.cpu_softirq
|
||||||
|
|
||||||
class PowerSupply:
|
class PowerSupply:
|
||||||
"""
|
"""
|
||||||
reads values from /sys/class/power_supply/$dev/ API
|
reads values from /sys/class/power_supply/$dev/ API
|
||||||
@@ -263,9 +358,39 @@ def try_all_batteries() -> BatteryInfo | None:
|
|||||||
@dataclass
|
@dataclass
|
||||||
class AllInfo:
|
class AllInfo:
|
||||||
_fmt: Formatter
|
_fmt: Formatter
|
||||||
_mem: MemInfo | None
|
__bat: BatteryInfo | None = None
|
||||||
_bat: BatteryInfo | None
|
__cpu: ProcStat | None = None
|
||||||
|
__mem: MemInfo | None = None
|
||||||
|
|
||||||
|
# lazy-loading
|
||||||
|
@property
|
||||||
|
def _bat(self):
|
||||||
|
if self.__bat is None:
|
||||||
|
self.__bat = try_all_batteries()
|
||||||
|
return self.__bat
|
||||||
|
@property
|
||||||
|
def _cpu(self):
|
||||||
|
if self.__cpu is None:
|
||||||
|
self.__cpu = ProcStat.sample()
|
||||||
|
return self.__cpu
|
||||||
|
@property
|
||||||
|
def _mem(self):
|
||||||
|
if self.__mem is None:
|
||||||
|
self.__mem = MemInfo()
|
||||||
|
return self.__mem
|
||||||
|
|
||||||
|
# user-facing format shorthands
|
||||||
|
@property
|
||||||
|
def bat(self) -> str:
|
||||||
|
return f"{self.bat_icon}{self.bat_time}"
|
||||||
|
@property
|
||||||
|
def cpu(self) -> str:
|
||||||
|
return f"{self.cpu_icon}{self.cpu_pct}"
|
||||||
|
@property
|
||||||
|
def mem(self) -> str:
|
||||||
|
return f"{self.mem_icon}{self.mem_pct}"
|
||||||
|
|
||||||
|
# manual/low-level fields
|
||||||
@property
|
@property
|
||||||
def mem_icon(self) -> str:
|
def mem_icon(self) -> str:
|
||||||
if self._mem is None: return ""
|
if self._mem is None: return ""
|
||||||
@@ -307,6 +432,34 @@ class AllInfo:
|
|||||||
else:
|
else:
|
||||||
return self._fmt.render_percent(self._bat.percent_charged)
|
return self._fmt.render_percent(self._bat.percent_charged)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def cpu_icon(self) -> str:
|
||||||
|
if self._cpu is None: return ""
|
||||||
|
return self._fmt.render_cpu_icon()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def cpu_pct(self) -> str:
|
||||||
|
if self._cpu is None:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
idle = self._cpu.cpu_idle + self._cpu.cpu_iowait
|
||||||
|
total = self._cpu.cpu_total
|
||||||
|
|
||||||
|
cpu_use_pct = int((total - idle) / total * 100)
|
||||||
|
return self._fmt.render_percent(cpu_use_pct)
|
||||||
|
|
||||||
|
|
||||||
|
class LazyFormatter:
|
||||||
|
def __init__(self, obj: object, attr: str):
|
||||||
|
self.obj = obj
|
||||||
|
self.attr = attr
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return repr(getattr(self.obj, self.attr))
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return str(getattr(self.obj, self.attr))
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
logging.basicConfig()
|
logging.basicConfig()
|
||||||
logging.getLogger().setLevel(logging.INFO)
|
logging.getLogger().setLevel(logging.INFO)
|
||||||
@@ -317,8 +470,7 @@ def main() -> None:
|
|||||||
parser.add_argument("--hour-suffix", default=SUFFIX_HR)
|
parser.add_argument("--hour-suffix", default=SUFFIX_HR)
|
||||||
parser.add_argument("--minute-suffix", default=SUFFIX_MIN)
|
parser.add_argument("--minute-suffix", default=SUFFIX_MIN)
|
||||||
parser.add_argument("--percent-suffix", default=SUFFIX_PERCENT)
|
parser.add_argument("--percent-suffix", default=SUFFIX_PERCENT)
|
||||||
parser.add_argument("--template", default="{_.bat_icon}{_.bat_time}")
|
parser.add_argument("formatstr", nargs="+")
|
||||||
# parser.add_argument("--template", default="{_.mem_icon}{_.mem_pct}")
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if args.debug:
|
if args.debug:
|
||||||
@@ -330,12 +482,19 @@ def main() -> None:
|
|||||||
f.suffix_hr = args.hour_suffix
|
f.suffix_hr = args.hour_suffix
|
||||||
f.suffix_min = args.minute_suffix
|
f.suffix_min = args.minute_suffix
|
||||||
|
|
||||||
info = AllInfo(
|
info = AllInfo(f)
|
||||||
f,
|
formatstr = " ".join(args.formatstr)
|
||||||
MemInfo(),
|
print(formatstr.format(
|
||||||
try_all_batteries(),
|
bat=LazyFormatter(info, "bat"),
|
||||||
)
|
bat_icon=LazyFormatter(info, "bat_icon"),
|
||||||
print(args.template.format(_=info))
|
bat_time=LazyFormatter(info, "bat_time"),
|
||||||
|
cpu=LazyFormatter(info, "cpu"),
|
||||||
|
cpu_icon=LazyFormatter(info, "cpu_icon"),
|
||||||
|
cpu_pct=LazyFormatter(info, "cpu_pct"),
|
||||||
|
mem=LazyFormatter(info, "mem"),
|
||||||
|
mem_icon=LazyFormatter(info, "mem_icon"),
|
||||||
|
mem_pct=LazyFormatter(info, "mem_pct"),
|
||||||
|
))
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
@@ -6,8 +6,8 @@ let
|
|||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "Mic92";
|
owner = "Mic92";
|
||||||
repo = "sops-nix";
|
repo = "sops-nix";
|
||||||
rev = "c279dec105dd53df13a5e57525da97905cc0f0d6";
|
rev = "797ce4c1f45a85df6dd3d9abdc53f2691bea9251";
|
||||||
hash = "sha256-psA+1Q5fPaK6yI3vzlLINNtb6EeXj111zQWnZYyJS9c=";
|
hash = "sha256-Pm9I/BMQHbsucdWf6y9G3xBZh3TMlThGo4KBbeoeczg=";
|
||||||
};
|
};
|
||||||
flake = import "${src}/flake.nix";
|
flake = import "${src}/flake.nix";
|
||||||
evaluated = flake.outputs {
|
evaluated = flake.outputs {
|
||||||
@@ -21,7 +21,7 @@ in src.overrideAttrs (base: {
|
|||||||
# attributes required by update scripts
|
# attributes required by update scripts
|
||||||
pname = "sops-nix";
|
pname = "sops-nix";
|
||||||
# nix-update-script insists on this weird `assets-` version format
|
# nix-update-script insists on this weird `assets-` version format
|
||||||
version = "assets-unstable-2024-06-11";
|
version = "assets-unstable-2024-06-16";
|
||||||
src = src;
|
src = src;
|
||||||
|
|
||||||
passthru = base.passthru
|
passthru = base.passthru
|
||||||
|
@@ -107,6 +107,7 @@ let
|
|||||||
xdotool
|
xdotool
|
||||||
] ++ lib.optionals preferXdgOpen [ xdg-utils ];
|
] ++ lib.optionals preferXdgOpen [ xdg-utils ];
|
||||||
in
|
in
|
||||||
|
lib.warn "sxmo-utils from nur.colinsane is no longer maintained and will be removed in the future. consider pointing to a different upstream or copying the package into your own config."
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "sxmo-utils";
|
pname = "sxmo-utils";
|
||||||
version = "unstable-2024-02-05";
|
version = "unstable-2024-02-05";
|
||||||
|
@@ -8,14 +8,14 @@
|
|||||||
, wrapGAppsHook4
|
, wrapGAppsHook4
|
||||||
}:
|
}:
|
||||||
stdenv.mkDerivation {
|
stdenv.mkDerivation {
|
||||||
pname = "sysvol";
|
pname = "syshud";
|
||||||
version = "0-unstable-2024-06-13";
|
version = "0-unstable-2024-06-20";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "System64fumo";
|
owner = "System64fumo";
|
||||||
repo = "sysvol";
|
repo = "syshud";
|
||||||
rev = "af882d40df7c6e1a0ec415d934f643933f455b5a";
|
rev = "2b97f3441970efe67c788a8313eb58182aa7965b";
|
||||||
hash = "sha256-3gB1u7fEi7EB+FWZKS8ddJ53RC5Chyw3fTBX8Z0Itis=";
|
hash = "sha256-XPAKjBLaTGEyDgiZT8tYinYzMivOocOEeauzR4leOjI=";
|
||||||
};
|
};
|
||||||
postPatch = ''
|
postPatch = ''
|
||||||
substituteInPlace Makefile \
|
substituteInPlace Makefile \
|
||||||
@@ -40,9 +40,9 @@ stdenv.mkDerivation {
|
|||||||
};
|
};
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
description = "A basic GTK4 volume indicator";
|
description = "Simple heads up display written in gtkmm 4";
|
||||||
homepage = "https://github.com/System64fumo/sysvol";
|
homepage = "https://github.com/System64fumo/syshud";
|
||||||
mainProgram = "sysvol";
|
mainProgram = "syshud";
|
||||||
platforms = lib.platforms.linux;
|
platforms = lib.platforms.linux;
|
||||||
maintainers = with lib.maintainers; [ colinsane ];
|
maintainers = with lib.maintainers; [ colinsane ];
|
||||||
};
|
};
|
@@ -5,12 +5,12 @@
|
|||||||
}:
|
}:
|
||||||
stdenv.mkDerivation {
|
stdenv.mkDerivation {
|
||||||
pname = "uassets";
|
pname = "uassets";
|
||||||
version = "0-unstable-2024-06-15";
|
version = "0-unstable-2024-06-21";
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "uBlockOrigin";
|
owner = "uBlockOrigin";
|
||||||
repo = "uAssets";
|
repo = "uAssets";
|
||||||
rev = "bbb9bd592fe54dc2cbc952a68dd715bb481ab83d";
|
rev = "05dfb7b5504b20e5432f7092111ad51568b3d9f4";
|
||||||
hash = "sha256-r7ZCfHxCNVETu1X7O8vb4xkxTAmYVWFDTHQOZeQ8C2I=";
|
hash = "sha256-FrSMmZxR+XWUUOb8X1kImEM4Lhw8Ikg8k1vtqXOJD+8=";
|
||||||
};
|
};
|
||||||
|
|
||||||
dontBuild = true;
|
dontBuild = true;
|
||||||
|
@@ -1,9 +0,0 @@
|
|||||||
{ linkFarm
|
|
||||||
, geoclue2
|
|
||||||
}:
|
|
||||||
linkFarm "where-am-i" [{
|
|
||||||
# bring the `where-am-i` tool into a `bin/` directory so it can be invokable via PATH
|
|
||||||
name = "bin/where-am-i";
|
|
||||||
path = "${geoclue2}/libexec/geoclue-2.0/demos/where-am-i";
|
|
||||||
}]
|
|
||||||
|
|
@@ -71,6 +71,7 @@ let
|
|||||||
nixpkgs-staging = nixpkgs.override { variant = "staging"; };
|
nixpkgs-staging = nixpkgs.override { variant = "staging"; };
|
||||||
nixpkgs-next = nixpkgs.override { variant = "staging-next"; };
|
nixpkgs-next = nixpkgs.override { variant = "staging-next"; };
|
||||||
nixpkgs-wayland = callPackage ./additional/nixpkgs-wayland { };
|
nixpkgs-wayland = callPackage ./additional/nixpkgs-wayland { };
|
||||||
|
opencellid = callPackage ./additional/opencellid { };
|
||||||
peerswap = callPackage ./additional/peerswap { };
|
peerswap = callPackage ./additional/peerswap { };
|
||||||
phog = callPackage ./additional/phog { };
|
phog = callPackage ./additional/phog { };
|
||||||
pipeline = callPackage ./additional/pipeline { };
|
pipeline = callPackage ./additional/pipeline { };
|
||||||
@@ -84,7 +85,7 @@ let
|
|||||||
sane-open = callPackage ./additional/sane-open { };
|
sane-open = callPackage ./additional/sane-open { };
|
||||||
sane-screenshot = callPackage ./additional/sane-screenshot { };
|
sane-screenshot = callPackage ./additional/sane-screenshot { };
|
||||||
sane-scripts = lib.recurseIntoAttrs (callPackage ./additional/sane-scripts { });
|
sane-scripts = lib.recurseIntoAttrs (callPackage ./additional/sane-scripts { });
|
||||||
sane-sysinfo = callPackage ./additional/sane-sysinfo { };
|
sane-sysload = callPackage ./additional/sane-sysload { };
|
||||||
sane-weather = callPackage ./additional/sane-weather { };
|
sane-weather = callPackage ./additional/sane-weather { };
|
||||||
sanebox = callPackage ./additional/sanebox { };
|
sanebox = callPackage ./additional/sanebox { };
|
||||||
schlock = callPackage ./additional/schlock { };
|
schlock = callPackage ./additional/schlock { };
|
||||||
@@ -97,7 +98,7 @@ let
|
|||||||
sxmo_swaylock = callPackage ./additional/sxmo_swaylock { };
|
sxmo_swaylock = callPackage ./additional/sxmo_swaylock { };
|
||||||
sxmo-suspend = callPackage ./additional/sxmo-suspend { };
|
sxmo-suspend = callPackage ./additional/sxmo-suspend { };
|
||||||
sxmo-utils = callPackage ./additional/sxmo-utils { };
|
sxmo-utils = callPackage ./additional/sxmo-utils { };
|
||||||
sysvol = callPackage ./additional/sysvol { };
|
syshud = callPackage ./additional/syshud { };
|
||||||
tow-boot-pinephone = callPackage ./additional/tow-boot-pinephone { };
|
tow-boot-pinephone = callPackage ./additional/tow-boot-pinephone { };
|
||||||
tree-sitter-nix-shell = callPackage ./additional/tree-sitter-nix-shell { };
|
tree-sitter-nix-shell = callPackage ./additional/tree-sitter-nix-shell { };
|
||||||
trivial-builders = lib.recurseIntoAttrs (callPackage ./additional/trivial-builders { });
|
trivial-builders = lib.recurseIntoAttrs (callPackage ./additional/trivial-builders { });
|
||||||
@@ -113,7 +114,6 @@ let
|
|||||||
runCommandLocalOverridable
|
runCommandLocalOverridable
|
||||||
;
|
;
|
||||||
unftp = callPackage ./additional/unftp { };
|
unftp = callPackage ./additional/unftp { };
|
||||||
where-am-i = callPackage ./additional/where-am-i { };
|
|
||||||
zecwallet-light-cli = callPackage ./additional/zecwallet-light-cli { };
|
zecwallet-light-cli = callPackage ./additional/zecwallet-light-cli { };
|
||||||
|
|
||||||
# packages i haven't used for a while, may or may not still work
|
# packages i haven't used for a while, may or may not still work
|
||||||
@@ -162,6 +162,20 @@ let
|
|||||||
|
|
||||||
# modemmanager = callPackage ./patched/modemmanager { inherit (unpatched) modemmanager; };
|
# modemmanager = callPackage ./patched/modemmanager { inherit (unpatched) modemmanager; };
|
||||||
|
|
||||||
|
playerctl = unpatched.playerctl.overrideAttrs (upstream: {
|
||||||
|
patches = (upstream.patches or []) ++ [
|
||||||
|
(fetchpatch {
|
||||||
|
# playerctl, when used as a library, doesn't expect its user to `unref` it inside a glib signal.
|
||||||
|
# nwg-panel does this though, and then segfaults.
|
||||||
|
# playerctl project looks dead as of 2024/06/19, no hope for upstreaming this.
|
||||||
|
# TODO: consider removing this if nwg-panel code is changed to not trigger this.
|
||||||
|
# - <https://github.com/nwg-piotr/nwg-panel/issues/233>
|
||||||
|
name = "dbus_name_owner_changed_callback: acquire a ref on the manager before using it";
|
||||||
|
url = "https://git.uninsane.org/colin/playerctl/commit/bbcbbe4e03da93523b431ffee5b64e10b17b4f9f.patch";
|
||||||
|
hash = "sha256-l/w+ozga8blAB2wtEd1SPBE6wpHNXWk7NrOL7x10oUI=";
|
||||||
|
})
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
### PYTHON PACKAGES
|
### PYTHON PACKAGES
|
||||||
pythonPackagesExtensions = (unpatched.pythonPackagesExtensions or []) ++ [
|
pythonPackagesExtensions = (unpatched.pythonPackagesExtensions or []) ++ [
|
||||||
|
@@ -2,6 +2,8 @@
|
|||||||
{
|
{
|
||||||
depthcharge-tools = callPackage ./depthcharge-tools { };
|
depthcharge-tools = callPackage ./depthcharge-tools { };
|
||||||
feedsearch-crawler = callPackage ./feedsearch-crawler { };
|
feedsearch-crawler = callPackage ./feedsearch-crawler { };
|
||||||
|
fastcluster = callPackage ./fastcluster { };
|
||||||
|
ols = callPackage ./ols { };
|
||||||
pa-dlna = callPackage ./pa-dlna { };
|
pa-dlna = callPackage ./pa-dlna { };
|
||||||
pyln-bolt7 = callPackage ./pyln-bolt7 { };
|
pyln-bolt7 = callPackage ./pyln-bolt7 { };
|
||||||
pyln-client = callPackage ./pyln-client { };
|
pyln-client = callPackage ./pyln-client { };
|
||||||
|
38
pkgs/python-packages/fastcluster/default.nix
Normal file
38
pkgs/python-packages/fastcluster/default.nix
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
{ lib
|
||||||
|
, buildPythonPackage
|
||||||
|
, fetchFromGitHub
|
||||||
|
, oldest-supported-numpy
|
||||||
|
, numpy
|
||||||
|
, setuptools
|
||||||
|
}: buildPythonPackage rec {
|
||||||
|
pname = "fastcluster";
|
||||||
|
version = "1.2.6";
|
||||||
|
format = "pyproject";
|
||||||
|
# format = "setuptools";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "fastcluster";
|
||||||
|
repo = "fastcluster";
|
||||||
|
rev = "v${version}";
|
||||||
|
hash = "sha256-8FDipkAcOAI5zAC7JaJExe6HO1xHg+eXAL7IUIVrA3k=";
|
||||||
|
};
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
oldest-supported-numpy
|
||||||
|
setuptools
|
||||||
|
];
|
||||||
|
|
||||||
|
# propagatedBuildInputs = [
|
||||||
|
# numpy
|
||||||
|
# ];
|
||||||
|
|
||||||
|
pythonImportsCheck = [
|
||||||
|
"fastcluster"
|
||||||
|
];
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
homepage = "https://danifold.net/fastcluster.html";
|
||||||
|
description = "fast hierarchical clustering routines for R and Python";
|
||||||
|
maintainers = with maintainers; [ colinsane ];
|
||||||
|
};
|
||||||
|
}
|
60
pkgs/python-packages/ols/default.nix
Normal file
60
pkgs/python-packages/ols/default.nix
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
{ lib
|
||||||
|
, buildPythonPackage
|
||||||
|
, fetchFromGitea
|
||||||
|
, aiohttp
|
||||||
|
, fastcluster
|
||||||
|
, fastjsonschema
|
||||||
|
, mercantile
|
||||||
|
, numpy
|
||||||
|
, scipy
|
||||||
|
, setuptools
|
||||||
|
# , wheel
|
||||||
|
}: buildPythonPackage {
|
||||||
|
pname = "ols";
|
||||||
|
version = "0.1.0-unstable-2024-06-21";
|
||||||
|
format = "pyproject";
|
||||||
|
# format = "setuptools";
|
||||||
|
|
||||||
|
src = fetchFromGitea {
|
||||||
|
# my dev branch has a few changes:
|
||||||
|
# - fix `cellid-ols-import` to make --mcc, --mnc actually be optional
|
||||||
|
# - synthesize cell locations when no exact match is found
|
||||||
|
domain = "git.uninsane.org";
|
||||||
|
owner = "colin";
|
||||||
|
repo = "ols";
|
||||||
|
rev = "2caacd27a6253f711d0820ae51e6fe178bd80343";
|
||||||
|
hash = "sha256-vzvEraBi71xz1rjQWFRFKkAaVO9ASNQ2dTvT6y+xihI=";
|
||||||
|
};
|
||||||
|
# src = fetchFromGitea {
|
||||||
|
# domain = "codeberg.org";
|
||||||
|
# owner = "tpikonen";
|
||||||
|
# repo = "ols";
|
||||||
|
# rev = "069560accc6558f16d6d9abea63bd7563ea3f0e9";
|
||||||
|
# hash = "sha256-/931fc37QzITOA61D2CeXr/JmvDg0t8fLSt2y+2kSyQ=";
|
||||||
|
# };
|
||||||
|
# src = /home/colin/ref/repos/tpikonen/ols;
|
||||||
|
|
||||||
|
propagatedBuildInputs = [
|
||||||
|
aiohttp
|
||||||
|
fastcluster
|
||||||
|
fastjsonschema
|
||||||
|
mercantile
|
||||||
|
numpy
|
||||||
|
scipy
|
||||||
|
];
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
setuptools
|
||||||
|
# wheel
|
||||||
|
];
|
||||||
|
|
||||||
|
pythonImportsCheck = [
|
||||||
|
"ols"
|
||||||
|
];
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
homepage = "https://codeberg.org/tpikonen/ols";
|
||||||
|
description = "HTTP location service with Mozilla Location Service (MLS) compatible API";
|
||||||
|
maintainers = with maintainers; [ colinsane ];
|
||||||
|
};
|
||||||
|
}
|
@@ -1,7 +1,8 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
cd ../integrations/nur
|
NIX_FILES_TOP=/home/colin/nixos
|
||||||
|
cd $NIX_FILES_TOP/integrations/nur
|
||||||
# TODO: should include `-I nixpkgs=</path/to/an/unpatched/nixpkgs>`
|
# TODO: should include `-I nixpkgs=</path/to/an/unpatched/nixpkgs>`
|
||||||
NIX_PATH= NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM=1 nix-env -f . -qa \* --meta --xml \
|
NIX_PATH= NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM=1 nix-env -f . -qa linux\* --meta --xml \
|
||||||
--allowed-uris https://static.rust-lang.org \
|
--allowed-uris https://static.rust-lang.org \
|
||||||
--option restrict-eval true \
|
--option restrict-eval true \
|
||||||
--option allow-import-from-derivation true \
|
--option allow-import-from-derivation true \
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env nix-shell
|
#!/usr/bin/env nix-shell
|
||||||
#!nix-shell -i bash -p curl -p dig -p iputils -p lftp -p openssh
|
#!nix-shell -i bash -p curl -p dig -p iputils -p openssh
|
||||||
|
|
||||||
echo "this script will check that uninsane.org is baseline operational"
|
echo "this script will check that uninsane.org is baseline operational"
|
||||||
echo "it doesn't check all services, just the most critical ones"
|
echo "it doesn't check all services, just the most critical ones"
|
||||||
@@ -8,12 +8,40 @@ echo ""
|
|||||||
OVPNS_IPV4=185.157.162.178
|
OVPNS_IPV4=185.157.162.178
|
||||||
DOOF_IPV4=205.201.63.12
|
DOOF_IPV4=205.201.63.12
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "usage: check-uninsane [flags ...]"
|
||||||
|
echo "flags:"
|
||||||
|
echo "- --verbose: show commands before running them"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
verbose=
|
||||||
|
parseArgs() {
|
||||||
|
while [ "$#" -ne 0 ]; do
|
||||||
|
local arg=$1
|
||||||
|
shift
|
||||||
|
case $arg in
|
||||||
|
(--verbose)
|
||||||
|
verbose=1
|
||||||
|
;;
|
||||||
|
(*)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
last_error=0
|
last_error=0
|
||||||
check() {
|
check() {
|
||||||
local label=$1
|
local label=$1
|
||||||
shift
|
shift
|
||||||
|
if [ -n "$verbose" ]; then
|
||||||
|
printf "checking %s (%s) \n" "$label" "$*"
|
||||||
|
"$@"
|
||||||
|
else
|
||||||
printf "checking %s\n" "$label"
|
printf "checking %s\n" "$label"
|
||||||
"$@" > /dev/null
|
"$@" > /dev/null
|
||||||
|
fi
|
||||||
local rc=$?
|
local rc=$?
|
||||||
if [ $rc -ne 0 ]; then
|
if [ $rc -ne 0 ]; then
|
||||||
last_error=$rc
|
last_error=$rc
|
||||||
@@ -23,6 +51,16 @@ check() {
|
|||||||
return $rc
|
return $rc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
runOnHost() {
|
||||||
|
local host="$1"
|
||||||
|
shift
|
||||||
|
if [ "$host" = "$(hostname)" ]; then
|
||||||
|
"$@"
|
||||||
|
else
|
||||||
|
ssh "$host-hn" "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
check "self-test" false 2> /dev/null
|
check "self-test" false 2> /dev/null
|
||||||
if [ $last_error -eq 0 ]; then
|
if [ $last_error -eq 0 ]; then
|
||||||
echo "SELF-TEST FAILED" >&2
|
echo "SELF-TEST FAILED" >&2
|
||||||
@@ -31,10 +69,12 @@ if [ $last_error -eq 0 ]; then
|
|||||||
fi
|
fi
|
||||||
last_error=0
|
last_error=0
|
||||||
|
|
||||||
|
parseArgs "$@"
|
||||||
|
|
||||||
check "uninsane.org. DNS" nslookup uninsane.org.
|
check "uninsane.org. DNS" nslookup uninsane.org.
|
||||||
check "uninsane.org. DNS via external resolver" nslookup uninsane.org. 1.1.1.1
|
check "[1.1.1.1] uninsane.org. DNS" nslookup uninsane.org. 1.1.1.1
|
||||||
check "uninsane.org. bootstrap DNS" nslookup uninsane.org. ovpns.uninsane.org
|
check "[OVPNS] uninsane.org. DNS" nslookup uninsane.org. "$OVPNS_IPV4"
|
||||||
|
check "[DOOF] uninsane.org. DNS" nslookup uninsane.org. "$DOOF_IPV4"
|
||||||
|
|
||||||
check "https://uninsane.org online" curl --silent --fail-with-body https://uninsane.org
|
check "https://uninsane.org online" curl --silent --fail-with-body https://uninsane.org
|
||||||
check "https://matrix.uninsane.org online" curl --silent --fail-with-body https://matrix.uninsane.org
|
check "https://matrix.uninsane.org online" curl --silent --fail-with-body https://matrix.uninsane.org
|
||||||
@@ -53,13 +93,14 @@ check "uninsane.org DMARC record" nslookup -querytype=TXT _dmarc.uninsane.org.
|
|||||||
|
|
||||||
check "servo-hn wireguard network" ping -c 1 -W 3 servo-hn
|
check "servo-hn wireguard network" ping -c 1 -W 3 servo-hn
|
||||||
|
|
||||||
check "git.uninsane.org" git ls-remote origin --quiet
|
check "git.uninsane.org" git ls-remote https://git.uninsane.org/colin/nix-files.git --quiet
|
||||||
|
|
||||||
check "ftp://uninsane.org" lftpget ftp://uninsane.org/README.md && rm README.md
|
check "ftps://ftp.uninsane.org" curl --silent ftps://ftp.uninsane.org/pub/test
|
||||||
|
check "[DOOF] ftps://ftp.uninsane.org" curl "--connect-to" "uninsane.org:80:$DOOF_IPV4:80" --silent ftps://ftp.uninsane.org/pub/test
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "systemctl --failed:"
|
echo "systemctl --failed:"
|
||||||
ssh uninsane.org systemctl -q --failed
|
runOnHost servo systemctl -q --failed
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
if [ $last_error -eq 0 ]; then
|
if [ $last_error -eq 0 ]; then
|
||||||
|
@@ -9,8 +9,10 @@ usage() {
|
|||||||
echo "usage: deploy [options] [host] [host2 ...]"
|
echo "usage: deploy [options] [host] [host2 ...]"
|
||||||
echo "options:"
|
echo "options:"
|
||||||
echo "- --action copy|switch|test (default: 'switch')"
|
echo "- --action copy|switch|test (default: 'switch')"
|
||||||
echo "- --variant light|min|''|all (default: '')"
|
echo "- --dry-run: show what would be done without actually doing it"
|
||||||
echo "- --pre: alias for --action copy --variant all all"
|
echo "- --pre: alias for --action copy --variant all all"
|
||||||
|
echo "- --reboot: reboot the target machine after deploying (whether deployment was 'successful' or not)"
|
||||||
|
echo "- --variant light|min|''|all (default: '')"
|
||||||
echo ""
|
echo ""
|
||||||
echo "common idioms:"
|
echo "common idioms:"
|
||||||
echo "- deploy all: deploy all hosts, sequentially"
|
echo "- deploy all: deploy all hosts, sequentially"
|
||||||
@@ -30,6 +32,8 @@ defaultHost="$SELF"
|
|||||||
variants=()
|
variants=()
|
||||||
defaultVariant=
|
defaultVariant=
|
||||||
nixArgs=()
|
nixArgs=()
|
||||||
|
doReboot=
|
||||||
|
dryRun=
|
||||||
addHost() {
|
addHost() {
|
||||||
if [ "$1" = all ]; then
|
if [ "$1" = all ]; then
|
||||||
# order matters:
|
# order matters:
|
||||||
@@ -57,9 +61,20 @@ parseArgs() {
|
|||||||
action=$1
|
action=$1
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
(--dry-run)
|
||||||
|
dryRun=1
|
||||||
|
;;
|
||||||
(--help)
|
(--help)
|
||||||
usage
|
usage
|
||||||
;;
|
;;
|
||||||
|
(--pre)
|
||||||
|
action=copy
|
||||||
|
defaultVariant=all
|
||||||
|
defaultHost=all
|
||||||
|
;;
|
||||||
|
(--reboot)
|
||||||
|
doReboot=1
|
||||||
|
;;
|
||||||
(--variant)
|
(--variant)
|
||||||
addVariant "$1"
|
addVariant "$1"
|
||||||
shift
|
shift
|
||||||
@@ -67,11 +82,6 @@ parseArgs() {
|
|||||||
(all|crappy|desko|lappy|moby|servo)
|
(all|crappy|desko|lappy|moby|servo)
|
||||||
addHost "$arg"
|
addHost "$arg"
|
||||||
;;
|
;;
|
||||||
(--pre)
|
|
||||||
action=copy
|
|
||||||
defaultVariant=all
|
|
||||||
defaultHost=all
|
|
||||||
;;
|
|
||||||
(*)
|
(*)
|
||||||
nixArgs+=("$arg")
|
nixArgs+=("$arg")
|
||||||
;;
|
;;
|
||||||
@@ -86,14 +96,24 @@ parseArgs() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
destructive() {
|
||||||
|
if [ -z "$dryRun" ]; then
|
||||||
|
"$@"
|
||||||
|
else
|
||||||
|
echo "dry-run: $@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
runOnTarget() {
|
runOnTarget() {
|
||||||
|
local host="$1"
|
||||||
|
shift
|
||||||
# run the command ($@) on the machine we're deploying to.
|
# 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 that's a remote machine, then do it via ssh, else local shell.
|
||||||
if [ -n "$host" ] && [ "$host" != "$SELF" ]; then
|
if [ -n "$host" ] && [ "$host" != "$SELF" ]; then
|
||||||
info "running on remote:" "$@"
|
info "running on remote ($host):" "$@"
|
||||||
ssh "$host" "$@"
|
ssh "$host" "$@"
|
||||||
else
|
else
|
||||||
info "running locally:" "$@"
|
info "running locally ($SELF):" "$@"
|
||||||
"$@"
|
"$@"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
@@ -104,7 +124,7 @@ deployOneHost() {
|
|||||||
local variant="$2"
|
local variant="$2"
|
||||||
|
|
||||||
info "building $host$variant ..."
|
info "building $host$variant ..."
|
||||||
nix-build -A "hosts.$host$variant.toplevel" --out-link "./build/result-$host$variant" "${nixArgs[@]}" || return 1
|
destructive nix-build -A "hosts.$host$variant.toplevel" --out-link "./build/result-$host$variant" "${nixArgs[@]}" || return 1
|
||||||
storePath="$(readlink ./build/result-$host$variant)"
|
storePath="$(readlink ./build/result-$host$variant)"
|
||||||
info "build $host$variant -> $storePath"
|
info "build $host$variant -> $storePath"
|
||||||
|
|
||||||
@@ -120,20 +140,24 @@ deployOneHost() {
|
|||||||
if [ -n "$host" ] && [ "$host" != "$SELF" ]; then
|
if [ -n "$host" ] && [ "$host" != "$SELF" ]; then
|
||||||
if [ -e /run/secrets/nix_signing_key ]; then
|
if [ -e /run/secrets/nix_signing_key ]; then
|
||||||
info "signing store paths ..."
|
info "signing store paths ..."
|
||||||
sudo nix store sign -r -k /run/secrets/nix_signing_key "$storePath"
|
destructive sudo nix store sign -r -k /run/secrets/nix_signing_key "$storePath"
|
||||||
else
|
else
|
||||||
info "not signing store paths: /run/secrets/nix_signing_key does not exist"
|
info "not signing store paths: /run/secrets/nix_signing_key does not exist"
|
||||||
fi
|
fi
|
||||||
# add more `-v` for more verbosity (up to 5).
|
# 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.
|
# 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.
|
# 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://$host" "$storePath" || return 1
|
destructive nix copy -vv --option builders-use-substitutes false --to "ssh-ng://$host" "$storePath" || return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "$action" ] && [ "$action" != "copy" ]; then
|
if [ -n "$action" ] && [ "$action" != "copy" ]; then
|
||||||
info "activating profile... "
|
info "activating profile... "
|
||||||
runOnTarget sudo nix-env -p /nix/var/nix/profiles/system --set "$storePath" || return 1
|
destructive runOnTarget "$host" sudo nix-env -p /nix/var/nix/profiles/system --set "$storePath" || return 1
|
||||||
runOnTarget sudo "$storePath/bin/switch-to-configuration" "$action" || return 1
|
destructive runOnTarget "$host" sudo "$storePath/bin/switch-to-configuration" "$action" || return 1
|
||||||
|
if [ -n "$doReboot" ]; then
|
||||||
|
info "rebooting $host"
|
||||||
|
destructive runOnTarget "$host" sane-reboot
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,8 +165,8 @@ deployOneHost() {
|
|||||||
parseArgs "$@"
|
parseArgs "$@"
|
||||||
|
|
||||||
failedDeploys=()
|
failedDeploys=()
|
||||||
for h in "${hosts[@]}"; do
|
for v in "${variants[@]}"; do
|
||||||
for v in "${variants[@]}"; do
|
for h in "${hosts[@]}"; do
|
||||||
deployOneHost "$h" "$v" || \
|
deployOneHost "$h" "$v" || \
|
||||||
failedDeploys+=("$h$v")
|
failedDeploys+=("$h$v")
|
||||||
done
|
done
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
#!/usr/bin/env nix-shell
|
#!/usr/bin/env nix-shell
|
||||||
#!nix-shell -i bash -p nix-update
|
#!nix-shell -i bash -p nix-update
|
||||||
|
|
||||||
|
NIX_FILES_TOP=/home/colin/nixos
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
echo "update: update rev/hash for one or more packages"
|
echo "update: update rev/hash for one or more packages"
|
||||||
echo "usage: update [options] [attr-path]"
|
echo "usage: update [options] [attr-path]"
|
||||||
@@ -44,34 +46,51 @@ getPkgs() {
|
|||||||
attrPrefix=sane
|
attrPrefix=sane
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local attrs="$(nix-env -f . --query --available --attr-path --no-name -A $attrPrefix)"
|
# nix-env doesn't seem to build anything when evaluating queries,
|
||||||
|
# but since i use Import From Derivation along paths which i also want to query,
|
||||||
|
# then i need to ensure those derivations are available for import.
|
||||||
|
debug "creating requisite .drv store paths"
|
||||||
|
nix-instantiate -A nixpkgs "$NIX_FILES_TOP"
|
||||||
|
debug "querying attributes which match '$attrPrefix'"
|
||||||
|
local attrs=$(nix-env -f "$NIX_FILES_TOP" --query --available --attr-path --no-name -A "$attrPrefix" --show-trace)
|
||||||
|
debug "got: $attrs"
|
||||||
attrsArr+=($attrs)
|
attrsArr+=($attrs)
|
||||||
}
|
}
|
||||||
|
|
||||||
updateOnePkg() {
|
updateOnePkg() {
|
||||||
local attrPath="$1"
|
local attrPath="$1"
|
||||||
|
|
||||||
if [[ "$attrPath" =~ ^"$ignore" ]]; then
|
if [ -n "$ignore" ] && [[ "$attrPath" =~ ^"$ignore" ]]; then
|
||||||
warn "ignoring $attrPath"
|
warn "ignoring $attrPath"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local updateScript="$(nix eval --raw -f . $attrPath.passthru.updateScript --apply 'builtins.concatStringsSep "'" "'"')"
|
local updateScript=$(nix eval --raw -f "$NIX_FILES_TOP" $attrPath.passthru.updateScript --apply 'builtins.concatStringsSep "'" "'"')
|
||||||
if [ -z "$updateScript" ]; then
|
if [ -z "$updateScript" ]; then
|
||||||
warn "don't know how to update '$attrPath'"
|
warn "don't know how to update '$attrPath'"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# make sure everything needed to invoke the script actually exists on disk
|
# make sure everything needed to invoke the update script exists in-store
|
||||||
nix-build -A "$attrPath.passthru.updateScript" || true
|
local context=$(nix eval --raw -f "$NIX_FILES_TOP" $attrPath.passthru.updateScript --apply 's: builtins.concatStringsSep " " (builtins.foldl'"'"' (acc: next: acc ++ next) [] (builtins.map builtins.attrNames (builtins.map builtins.getContext s)))')
|
||||||
|
for c in $context; do
|
||||||
|
debug "realizing updateScript requisite: $context"
|
||||||
|
nix-store --realize "$c" || true
|
||||||
|
done
|
||||||
|
|
||||||
local UPDATE_NIX_NAME="$(nix eval --raw -f . $attrPath.name)"
|
local UPDATE_NIX_NAME=$(nix eval --raw -f "$NIX_FILES_TOP" $attrPath.name)
|
||||||
local UPDATE_NIX_PNAME="$(nix eval --raw -f . $attrPath.pname)"
|
local UPDATE_NIX_PNAME=$(nix eval --raw -f "$NIX_FILES_TOP" $attrPath.pname)
|
||||||
local UPDATE_NIX_OLD_VERSION="$(nix eval --raw -f . $attrPath.version)"
|
local UPDATE_NIX_OLD_VERSION=$(nix eval --raw -f "$NIX_FILES_TOP" $attrPath.version)
|
||||||
info "updating: '$attrPath'"
|
info "updating: '$attrPath'"
|
||||||
debug "$updateScript"
|
debug "$updateScript"
|
||||||
|
(
|
||||||
|
# update script assumes $PWD is an entry point to a writable copy of my nix config,
|
||||||
|
# so provide that:
|
||||||
|
pushd "$NIX_FILES_TOP/integrations/nix-update"
|
||||||
# we lose spaces inside the exec args... could `nix eval` without `--raw` to fix that.
|
# we lose spaces inside the exec args... could `nix eval` without `--raw` to fix that.
|
||||||
UPDATE_NIX_NAME="$UPDATE_NIX_NAME" UPDATE_NIX_PNAME="$UPDATE_NIX_PNAME" UPDATE_NIX_OLD_VERSION="$UPDATE_NIX_OLD_VERSION" UPDATE_NIX_ATTR_PATH="$attrPath" eval $updateScript
|
UPDATE_NIX_NAME="$UPDATE_NIX_NAME" UPDATE_NIX_PNAME="$UPDATE_NIX_PNAME" UPDATE_NIX_OLD_VERSION="$UPDATE_NIX_OLD_VERSION" UPDATE_NIX_ATTR_PATH="$attrPath" eval $updateScript
|
||||||
|
popd
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
dryRun=
|
dryRun=
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"data": "ENC[AES256_GCM,data:73Bwq+HulAk89E4LrAymv8QE+kw8KViFqsD0gMAIAqeRPJP6x+CtH4/ajJtWeBrxkrW+BhA0mO57x/N/Fx+u+YxjpFh9oGiQeapBJOAmbZ6ZZAD2/3Xf4cQLknCPxCY/jMeBdvIoA3U8jn+5RgxWnlXj5cAR7oB5FyNld5c+zLO+xWOLxhds1/q4JuYZlN+nwiunw5dSZzA1IcbNJiIaogukliUBvy86QlvIKvHg9mG+60TcGvJSNXAY+YrzAmLD0rt2rkQnOS5Wn6sQIKek5sY3/68OWhWVhv151FxT5Jd90imJy84aDsL4YOYjpXNnm5WuRQkIo5ByS6HYmxWTeqzRaxPUpl0regK7yn6un/3cgiCjLL+M11Jnp4LZAco6VcvGgNA7hn2AAm2je6Kel13PPLiWsNoKPXWFdTsvYKsJu0VF4LUJGr3IEq+Xdg2PyS0qXayH0zlOAPxwY1VtA+NYaS/u4a6m+fww0YLb3UVPzh+HharIWwNgBxhrKU55KSK/34aQ8snHxTtvJBe2pGl8zs+gxdAKvF77kppUilivqJ6zm0d92kimW+a/i3x7XNVLFPPyrMKQF+qEwQUs5CoO3lwk7fmFbMJLg47C7Qxok6D2kRdCWuYA04aq1qx6ReYChoeM6vdT4rDu8OzBk2iZ6by17tBKwv5b1Jevu97pK7LTdnnsl8qu8yUAc5II5FVxkNjc8+nY8HsPrHPiDvds9bcA3JWIVC3zz2uD31bQ1lBczRFRsbXDs6WWhHUAd/VQxgQqxg9CbVFxzMod7ZFdjViMW6OZ8CcBeg7+cr4BiT9x1AICFY4AFl44buEXQ3p6OoOE492eTZSbjMIwXK+UpKXSs8cUOrp13KJBnm6/lAHI/khFN0HXon2J4WaoZmdGyZti5XpNqYrMX5P//2QvRg1FwL1CAiNUC6Uu+ueH959Nbmjom97OiHku2UICTwpSJtEgWuhtfdldVpTbPKIPPh3XoCDGpkqFtW7Yi8nl2GS2H5IpRr4CmFtLIKENuifioAOftCUOWoIJ6MuT6TmLThfCzC5KWdcWIh4r3hY0LKnz0t74Y+8EIUtgLUKLBQGKxraoca5v93Hx1YfQREYyzCIJ19foAQKg0fGrAVZ6xJ0M913JAU8+0N+XYnISJNo8s/PMDiQaISLTybSm50XoY8I28endyhpGk9XB0JgSYq1cbEK8N30yrTd/JTCCd5rArOjBFtfD6D0wD/0YNZLMPWFEun6mh6KWXeZmr/VGk9p5oI6figUUQCACXSB71LVQbh475mQl/vefSK5CxGuz1eT8eeX3bgcmfHMFm1hWB2bdo1hhP/2yLCo63fGUzYT0maPHqOMY/9QbAQcfL4AUffdFbWkspdW6w++PpVBcUfV5hraJV37LVG3dguvEy1UUGlO6YnsNpWKbY7sdPWaqd+6MYtljVHUPOj13nuK8qIvUorpRM9ZL1LrpgDTCAGO52HC5yqDfDbrmG0daFrHNWpz1lML4k8iq90hW80YIV+4JYAPr95IijHGNQ/mk/68ReX1RXHKcMzCY4DZciQntplOI3KRwTXcPiREXEIK67J3u35duUPuuw0Sc77KsqBXO+L0o4zW7sSRA58yAI73Oa8xtT3Y3/tCGTyNdNF0R6gB75pyTHdK6J0+AsK4deLizTiegFVRHOhpnm68bWTbdankpiPGKxiX6EyFHxTRQeWxDVOGjjQElmmBulqYBKtXbgaCWGiu2MIgGiayqeet2AqD1h+CbLCzo08fJcMg6fsArHjefap8sLw07jxEb4wjpKg7UIcFbLBXo31qpE/2kWgWt731lk1X/rjmT/fw5znp/tVXFLAhWiJUL78ooS0Ua3M56PVZe87YCr1Czak1l2b+vxdpT6p5ULjaLmwtYNKc0hVIPVrvYU+eyqiVtbZapdcWEXcBPlQvKCqGoieYnwMeeYRKjPuRBsONQ9gI6+NJkxt+QLQ6n7BO4yHWzAW/TGdw9GAnV1m8OANICJjU1wmntIyLX2v8CXNaZyfVFSm0O98pqVUWRVvJDAM4I9rxs/wFxQ5Eo61OZe3cx/zLxwYz/VAKcuSGNVdrp,iv:9WvW3DScrLPI3bEb7neJgWI/MDTvBfajWDtDj3rGxJs=,tag:VTDd0X5Oep/dSlZbjIO6tw==,type:str]",
|
"data": "ENC[AES256_GCM,data:9loyFBNvDB8MjARYOUYjC5Bb4bTXjNqEFTztKoECYuCWoPpcAiX1rTa2jghnwSHg+t3zALYEGGCIchzM+2A6WyAmhfg5S4kHhUL/kzSmgMFloBwsiKeMs8rVPV7YPH8MVoDvohvUocgjcf9j2sz/oC4Ng7YJkQpQB883kLfvRMP9bfuKIofl2C8EhaQ9ixgT6PwLBR1oCzWbvsFHoaWwSj4A9NDCLmKZZmNPd6cZI+WCR9Mzepz7Q0gWpGrQz+K752fmGYHAkLT8aElLmAyhugSebC5IfvrfuVPKFFmTtEGXQdAZrnAdUVSz1F60HROgxf6vCpfiNCg5YS7D6XCjNZUdlpYOt4SA4jzaocV5F5gEUXs7URD2VTJuc496QEmshzKJrclcjmBZt5rxG0ltsYxl6d/FoD2qYEptYooyuz4l/4xe5LF8e2Iz9SPBc0IFWwhFMHTXl4WfdLTuTDk26h+PPEZGP3Jlb8Nvm2X5hN3Ph/gi/Bqo8OY+x1PbqcSyGQkVwNEHZaLO8+6n7Tc7KzWrvRMgZDhf9CtIEo7btn5HhV0mu4q3bDddCXPcRMv93WAj3AQM0aFSTqrI2KEfQKulHio3KRmQJ1Nfr0SfR6oME4oljFjnEUq8Vt2VUUoHbF5Zy8ajh08MaldFZrVHVbB1ESXFQ++N8Hf6CpSkvMbfS5BW+FXwG9keqBSmKvpV1QlPHhIvy5or51/UOedYO4qnO2CGKzsbR8vcFcrdUH/6es5Of54Zw5LgL7O5w462FD/QG9qdewsMQb76q4QJUfQ6GVYm+kwF+ivwYyqBVpzrZtPUXJnInhaZ6bGcaBGL1TM1ucl768wGtzfpvWQh1k5hi6aRE7UsAoRaIgfzxcEtLAduQOsNBWrMFHYzz9zLnTUMt2GtH/CGL72myyxjmMG4jwVpCkommZ9YVf3EPzZYwr64/EVC1cooQ4QUKUk1+113LEPm16NQlZLem99Boq/L6JZJ+JCv2KTr1SqIKa8UDvIK5hpWCHiTDTMIKObLvGEAt698L6N8V2LH6dq9IGIB+W293zy7biYvD9yuHiCvR8w8ViwQsnoCSedbMzyYby8AvGmQxq1zj23kkzea4E0bSGNzzmeJHgZAM8uWcHMQ7wnvQLg0OPwl4nuom8/taIAKEtepKWzv0C7AKRCHOISplaz01ad0KgANsJFJskhUbgTJGbaocd/6QiFRns5gqWk18Dft7CDCAsVbEygT6PRlbItwBG2Wih3q2BZ8K8yU+8GMvL0/aAjSEbIKQwcXHoge9YklsDjZncqan1JfLbIrFXZO0t/SIz6Vh2gFtCTQ5smn1I1vlrA9xtoqWKSgdbhvYk+XIsL1MwWb3nWsX3vosciKPQW3POWwK+lkhWp0OQEJ/f15eZ9lvMRWyZMfHnT2DW30UwJurbB0K9J2MkPq11N5bwKW3t6AEbt0Jp+X/BLckE99Z4nlGlQ5RvFAlVHhQWc0oSAntYgq2QrqwtP3OEoevJTtyKNnodUcFN1NkWtPgwg4FsxanEWgC3ccrJoLNS99YWcyV3SuIdozyF5nqZeRQQb9bRNcGH/OQyg04TD1RWM5SiSy9p94cN7NYVmLJKwTzCK/rx1nrsV95wdrH2MhA2vPDkyEjSI0oGy6zMDbtl68l8ToFy3x3tUDHhlemEm4J77SZiNaapN/hYE591tvkWtd/xWEuOAMcPjx7XzefDIXektwoZQvCYMEZN2jQdSr6BX6fpTSkIWtkWqbcv93p9xeyska+z/TajX9Q57vl0aFeX6i7q9jnHUjEbBLqdkAxAVkvfSTYYin5hAYHRVQ5VJjWwsDQY3Aogz8p5KHXVLCS8PJlFKrMympAhF2B+1fH1+kh+PjCp1+tI7XXDPvQboV+bUCMlTKWTvE3wQdRPj8w7H/t5/kDbtzm89veIb70si9KhYN6xA0JB1x6v7YOq08neNVWv3edXouYGnwR3RtU977yTBl8CVRCVtleqAaCj1HDrBvIvw4hE5fV/OTWAjhdIPiyi/P++qINyWHUOAn9auodcszhwbu2V91LI1r//T3db6NF0T/kFexEJ2CI9t5oZKp3m+qQQ9WWPyTEleblkXUR3gYsONLCCVgl0/U9Qift9Vx9B5l/6yorU3UyB5tjmAXT6VS0eTsdNZhPN7nG6XKjOCBYy5QA/mH6ZKPD08i7lYmIyN3wrDDpGinSx69Ap41vIA2YVqjtIsKeVRFI7/qaXl4komAdUi6Fk4X4Z/PnNmb2OKvfroMI6ZEhEVpL3doHiIQkJMCW52AzH7Rvo4TJl6zN/B9nC51z272yazJwhirfcB2C81StHLHHn+v5N8DIvV7DX95slfGkhssxlIXNQ6F02fQtzxhIYxwFsFjrTYcj+0iIUnWoPDj+eOwEVX2uC9UrIwLrL6vyDoEO3XZjfVDDRmN73ds3TqWpfKb2MrsENh2g3f4W5HvfmC+2xSgcg86a14oG5t+lzl5D5CF0Ol67dkrJdVguImKf+YW9qcVQsMqTPV9FkIjAUADiBGY/kFoy72Kl/YEis6468YtLQkBwqPqqIm440JzONw+BBy6B0zIjaK34h3ydTi6AqbAnbirl+W9+i4ULPJjlc1fIsCTF8DQQGJZUPmxO1WmmBEu9gX1rMMboMTKsN9ZuXjxN/GlfKy9QMXBgA0NY6huAhYSe8bBEYJaNCafQZds4PSo9hQ9EnV4/LVK2/8usQ==,iv:jlCa29fKe/HWq3z17ymOrgYt50g3EjzOYYln6ywLWLg=,tag:MFtkrsTjtYCqZ+AYloffGQ==,type:str]",
|
||||||
"sops": {
|
"sops": {
|
||||||
"kms": null,
|
"kms": null,
|
||||||
"gcp_kms": null,
|
"gcp_kms": null,
|
||||||
@@ -43,8 +43,8 @@
|
|||||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAwcXlNMlFUaWhXbmlPc0Ir\nT2hRd3BMQUZ1TkVkWGlrdjJ5ZnhPdWhPbTFBCmdzazV5bzV0aTNNaTFpaDlBOWU5\naUdBTFlEeWM5T1Q3UGhrZWdGZkVPUzQKLS0tIEloSFVJd2JCNmY0VkpqTGppRE1p\nQ2Mvekx0RWN5dlhxWmwwaDVnUUVDdFEKJgyAed3yBaIBwfxypG7RKV+u80SiQV89\ntU4YMw0j7GvnkVhPenB8q0w3yrslCh35GDvKkaMpfp8jVFIpcrRXtA==\n-----END AGE ENCRYPTED FILE-----\n"
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAwcXlNMlFUaWhXbmlPc0Ir\nT2hRd3BMQUZ1TkVkWGlrdjJ5ZnhPdWhPbTFBCmdzazV5bzV0aTNNaTFpaDlBOWU5\naUdBTFlEeWM5T1Q3UGhrZWdGZkVPUzQKLS0tIEloSFVJd2JCNmY0VkpqTGppRE1p\nQ2Mvekx0RWN5dlhxWmwwaDVnUUVDdFEKJgyAed3yBaIBwfxypG7RKV+u80SiQV89\ntU4YMw0j7GvnkVhPenB8q0w3yrslCh35GDvKkaMpfp8jVFIpcrRXtA==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"lastmodified": "2023-10-28T10:34:31Z",
|
"lastmodified": "2024-06-23T17:59:53Z",
|
||||||
"mac": "ENC[AES256_GCM,data:GS492dizmvoW6uCO4Wz+YzwFbtM6LfUdEgx7DzSbHG3hM/q3k5LW8E4HzxkBkDUylL5GS3FUWCADcoKe+JWqX3TUqQDqqrYScAVcE5e9TM2mZ12U6xz1SU8Tc5DkqQuUgrv/pvaJBI1UlEEdFkSOSIBzHZ5C7xW0WsNFauC9HFI=,iv:rnDBUWzieefIpES4WjWWEiAY3LtKkfazAgHaSoJ9VEw=,tag:n4b6kctXHHKiQfQAeQeFTw==,type:str]",
|
"mac": "ENC[AES256_GCM,data:ZKGwqisn27YnSjroCxrCxIoR5vkYgnfzVoLNbxfnti+RFUX67eBfcj0jOc8KqfAWyNOCMlWlfOZ1AonIOqsBqhPrX1LEyOdhrCp+M7zfhnIheOJFfqVyUzN0O7N0PIj696tM8HgYg2OX+YLCvZvFf9DSrK92RsRCkWSfH34OKd8=,iv:AByoesqgTOoet2BR01d6G1CBx0o/PDGj2kbxNU5St20=,tag:Um2vz1mdD5gu4CifY4QuTA==,type:str]",
|
||||||
"pgp": null,
|
"pgp": null,
|
||||||
"unencrypted_suffix": "_unencrypted",
|
"unencrypted_suffix": "_unencrypted",
|
||||||
"version": "3.8.1"
|
"version": "3.8.1"
|
||||||
|
52
secrets/common/ols.toml.bin
Normal file
52
secrets/common/ols.toml.bin
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"data": "ENC[AES256_GCM,data:gQxh1msPLuraF/GEczHeheDUvWZcvVyKZDY/mD85LJHhjnnqPWGOrIvZjFaH1bVg71VAgGSIdC66UnoptaKxA6j6BE0aB6SOsvLQOxXdvEELTECT0Gy17wLXNM7tVFUKIFreLM3gykZXYnT44IzkjLDduIt5TfvgvE/Jr2gLQpPq0ooVgcExuueSTGHYxkKEvHb+TwaLSbg/ndWiq1W7i0ZaGt4FIOt/9gHqMcOBfpKp/IqyVidjG4aXLLcb96gsOqS/sv+acVr9rM3ZfEWyWbwWoNTiKn3AnFU/l6Cj/TmGcDa8M+WfwWTpy8DqEzQ6CH2jBtuYs5w+O7ccAZREE2+x5OE8S7NhEluoO+DSmHZfk1tywLtSlS6cWmrhdbSc2xqKxPDQln+y5gjYHD95ccQrdK1TbSgkYu2AH/Jpjcmm/3z6v8NJDtL8VRQh9Q4S20QMTN8D3B14AGKXc8ulHDnw7wJpN6QF38b51vqGK8Jjc3hlPnRnS2pBOxVfa5BZFCgBaVfxqpRSBA85wQQzpjdHG/lQ8uwtDHR4fGsafPFOOhzhA+aUKTIZ/oCEnf9X8jJ6O/j5k0NO/QUU5H36/V9Hh+bywyacT9fgqPuhu68R/eb/aNaaY6bebYiaIaxHulpzAyobAbC9ls3VMYk7S4TxSRnhLp1kxpmiO32n5eCiW/tEm8Xxa4N7KXwfyWccwHjm0Y5jOyKhXtK60lv8/vR2zesOPiyOh57fCx8V5R/GO1RpY3Wd94gBsXULGOb+H4DD+fuSCWAr4iajD8ZGoFj6p2yFxP5RBUDffO08ahF6HCe29sqAf4DoVGFFvlulj1JB0436zy44y+/tOf0+ztOuWP4ERzpfgVY8pWUgOQpwKJ3bEoojUokqhHUvXG1RQzKohOcInn4EUmi9L7aLVfijw6IwpJXAXUfbnuacBalAhrpQhmU7THs94HSXZ56yUk0ukbmNxoHoaG378RApoPJVXKQL68IYfV05+rr7i+w096TiSFbvSWC1/6cULwVNQMQdOasiiJVkNeM5D9ecbB+QIr8edcRX5vvhtwRiqoqNOJNwlKGshLK+gJJQRikD+IrQpWcrHWZBICF+Vax4GAxNk1jfOtfDzDE7RkOi8v3aZLBmxszi8MIlAbvjQijr52iFiBLoSTCftQ+uOXVt1aNkOe2JDX1gHzZdUJIZyssgwPFB12ggWRB8VxQHY6K8T34J3M77GvELjpyx07L4elQpg/WqhX/qZXNHjdk3AdbCUYWYqvlMXa7JXq1HTHMpnPsq0sNyqpUARD3OuQB9bDrfsrOYkgTU8J8OOfbdr+bsCYINDDVb4unior256z9h7f+mY28YiJeHJBg0YgCHLK5rdZ23qIbxDiGkYuLPLVAhAVXdbjgcNYTldKBzjq9GPdqoXWvtWZgCewzxf2FPMrPMqw7A+vnn2exZt0v/F9xGFL/885I0Tnbq7UpTesvJ4dqj8qIkUjmpVXUcbuEPDMMIt3o+5Tf9JquhAL1V1DscY77N3SoHe+8NdZLP4hgP7/t7LB757BVf86ZUsDvIpfprjNUoJ7wwnmK6yMtHH2026wrRx25eHNFqbLVVzVeg28grXWEV3xU1y0S5qvheAp1aotFTHP9lrS/LGlpIqnNnDpod9ecdkk/VEeib1+QG19SEBYcVYjmGvLpYNg+EZS8w1Ca+P1kvNXRUojeyUKk5aVCyo10f/PE/kKaFmF42+BZxaxf6GY+TwTSvDlsqfDnzn8bse/fTmjLsYNlXEl4Xgb+idQfrGTUaP+t13zAFsqDKGap7F25xKyjY+feZo9iNosgVAaaplP0CHFpEYAxnTtC+YIZ78Yjo3H2dVWVo9o3JAPKlsSEccjgy5rtSXqhmHK0GFEtnNDj8teOFJ+y/EwxEMiFK7XAZpnvdSEuEZeIJH10hWb0Yo52hZrotx11Xy0t3C9LqiW4kjzpLlMpfgFJNtsd/+9L5RwIClvJnmrVcpe9xCvDQ5c4/3Wk/zykx3qIxgNUXVkDjqbKGcSJJOorwPDquPmDSmzu70qaMn0FdCdlWzq2iwdsGcrp9PSH/C52IvM9XooNPrrq/Wt/grC/lhhUrhGAS6G6tXgmJe767IdaMCFysHgn4hlXWQ3KzJaIJC1cJoFPZgczcGBdqnsa3gxXOqOc3vBcABB2lNpPp2wIqHkvZZBzTHIgkNSdW74QzrsNn2yF3aKP+wTHuaeDeVGWW5VFwzwGJGY/50vlel5JWP7TtBnHQ2gU6QUnswF/Cv6D92kdh92GqSC1pzzQ/weq3+4XCN+QpDqLf7jZfR7YUv2iJup3cpfo/++ixTD4uPSuYf4zsyAec4HgV2IXQwCm32pST4eQfFPa2j3wE33K05mqMCnNL9CqbXf1emImnZLPlDeZuDQ+CuuZ7iC5EpO6+bgjnIuZypVlVaVp0axNNfyUmL25kTdz1EdXXLkMKLUJld6EyFnnwJPfcBBBtmkL5j7Slxjdp/nAW3zr8Buk2zzCMnJzkVkgpSet4IbBLbz1+f0MBG5JKVGoNyeeFrIC/ZDcjHQd6LMbss9QVhPhANl9Msj4WS/Qfe4TI8He8Qy9izIRltakF78uLfI3zcjk+6ZIC42vc9N3MKjLHJ0/W5S3s4wEAtgIRGf33b7wtShE8st5vYGOiwTY/IGfpsySGKJwaEvQssRRjUWlOCmOCJthrd9zK2Xh40lGAgkUnPI/36orVF+hV1jLHHuyznVMwfXb1syXLdIYevoUJPCxs7Jnkj2re5G2v/7YXFlvMLqewNrBg,iv:jbrfq9CYDgVQUK3od8eFjm6+KOTcypeTF3itq72XBBE=,tag:1jbIG1GaI0pSxIsErUXoBg==,type:str]",
|
||||||
|
"sops": {
|
||||||
|
"kms": null,
|
||||||
|
"gcp_kms": null,
|
||||||
|
"azure_kv": null,
|
||||||
|
"hc_vault": null,
|
||||||
|
"age": [
|
||||||
|
{
|
||||||
|
"recipient": "age1tnl4jfgacwkargzeqnhzernw29xx8mkv73xh6ufdyde6q7859slsnzf24x",
|
||||||
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBwQU9melI3VDB1aEtOYW5E\nbDRDL1BWMExsbjlxckFYZWtWMTlPZ29yR25BCjV5a0VyNHdQbXpMVGljZENxM2hl\nRlBRYTZoWnE4VVNQb05MTm1pcGsrVk0KLS0tIFFhOTE2S1luLzMxWnlmbGlzbEh5\nS1dFZU1JRG8vdDFjL3g5eEJ3ckZKNEkK1S1FMhvKCNbWlmDdOIgnn3+uAcK9bs9G\nvlfoV6xzAdAJDlckPLDipfS0x6HKUkN9PdA2K+SYJJ9673xegZ/xeQ==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recipient": "age1j2pqnl8j0krdzk6npe93s4nnqrzwx978qrc0u570gzlamqpnje9sc8le2g",
|
||||||
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBHWkZva1JreGpGWTBzcVBz\nSXlxakpjVk5ycndQRnUzYm9ZMXRXcFZTK3c0CmRBUFowNDlTMEgwVkpkOEQvNms4\nY2NRZ3g2SnJhdEJjbDlKZzlmVjFFL1EKLS0tIEFlL3VoUGJUaGY2SzFPT09QSXNS\ndElTQ2ZnNzJIRG51NmNjWldZYVFLV0EKOMJvXC9HjtNDuJELLfbByES0yVpliAnq\n7sWQRkY3K/J/F6cW5++LepZWMmMY7YmnKzIphreBeZncYUYx4JuzUQ==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recipient": "age1z8fauff34cdecr6sjkre260luzxcca05kpcwvhx988d306tpcejsp63znu",
|
||||||
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBTMmVSU1ByanlMYUR4TlFN\nYml4SjU4b1ZRR3VDazFlN3p2ZndacFZXUmo0CkhhTWtzVyszaUR4dG9nWmhoSHFn\nSWNtaGN2SzhtVWNkSkdUUEdqWmNyWTQKLS0tIHJnblV3Z082dVNLRUtNN216eTJL\nRXlKRVd0UGE3SE1rdUQ1NVlCSUFjL1UKf6Y6lvki5rFjqrPCLCL8SulHh3yg0Cns\nDdMsZgqLql1O3Cua4CHjSi+08hsz0RT9qqzcNr798Bqj5JnvFSTUPw==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recipient": "age1zsrsvd7j6l62fjxpfd2qnhqlk8wk4p8r0dtxpe4sdgnh2474095qdu7xj9",
|
||||||
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBpZGs5MHZqOFVoSzQxdEFC\nem1yVzZCditGekRMYzFCcWsvVk0vYlBubEJVCmV2ZHZqR3BMTW9Pa1RGWXVFdkV4\nbnNlKy9PUSswTVlETmxjMDAxakp2cmsKLS0tIFJDZlZzYmwwaFlua2FGeTdTUGtZ\nUXNoVFpwT21uR0NpcTFzZEgzby9YR0UKmZFKfm6ypb9SZBW0vTtw6SDL6TgZnsp3\ns41G4S4PS/8XyAHKrLlgGiJK/Fv3bMULG54D2TKQSbuYRhKXT9nWoA==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recipient": "age1hl50ufuxnqy0jnk8fqeu4tclh4vte2xn2d59pxff0gun20vsmv5sp78chj",
|
||||||
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2Y3Frc2RleThrK1NmRTcx\nUkxvV29GNXllU0tXOWQ2YVkwSTloUjFCaUZFCk5iaVpJLy8vVUh5cGJBODVNWXNG\nRmtZYTZKK044S0VpSGdhSVBZZlZGY0kKLS0tIDg5c0IyTjNlU2FRYy9ueVYxbXIz\nZjZ0MGoweEtwQ2lUWDlqcEZvdThzYjQKMi0m7wyRoCoIbS/HBl6xaVEeK4TvYzkW\ny/rDK0IZuBAr9I1/avdDGM8LWo2EBSmqEqW6jooMmdrkkjwJE6lwVA==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recipient": "age1vnw7lnfpdpjn62l3u5nyv5xt2c965k96p98kc43mcnyzpetrts9q54mc9v",
|
||||||
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBMc0grUDVodGp5YWtpb1RS\nVUpweUUzcGxIbVpPYTJma3RaSDUwM2MvUlRJCmdacFE3OEQ1am53Q2hzYjRRaFRI\nSXlrbzVacDVlMnp1YlgrckExSG1yWTQKLS0tIE55R1QxOUJyN0N5Vmh1cG1iN2xC\nclNrWUF6TFRsTlBIUE9mNFZmQXNrMnMKVTrGgIrxA0pAjGOZyHJpwl6TBPBqXbGz\nUPgPFUUfLpUA+soyAQGE+/4bD4WFWwnro8B9zj0ahZYj1GvC8ddbig==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recipient": "age1w7mectcjku6x3sd8plm8wkn2qfrhv9n6zhzlf329e2r2uycgke8qkf9dyn",
|
||||||
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtT3NIUE1ZeXN1ZnkxaXJ4\nUzJNRFZWMHg0WWNJeFJ0NUlITGMwYVlLajEwCkd4WGJXbjdwcnJPeDdrZEFyaDds\nZjR2eEtkc1ZpdzVFeG9LajBIcVVNTVEKLS0tIEwzd1ppa3EvSHNYdUhjcHVnZ3Fh\ncWJwUkZVM1QwTHp6a1N2MzVQcUFSeGMK0PFJNAkpQEKQiNarb9dDr7MwtvGZeke6\n7vBhMsJ1lmCMu0TshNNbOmQpre2J6ZnGDnvOrpy8IQukym2py9KvXQ==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recipient": "age1tzlyex2z6t88tg9h82943e39shxhmqeyr7ywhlwpdjmyqsndv3qq27x0rf",
|
||||||
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzSkFLMnF0ZGdQV056VTdw\neUhyYnhGbzJORTh2ZlhXM0RzaWNjL3VybGlNCmNBVGlxSHIwWkxhZEg0ZXI3RFN0\nSk1XU0dTbFJ5NENGUnh0K3NRUCtzY1kKLS0tIGh2TnhuSERKb3B2c0oramhPelhm\nT1BBODhUaDVJbjg2Nlh3dnNPOUtvWmMKDyrOAsUZXp/hhXWczlf+VZRcz4mzaYZF\n3bW7w/nkojmMfKwKWvEYsunNPJSV+In1CTkvv8e8E1aIq5jithYe6Q==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recipient": "age18vq5ktwgeaysucvw9t67drqmg5zd5c5k3le34yqxckkfj7wqdqgsd4ejmt",
|
||||||
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBGVmZEU2ozMjBNTmVMU1NG\ndFIzSndXcmZQVWphU1BWSURCVGhGQVhPUDE4CmZMS1dFU1BxL3FYQ25ETDJJWjhu\nTWwrd2VzemxoWGhJTzFXUzh4d0o2c2sKLS0tIEt1cmg1WHFQWjV6UlRvWEJhQVFh\nQjV0MU5zYm1US1Y0dUR1RldZeUxkcmcKgbhTfvnP+krgib2xcZ85szzH/EvgxAwH\nqKlmN5J8DmllxR+O97hwCdDMu3vC5Vx+lp7Rxs85xFHu2quw37liGw==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"lastmodified": "2024-06-21T13:47:00Z",
|
||||||
|
"mac": "ENC[AES256_GCM,data:vY0UHEkQKgWaevRo+9FxBjdSSFkAPMFt6ABSsZfArVqjBRLAo5O53aIV40KTDahd5UP25UgjPE8TVqXpWo/CVXct3M6SOnbSAlO9NGHkygyM5xk8PqzA6TXfPw7XzInvwMiAIuRNqJRAyKktHYmuiFMlEnhPhuCB6GLUdqpZEmQ=,iv:sK+QmTpl9y0UrruTqTb8oNcKrZrn9fgmldMxxyqr+vg=,tag:aeJeVIjwrcXAVOqMHNgIfQ==,type:str]",
|
||||||
|
"pgp": null,
|
||||||
|
"unencrypted_suffix": "_unencrypted",
|
||||||
|
"version": "3.8.1"
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user