Compare commits
278 Commits
wip-emulat
...
dev-export
Author | SHA1 | Date | |
---|---|---|---|
15e09573d5 | |||
d6479ca148 | |||
cf9558f166 | |||
68bce9c8b7 | |||
913201b9cd | |||
3f748164e4 | |||
ded5d94d69 | |||
815a8b52b6 | |||
639a4cfe50 | |||
b2af4e8983 | |||
ff39fc5d95 | |||
9fea007d4f | |||
f44a094d1d | |||
ec6f90eb44 | |||
bbe583637f | |||
29eab151a1 | |||
a7c5daf8a5 | |||
a23dea03a9 | |||
45e5f3ecca | |||
8bcba8802f | |||
3e2e0ccc1c | |||
c14d88f1ea | |||
e72e847147 | |||
073879e523 | |||
bf302f70f1 | |||
a045eaa181 | |||
b83b2ce0cc | |||
377aec7e07 | |||
9d50a6669a | |||
bded6c9562 | |||
5520c74921 | |||
589c005bc4 | |||
d64a213ec2 | |||
18c940962e | |||
e01b1f35fc | |||
60030860e5 | |||
90894087e5 | |||
bdcccbd894 | |||
b64cf408fb | |||
eaca5b9889 | |||
1c265b2073 | |||
fa98ba86bc | |||
53aee9e651 | |||
d4a305f5bb | |||
fd39efe31f | |||
3b2f4b6f72 | |||
9a16942b16 | |||
fe47d68fd3 | |||
deaee833cf | |||
8d03881109 | |||
e476adfdf5 | |||
4201aa7466 | |||
a85d594c89 | |||
7b98cd3d50 | |||
d256a0b647 | |||
c87ba7f670 | |||
e4e5df80f1 | |||
02f409451d | |||
9f2c7b90ce | |||
559c551752 | |||
304482cc9b | |||
ad9db91812 | |||
1c7997e1ef | |||
deefcaae9a | |||
562008f3c0 | |||
2584d62b28 | |||
dc64193a62 | |||
a7f8089ed8 | |||
e8e63167d2 | |||
c056191de1 | |||
f2a597f698 | |||
7b637f976b | |||
39a378c517 | |||
0f9dfb9f8a | |||
ab7f2fb1ec | |||
a892c364c6 | |||
a5c829fa96 | |||
e844cf5970 | |||
999c6fd880 | |||
2aa4bdd5a6 | |||
05801f298f | |||
0fd1ec861b | |||
37d0473b7f | |||
aaca46c485 | |||
30a6a1c1c2 | |||
2c39ac3015 | |||
cc6a0dd8b3 | |||
fbf62f0531 | |||
c96b951895 | |||
34294341d7 | |||
cdc8885e60 | |||
41416cd184 | |||
3c32246d9a | |||
6862d084ac | |||
6eb3626203 | |||
5f808eab5c | |||
fe15c0b097 | |||
e4fbe9d03c | |||
de09d54c64 | |||
5bf117fc05 | |||
f734797628 | |||
236470dc33 | |||
555627dad5 | |||
49c5ddd9f3 | |||
a43ccaac64 | |||
91c02aec9a | |||
681d3d5520 | |||
f945dc42fa | |||
cc6f33b928 | |||
2f83e73139 | |||
53ccb96234 | |||
a0d6139e50 | |||
90abadf7c4 | |||
7f1e959ece | |||
794df4d762 | |||
d6b262a28e | |||
0cc518e523 | |||
8780dff794 | |||
0f881006e7 | |||
5d349ce042 | |||
940711878b | |||
75048efcf3 | |||
8cc5199d9b | |||
3f60bacd38 | |||
8fb705dde4 | |||
79777cd4ae | |||
fabd1e3b64 | |||
bcb6beef05 | |||
34336e4ade | |||
a518e56cf1 | |||
6cc7655180 | |||
0a15aad6d7 | |||
1d8bee2856 | |||
6894d5828b | |||
35bc222552 | |||
16b5b6840f | |||
1a7837d740 | |||
607bfbe452 | |||
c2b85bd6b8 | |||
c3bc0ec645 | |||
89b5e8145d | |||
0edab7ed64 | |||
c8a3814f6a | |||
9ddac508e2 | |||
3245f8f94c | |||
8be1f43c23 | |||
e29e26605b | |||
7bd6c0c14d | |||
d7c912386f | |||
e7e86cae95 | |||
b083ce87be | |||
17b90fc697 | |||
4fc59fa2ac | |||
e87cda2e55 | |||
2c4d30b5ec | |||
d0af645af8 | |||
a1f79dc18a | |||
ff65a697a9 | |||
ef881b1392 | |||
debea8fa5b | |||
8a9acbaeea | |||
8869ec7bca | |||
dc0268736a | |||
6f9c2a846e | |||
3cb00840de | |||
6a2603a4ea | |||
69efecb2ef | |||
056e6d358e | |||
793baf0e0f | |||
721899258a | |||
4f9d84cd82 | |||
a462180d3c | |||
58f2d87959 | |||
a50b8e6373 | |||
4ec947d549 | |||
6751a74063 | |||
6118a18200 | |||
d223d4be06 | |||
ab7ec9bd74 | |||
7b70b5ec86 | |||
db99043753 | |||
8f87e49606 | |||
5557107259 | |||
1b5c870798 | |||
a5162651b7 | |||
b9868512d6 | |||
8432d9c9ed | |||
5d4f94f218 | |||
7e9d5d99c7 | |||
487e64b09b | |||
5e350b810f | |||
5fb3a6be81 | |||
dbec4b8f32 | |||
f8b559bef1 | |||
7d9d0ce8b5 | |||
7857f123a4 | |||
e3ba156fe1 | |||
c824751682 | |||
e5520437a5 | |||
c6211fe48f | |||
54d6c9008d | |||
05e5edcce3 | |||
3249baccfa | |||
274682cf85 | |||
31a700f6a7 | |||
91a6fc32ef | |||
135b87a091 | |||
6b9484f611 | |||
7a612b701d | |||
c69fb690f1 | |||
1ef73dd69d | |||
54afa1aec5 | |||
72c3c939e2 | |||
67d8e89556 | |||
07408813db | |||
436760a592 | |||
5c758df032 | |||
d12a41bfa9 | |||
8ec22b6320 | |||
95d04467a8 | |||
dd53de96fe | |||
8089334ea9 | |||
5bbb3678ed | |||
4e7ffe3140 | |||
d2842484fd | |||
a8932b5a72 | |||
a283d1ee21 | |||
d41d802d83 | |||
8a0efb3e40 | |||
b013123669 | |||
264657d623 | |||
8ad4ee4341 | |||
664b21e5f1 | |||
163a7af328 | |||
4adeae6d85 | |||
9168803008 | |||
3f9c0d1b60 | |||
cc35317b54 | |||
006070d08f | |||
19f6a98d31 | |||
301abbe155 | |||
dab3a2d0a9 | |||
3a00e93dc3 | |||
4c4b0ce920 | |||
b9259ff8b9 | |||
e2ed37196f | |||
b343d5d83a | |||
9bbff0d7a7 | |||
014fb5a633 | |||
76d8921bdf | |||
b7f23a032c | |||
68be1ba2a1 | |||
5a6bb475c4 | |||
132e15cb9f | |||
07c0878d11 | |||
b993479ada | |||
8dc568d52e | |||
44ee7cd3db | |||
2773cd8406 | |||
9bb26e0199 | |||
8d772074ba | |||
18c6ad0663 | |||
24a91acd0a | |||
bec5241326 | |||
2b5365d774 | |||
e377a9f05b | |||
2f53e94cc9 | |||
75770cd34b | |||
a4860c3963 | |||
4b072ecbe5 | |||
3423f103fc | |||
c3bb776149 | |||
d31aac4d19 | |||
378e72ceb7 | |||
d86be97ced | |||
44388b132a | |||
cd6b112d33 | |||
8eb6be863a |
66
TODO.md
66
TODO.md
@@ -1,7 +1,10 @@
|
|||||||
## BUGS
|
## BUGS
|
||||||
|
- mpv UI is sometimes blank for audio/podcasts?
|
||||||
|
- i think it's when the audio file has no thumbnail?
|
||||||
- why i need to manually restart `wireguard-wg-ovpns` on servo periodically
|
- why i need to manually restart `wireguard-wg-ovpns` on servo periodically
|
||||||
- else DNS fails
|
- else DNS fails
|
||||||
- fix epiphany URL bar input on moby
|
- fix epiphany URL bar input on moby
|
||||||
|
- sxmo: wvkbd: missing font for icons on the 3rd page
|
||||||
|
|
||||||
## REFACTORING:
|
## REFACTORING:
|
||||||
|
|
||||||
@@ -12,7 +15,7 @@
|
|||||||
|
|
||||||
### roles
|
### roles
|
||||||
- allow any host to take the role of `uninsane.org`
|
- allow any host to take the role of `uninsane.org`
|
||||||
- will make it easier to test new services?
|
- will make it easier to test new services?
|
||||||
|
|
||||||
### upstreaming
|
### upstreaming
|
||||||
- split out a sxmo module usable by NUR consumers
|
- split out a sxmo module usable by NUR consumers
|
||||||
@@ -23,27 +26,38 @@
|
|||||||
- REVIEW/integrate jellyfin dataDir config: <https://github.com/NixOS/nixpkgs/pull/233617>
|
- REVIEW/integrate jellyfin dataDir config: <https://github.com/NixOS/nixpkgs/pull/233617>
|
||||||
- remove `libsForQt5.callPackage` broadly: <https://github.com/NixOS/nixpkgs/issues/180841>
|
- remove `libsForQt5.callPackage` broadly: <https://github.com/NixOS/nixpkgs/issues/180841>
|
||||||
|
|
||||||
|
#### upstreaming to non-nixpkgs repos
|
||||||
|
- gtk: build schemas even on cross compilation: <https://github.com/NixOS/nixpkgs/pull/247844>
|
||||||
|
- sxmo: add new app entries
|
||||||
|
|
||||||
|
|
||||||
## IMPROVEMENTS:
|
## IMPROVEMENTS:
|
||||||
### security/resilience
|
### security/resilience
|
||||||
- validate duplicity backups!
|
- validate duplicity backups!
|
||||||
- encrypt more ~ dirs (~/archives, ~/records, ..?)
|
- encrypt more ~ dirs (~/archives, ~/records, ..?)
|
||||||
- best to do this after i know for sure i have good backups
|
- best to do this after i know for sure i have good backups
|
||||||
- have `sane.programs` be wrapped such that they run in a cgroup?
|
- have `sane.programs` be wrapped such that they run in a cgroup?
|
||||||
- at least, only give them access to the portion of the fs they *need*.
|
- at least, only give them access to the portion of the fs they *need*.
|
||||||
- Android takes approach of giving each app its own user: could hack that in here.
|
- Android takes approach of giving each app its own user: could hack that in here.
|
||||||
- **systemd-run** takes a command and runs it in a temporary scope (cgroup)
|
- **systemd-run** takes a command and runs it in a temporary scope (cgroup)
|
||||||
- presumably uses the same options as systemd services
|
- presumably uses the same options as systemd services
|
||||||
- see e.g. <https://github.com/NixOS/nixpkgs/issues/113903#issuecomment-857296349>
|
- see e.g. <https://github.com/NixOS/nixpkgs/issues/113903#issuecomment-857296349>
|
||||||
- flatpak does this, somehow
|
- flatpak does this, somehow
|
||||||
- apparmor? SElinux? (desktop) "portals"?
|
- apparmor? SElinux? (desktop) "portals"?
|
||||||
- see Spectrum OS; Alyssa Ross; etc
|
- see Spectrum OS; Alyssa Ross; etc
|
||||||
- bubblewrap-based sandboxing: <https://github.com/nixpak/nixpak>
|
- bubblewrap-based sandboxing: <https://github.com/nixpak/nixpak>
|
||||||
- canaries for important services
|
- canaries for important services
|
||||||
- e.g. daily email checks; daily backup checks
|
- e.g. daily email checks; daily backup checks
|
||||||
- integrate `nix check` into Gitea actions?
|
- integrate `nix check` into Gitea actions?
|
||||||
|
|
||||||
### user experience
|
### user experience
|
||||||
|
- moby: sxmo: fix youtube scripts (package youtube-cli)
|
||||||
|
- moby: tune GPS
|
||||||
|
- run only geoclue, and not gpsd, to save power?
|
||||||
|
- 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?
|
||||||
|
- manually do smoothing, as some layer between mepo and geoclue/gpsd?
|
||||||
- neovim: set up language server (lsp; rnix-lsp; nvim-lspconfig)
|
- neovim: set up language server (lsp; rnix-lsp; nvim-lspconfig)
|
||||||
- Helix: make copy-to-system clipboard be the default
|
- Helix: make copy-to-system clipboard be the default
|
||||||
- firefox/librewolf: persist history
|
- firefox/librewolf: persist history
|
||||||
@@ -53,29 +67,37 @@
|
|||||||
- especially, make the menubar collapsible
|
- especially, make the menubar collapsible
|
||||||
- try Gradience tool specifically for theming adwaita? <https://linuxphoneapps.org/apps/com.github.gradienceteam.gradience/>
|
- try Gradience tool specifically for theming adwaita? <https://linuxphoneapps.org/apps/com.github.gradienceteam.gradience/>
|
||||||
- package Nix/NixOS docs for Zeal
|
- package Nix/NixOS docs for Zeal
|
||||||
- install [doc-browser](https://github.com/qwfy/doc-browser)
|
- install [doc-browser](https://github.com/qwfy/doc-browser)
|
||||||
- this supports both dash (zeal) *and* the datasets from <https://devdocs.io> (which includes nix!)
|
- this supports both dash (zeal) *and* the datasets from <https://devdocs.io> (which includes nix!)
|
||||||
- install [devhelp](https://wiki.gnome.org/Apps/Devhelp) (gnome)
|
- install [devhelp](https://wiki.gnome.org/Apps/Devhelp) (gnome)
|
||||||
- have xdg-open parse `<repo:...> URIs (or adjust them so that it _can_ parse)
|
- have xdg-open parse `<repo:...> URIs (or adjust them so that it _can_ parse)
|
||||||
- sane-bt-search: show details like 5.1 vs stereo, h264 vs h265
|
- sane-bt-search: show details like 5.1 vs stereo, h264 vs h265
|
||||||
- uninsane.org: make URLs relative to allow local use (and as offline homepage)
|
- uninsane.org: make URLs relative to allow local use (and as offline homepage)
|
||||||
- email: fix so that local mail doesn't go to junk
|
- email: fix so that local mail doesn't go to junk
|
||||||
- git sendmail flow adds the DKIM signatures, but gets delivered locally w/o having the sig checked, so goes into Junk
|
- git sendmail flow adds the DKIM signatures, but gets delivered locally w/o having the sig checked, so goes into Junk
|
||||||
- could change junk filter from "no DKIM success" to explicit "DKIM failed"
|
- could change junk filter from "no DKIM success" to explicit "DKIM failed"
|
||||||
|
- sxmo: don't put all deps on PATH
|
||||||
|
- maybe: use resholve to hard-code them
|
||||||
|
- this is the most "correct", but least patchable
|
||||||
|
- maybe: express each invocation as a function in sxmo_common.sh
|
||||||
|
- this will require some patching to handle `exec <foo>` style
|
||||||
|
- maybe: save original PATH and reset it before invoking user files
|
||||||
|
|
||||||
### perf
|
### perf
|
||||||
- add `pkgs.impure-cached.<foo>` package set to build things with ccache enabled
|
- add `pkgs.impure-cached.<foo>` package set to build things with ccache enabled
|
||||||
- every package here can be auto-generated, and marked with some env var so that it doesn't pollute the pure package set
|
- every package here can be auto-generated, and marked with some env var so that it doesn't pollute the pure package set
|
||||||
- would be super handy for package prototyping!
|
- would be super handy for package prototyping!
|
||||||
- why does nixos-rebuild switch take 5 minutes when net is flakey?
|
- why does nixos-rebuild switch take 5 minutes when net is flakey?
|
||||||
- trying to auto-mount servo?
|
- trying to auto-mount servo?
|
||||||
- something to do with systemd services restarting/stalling
|
- something to do with systemd services restarting/stalling
|
||||||
- maybe wireguard & its refresh operation, specifically?
|
- maybe wireguard & its refresh operation, specifically?
|
||||||
- get moby to build without binfmt emulation (i.e. make all emulation explicit)
|
- get moby to build without binfmt emulation (i.e. make all emulation explicit)
|
||||||
- then i can distribute builds across servo + desko, and also allow servo to pull packages from desko w/o worrying about purity
|
- then i can distribute builds across servo + desko, and also allow servo to pull packages from desko w/o worrying about purity
|
||||||
|
|
||||||
|
|
||||||
## NEW FEATURES:
|
## NEW FEATURES:
|
||||||
- migrate MAME cabinet to nix
|
- migrate MAME cabinet to nix
|
||||||
- boot it from PXE from servo?
|
- boot it from PXE from servo?
|
||||||
|
- deploy to new server, and use it as a remote builder
|
||||||
- enable IPv6
|
- enable IPv6
|
||||||
|
- package lemonade lemmy app: <https://linuxphoneapps.org/apps/ml.mdwalters.lemonade/>
|
||||||
|
18
flake.lock
generated
18
flake.lock
generated
@@ -69,11 +69,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs-stable": {
|
"nixpkgs-stable": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1690066826,
|
"lastModified": 1693097136,
|
||||||
"narHash": "sha256-6L2qb+Zc0BFkh72OS9uuX637gniOjzU6qCDBpjB2LGY=",
|
"narHash": "sha256-fBZSMdBaoZ0INFbyZ5s0DOF7zDNcLsLxgkwdDh3l9Pc=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "ce45b591975d070044ca24e3003c830d26fea1c8",
|
"rev": "9117c4e9dc117a6cd0319cca40f2349ed333669d",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -85,11 +85,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs-unpatched": {
|
"nixpkgs-unpatched": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1691006197,
|
"lastModified": 1693377291,
|
||||||
"narHash": "sha256-DbtxVWPt+ZP5W0Usg7jAyTomIM//c3Jtfa59Ht7AV8s=",
|
"narHash": "sha256-vYGY9bnqEeIncNarDZYhm6KdLKgXMS+HA2mTRaWEc80=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "66aedfd010204949cb225cf749be08cb13ce1813",
|
"rev": "e7f38be3775bab9659575f192ece011c033655f0",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -116,11 +116,11 @@
|
|||||||
"nixpkgs-stable": "nixpkgs-stable"
|
"nixpkgs-stable": "nixpkgs-stable"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1690199016,
|
"lastModified": 1693404499,
|
||||||
"narHash": "sha256-yTLL72q6aqGmzHq+C3rDp3rIjno7EJZkFLof6Ika7cE=",
|
"narHash": "sha256-cx/7yvM/AP+o/3wPJmA9W9F+WHemJk5t+Xcr+Qwkqhg=",
|
||||||
"owner": "Mic92",
|
"owner": "Mic92",
|
||||||
"repo": "sops-nix",
|
"repo": "sops-nix",
|
||||||
"rev": "c36df4fe4bf4bb87759b1891cab21e7a05219500",
|
"rev": "d9c5dc41c4b1f74c77f0dbffd0f3a4ebde447b7a",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
20
flake.nix
20
flake.nix
@@ -298,6 +298,26 @@
|
|||||||
program = ''${deployScript "servo" "servo" "switch"}'';
|
program = ''${deployScript "servo" "servo" "switch"}'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
sync-moby = {
|
||||||
|
# copy music from the current device to moby
|
||||||
|
# TODO: should i actually sync from /mnt/servo-media/Music instead of the local drive?
|
||||||
|
type = "app";
|
||||||
|
program = builtins.toString (pkgs.writeShellScript "sync-to-moby" ''
|
||||||
|
sudo mount /mnt/moby-home
|
||||||
|
${pkgs.sane-scripts.sync-music}/bin/sane-sync-music ~/Music /mnt/moby-home/Music
|
||||||
|
'');
|
||||||
|
};
|
||||||
|
|
||||||
|
sync-lappy = {
|
||||||
|
# copy music from servo to lappy
|
||||||
|
# can run this from any device that has ssh access to lappy
|
||||||
|
type = "app";
|
||||||
|
program = builtins.toString (pkgs.writeShellScript "sync-to-lappy" ''
|
||||||
|
sudo mount /mnt/lappy-home
|
||||||
|
${pkgs.sane-scripts.sync-music}/bin/sane-sync-music /mnt/servo-media/Music /mnt/lappy-home/Music
|
||||||
|
'');
|
||||||
|
};
|
||||||
|
|
||||||
check-nur = {
|
check-nur = {
|
||||||
# `nix run '.#check-nur'`
|
# `nix run '.#check-nur'`
|
||||||
# validates that my repo can be included in the Nix User Repository
|
# validates that my repo can be included in the Nix User Repository
|
||||||
|
@@ -28,7 +28,7 @@
|
|||||||
# see <repo:mil/sxmo-utils:scripts/deviceprofiles>
|
# see <repo:mil/sxmo-utils:scripts/deviceprofiles>
|
||||||
# SXMO_DEVICE_NAME = "pine64,pinephone-1.2";
|
# SXMO_DEVICE_NAME = "pine64,pinephone-1.2";
|
||||||
};
|
};
|
||||||
package = pkgs.sxmo-utils.overrideAttrs (base: {
|
package = pkgs.sxmo-utils-latest.overrideAttrs (base: {
|
||||||
postPatch = (base.postPatch or "") + ''
|
postPatch = (base.postPatch or "") + ''
|
||||||
# after volume-button navigation mode, restore full keyboard functionality
|
# after volume-button navigation mode, restore full keyboard functionality
|
||||||
cp ${./xkb_mobile_normal_buttons} ./configs/xkb/xkb_mobile_normal_buttons
|
cp ${./xkb_mobile_normal_buttons} ./configs/xkb/xkb_mobile_normal_buttons
|
||||||
|
@@ -44,6 +44,7 @@
|
|||||||
sane.programs.tuiApps.enableFor.user.colin = false; # visidata, others, don't compile well
|
sane.programs.tuiApps.enableFor.user.colin = false; # visidata, others, don't compile well
|
||||||
# disabled for faster deploys
|
# disabled for faster deploys
|
||||||
sane.programs.soundconverter.enableFor.user.colin = false;
|
sane.programs.soundconverter.enableFor.user.colin = false;
|
||||||
|
sane.programs.eg25-control.enableFor.user.colin = true;
|
||||||
|
|
||||||
# sane.programs.firefox.mime.priority = 300; # prefer other browsers when possible
|
# sane.programs.firefox.mime.priority = 300; # prefer other browsers when possible
|
||||||
# HACK/TODO: make `programs.P.env.VAR` behave according to `mime.priority`
|
# HACK/TODO: make `programs.P.env.VAR` behave according to `mime.priority`
|
||||||
@@ -112,6 +113,15 @@
|
|||||||
services.pipewire.environment.ALSA_CONFIG_UCM2 = ucm-env;
|
services.pipewire.environment.ALSA_CONFIG_UCM2 = ucm-env;
|
||||||
services.pipewire-pulse.environment.ALSA_CONFIG_UCM2 = ucm-env;
|
services.pipewire-pulse.environment.ALSA_CONFIG_UCM2 = ucm-env;
|
||||||
services.wireplumber.environment.ALSA_CONFIG_UCM2 = ucm-env;
|
services.wireplumber.environment.ALSA_CONFIG_UCM2 = ucm-env;
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: move elsewhere...
|
||||||
|
services.ModemManager.serviceConfig = {
|
||||||
|
# N.B.: the extra "" in ExecStart serves to force upstream ExecStart to be ignored
|
||||||
|
ExecStart = [ "" "${pkgs.modemmanager}/bin/ModemManager --debug" ];
|
||||||
|
# --debug sets DEBUG level logging: so reset
|
||||||
|
ExecStartPost = [ "${pkgs.modemmanager}/bin/mmcli --set-logging=INFO" ];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.udev.extraRules = let
|
services.udev.extraRules = let
|
||||||
@@ -127,37 +137,4 @@
|
|||||||
'';
|
'';
|
||||||
|
|
||||||
hardware.opengl.driSupport = true;
|
hardware.opengl.driSupport = true;
|
||||||
|
|
||||||
services.xserver.displayManager.job.preStart = let
|
|
||||||
dmesg = "${pkgs.util-linux}/bin/dmesg";
|
|
||||||
grep = "${pkgs.gnugrep}/bin/grep";
|
|
||||||
modprobe = "${pkgs.kmod}/bin/modprobe";
|
|
||||||
in ''
|
|
||||||
# common boot failure:
|
|
||||||
# blank screen (no backlight even), with the following log:
|
|
||||||
# ```syslog
|
|
||||||
# sun8i-dw-hdmi 1ee0000.hdmi: Couldn't get the HDMI PHY
|
|
||||||
# ...
|
|
||||||
# sun4i-drm display-engine: Couldn't bind all pipelines components
|
|
||||||
# ...
|
|
||||||
# sun8i-dw-hdmi: probe of 1ee0000.hdmi failed with error -17
|
|
||||||
# ```
|
|
||||||
#
|
|
||||||
# in particular, that `probe ... failed` occurs *only* on failed boots
|
|
||||||
# (the other messages might sometimes occur even on successful runs?)
|
|
||||||
#
|
|
||||||
# reloading the sun8i hdmi driver usually gets the screen on, showing boot text.
|
|
||||||
# then restarting display-manager.service gets us to the login.
|
|
||||||
#
|
|
||||||
# NB: the above log is default level. though less specific, there's a `err` level message that also signals this:
|
|
||||||
# sun4i-drm display-engine: failed to bind 1ee0000.hdmi (ops sun8i_dw_hdmi_ops [sun8i_drm_hdmi]): -17
|
|
||||||
|
|
||||||
if (${dmesg} --kernel --level err --color=never --notime | ${grep} -q 'sun4i-drm display-engine: failed to bind 1ee0000.hdmi')
|
|
||||||
then
|
|
||||||
echo "reprobing sun8i_drm_hdmi"
|
|
||||||
# if a command here fails it errors the whole service, so prefer to log instead
|
|
||||||
${modprobe} -r sun8i_drm_hdmi || echo "failed to unload sun8i_drm_hdmi"
|
|
||||||
${modprobe} sun8i_drm_hdmi || echo "failed to load sub8i_drm_hdmi"
|
|
||||||
fi
|
|
||||||
'';
|
|
||||||
}
|
}
|
||||||
|
@@ -15,10 +15,28 @@
|
|||||||
#
|
#
|
||||||
# geoclue somehow fits in here as a geospatial provider that leverages GPS and also other sources like radio towers
|
# geoclue somehow fits in here as a geospatial provider that leverages GPS and also other sources like radio towers
|
||||||
|
|
||||||
{ ... }:
|
{ 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.enable = true;
|
||||||
services.gpsd.devices = [ "/dev/ttyUSB1" ];
|
services.gpsd.devices = [ "/dev/ttyUSB1" ];
|
||||||
|
|
||||||
# TODO: enable eg25-manager, and bring online both the modem and GPS on boot
|
# test geoclue2 by building `geoclue2-with-demo-agent`
|
||||||
|
# and running "${geoclue2-with-demo-agent}/libexec/geoclue-2/demos/where-am-i"
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
sane.services.eg25-control.enable = true;
|
||||||
}
|
}
|
||||||
|
@@ -1,71 +1,56 @@
|
|||||||
{ lib, pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
let
|
let
|
||||||
# use the last commit on the 5.18 branch (5.18.14)
|
dmesg = "${pkgs.util-linux}/bin/dmesg";
|
||||||
# manjaro's changes between kernel patch versions tend to be minimal if any.
|
grep = "${pkgs.gnugrep}/bin/grep";
|
||||||
manjaroBase = "https://gitlab.manjaro.org/manjaro-arm/packages/core/linux/-/raw/25bd828cd47b1c6e09fcbcf394a649b89d2876dd";
|
modprobe = "${pkgs.kmod}/bin/modprobe";
|
||||||
manjaroPatch = name: sha256: {
|
ensureHWReady = ''
|
||||||
inherit name;
|
# common boot failure:
|
||||||
patch = pkgs.fetchpatch {
|
# blank screen (no backlight even), with the following log:
|
||||||
inherit name;
|
# ```syslog
|
||||||
url = "${manjaroBase}/${name}?inline=false";
|
# sun8i-dw-hdmi 1ee0000.hdmi: Couldn't get the HDMI PHY
|
||||||
inherit sha256;
|
# ...
|
||||||
};
|
# sun4i-drm display-engine: Couldn't bind all pipelines components
|
||||||
};
|
# ...
|
||||||
|
# sun8i-dw-hdmi: probe of 1ee0000.hdmi failed with error -17
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
# in particular, that `probe ... failed` occurs *only* on failed boots
|
||||||
|
# (the other messages might sometimes occur even on successful runs?)
|
||||||
|
#
|
||||||
|
# reloading the sun8i hdmi driver usually gets the screen on, showing boot text.
|
||||||
|
# then restarting display-manager.service gets us to the login.
|
||||||
|
#
|
||||||
|
# NB: the above log is default level. though less specific, there's a `err` level message that also signals this:
|
||||||
|
# sun4i-drm display-engine: failed to bind 1ee0000.hdmi (ops sun8i_dw_hdmi_ops [sun8i_drm_hdmi]): -17
|
||||||
|
# NB: this is the most common, but not the only, failure mode for `display-manager`.
|
||||||
|
# another error seems characterized by these dmesg logs, in which reprobing sun8i_drm_hdmi does not fix:
|
||||||
|
# ```syslog
|
||||||
|
# sun6i-mipi-dsi 1ca0000.dsi: Couldn't get the MIPI D-PHY
|
||||||
|
# sun4i-drm display-engine: Couldn't bind all pipelines components
|
||||||
|
# sun6i-mipi-dsi 1ca0000.dsi: Couldn't register our component
|
||||||
|
# ```
|
||||||
|
|
||||||
# the idea for patching off Manjaro's kernel comes from jakewaksbaum:
|
if (${dmesg} --kernel --level err --color=never --notime | ${grep} -q 'sun4i-drm display-engine: failed to bind 1ee0000.hdmi')
|
||||||
# - https://git.sr.ht/~jakewaksbaum/pi/tree/af20aae5653545d6e67a459b59ee3e1ca8a680b0/item/kernel/default.nix
|
then
|
||||||
# - he later abandoned this, i think because he's using the Pinephone Pro which received mainline support.
|
echo "reprobing sun8i_drm_hdmi"
|
||||||
manjaroPatches = [
|
# if a command here fails it errors the whole service, so prefer to log instead
|
||||||
(manjaroPatch
|
${modprobe} -r sun8i_drm_hdmi || echo "failed to unload sun8i_drm_hdmi"
|
||||||
"1001-arm64-dts-allwinner-add-hdmi-sound-to-pine-devices.patch"
|
${modprobe} sun8i_drm_hdmi || echo "failed to load sub8i_drm_hdmi"
|
||||||
"sha256-DApd791A+AxB28Ven/MVAyuyVphdo8KQDx8O7oxVPnc="
|
fi
|
||||||
)
|
'';
|
||||||
# these patches below are critical to enable wifi (RTL8723CS)
|
|
||||||
# - the alternative is a wholly forked kernel by megi/megous:
|
|
||||||
# - https://xnux.eu/howtos/build-pinephone-kernel.html#toc-how-to-build-megi-s-pinehpone-kernel
|
|
||||||
# - i don't know if these patches are based on megi's or original
|
|
||||||
(manjaroPatch
|
|
||||||
"2001-Bluetooth-Add-new-quirk-for-broken-local-ext-features.patch"
|
|
||||||
"sha256-CExhJuUWivegxPdnzKINEsKrMFx/m/1kOZFmlZ2SEOc="
|
|
||||||
)
|
|
||||||
(manjaroPatch
|
|
||||||
"2002-Bluetooth-btrtl-add-support-for-the-RTL8723CS.patch"
|
|
||||||
"sha256-dDdvOphTcP/Aog93HyH+L9m55laTgtjndPSE4/rnzUA="
|
|
||||||
)
|
|
||||||
(manjaroPatch
|
|
||||||
"2004-arm64-dts-allwinner-enable-bluetooth-pinetab-pinepho.patch"
|
|
||||||
"sha256-o43P3WzXyHK1PF+Kdter4asuyGAEKO6wf5ixcco2kCQ="
|
|
||||||
)
|
|
||||||
# XXX: this one has a Makefile, which hardcodes /sbin/depmod:
|
|
||||||
# - drivers/staging/rtl8723cs/Makefile
|
|
||||||
# - not sure if this is problematic?
|
|
||||||
(manjaroPatch
|
|
||||||
"2005-staging-add-rtl8723cs-driver.patch"
|
|
||||||
"sha256-6ywm3dQQ5JYl60CLKarxlSUukwi4QzqctCj3tVgzFbo="
|
|
||||||
)
|
|
||||||
];
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
# use Megi's kernel:
|
|
||||||
# even with the Manjaro patches, stock 5.18 has a few issues on Pinephone:
|
|
||||||
# - no battery charging
|
|
||||||
# - phone rotation sensor is off by 90 degrees
|
|
||||||
# - ambient light sensor causes screen brightness to be shakey
|
|
||||||
# - phosh greeter may not appear after wake from sleep
|
|
||||||
boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux-megous;
|
boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux-megous;
|
||||||
|
# boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux-manjaro;
|
||||||
|
# boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux_latest;
|
||||||
|
|
||||||
# alternatively, use nixos' kernel and add the stuff we want:
|
# alternatively, apply patches directly to stock nixos kernel:
|
||||||
# # cross-compilation optimization:
|
|
||||||
# boot.kernelPackages =
|
|
||||||
# let p = (import nixpkgs { localSystem = "x86_64-linux"; });
|
|
||||||
# in p.pkgsCross.aarch64-multiplatform.linuxPackages_5_18;
|
|
||||||
# # non-cross:
|
|
||||||
# # boot.kernelPackages = pkgs.linuxPackages_5_18;
|
|
||||||
|
|
||||||
# boot.kernelPatches = manjaroPatches ++ [
|
# boot.kernelPatches = manjaroPatches ++ [
|
||||||
# (patchDefconfig kernelConfig)
|
# (patchDefconfig kernelConfig)
|
||||||
# ];
|
# ];
|
||||||
|
|
||||||
|
# configure nixos to build a compressed kernel image, since it doesn't usually do that for aarch64 target.
|
||||||
|
# without this i run out of /boot space in < 10 generations
|
||||||
nixpkgs.hostPlatform.linux-kernel = {
|
nixpkgs.hostPlatform.linux-kernel = {
|
||||||
# defaults:
|
# defaults:
|
||||||
name = "aarch64-multiplatform";
|
name = "aarch64-multiplatform";
|
||||||
@@ -80,4 +65,7 @@ in
|
|||||||
target = "Image.gz"; # <-- compress the kernel image
|
target = "Image.gz"; # <-- compress the kernel image
|
||||||
# target = "zImage"; # <-- confuses other parts of nixos :-(
|
# target = "zImage"; # <-- confuses other parts of nixos :-(
|
||||||
};
|
};
|
||||||
|
|
||||||
|
services.xserver.displayManager.job.preStart = ensureHWReady;
|
||||||
|
systemd.services.greetd.preStart = ensureHWReady;
|
||||||
}
|
}
|
||||||
|
@@ -167,7 +167,7 @@ in
|
|||||||
WVKBD_LANDSCAPE_LAYERS = "landscape,special,emoji";
|
WVKBD_LANDSCAPE_LAYERS = "landscape,special,emoji";
|
||||||
WVKBD_LAYERS = "full,special,emoji";
|
WVKBD_LAYERS = "full,special,emoji";
|
||||||
};
|
};
|
||||||
package = pkgs.sxmo-utils.overrideAttrs (base: {
|
package = pkgs.sxmo-utils-latest.overrideAttrs (base: {
|
||||||
postPatch = (base.postPatch or "") + ''
|
postPatch = (base.postPatch or "") + ''
|
||||||
cat <<EOF >> ./configs/default_hooks/sxmo_hook_start.sh
|
cat <<EOF >> ./configs/default_hooks/sxmo_hook_start.sh
|
||||||
# rotate UI based on physical display angle by default
|
# rotate UI based on physical display angle by default
|
||||||
|
@@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
{
|
{
|
||||||
sane.persist.root-on-tmpfs = true;
|
sane.persist.root-on-tmpfs = true;
|
||||||
|
# increase /tmp space (defaults to 50% of RAM) for building large nix things.
|
||||||
|
# even the stock `nixpkgs.linux` consumes > 16 GB of tmp
|
||||||
|
fileSystems."/tmp".options = [ "size=32G" ];
|
||||||
|
|
||||||
fileSystems."/nix" = {
|
fileSystems."/nix" = {
|
||||||
device = "/dev/disk/by-uuid/cc81cca0-3cc7-4d82-a00c-6243af3e7776";
|
device = "/dev/disk/by-uuid/cc81cca0-3cc7-4d82-a00c-6243af3e7776";
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
./email
|
./email
|
||||||
./ejabberd.nix
|
./ejabberd.nix
|
||||||
./freshrss.nix
|
./freshrss.nix
|
||||||
./ftp
|
./export
|
||||||
./gitea.nix
|
./gitea.nix
|
||||||
./goaccess.nix
|
./goaccess.nix
|
||||||
./ipfs.nix
|
./ipfs.nix
|
||||||
@@ -18,7 +18,6 @@
|
|||||||
./lemmy.nix
|
./lemmy.nix
|
||||||
./matrix
|
./matrix
|
||||||
./navidrome.nix
|
./navidrome.nix
|
||||||
./nfs.nix
|
|
||||||
./nixserve.nix
|
./nixserve.nix
|
||||||
./nginx.nix
|
./nginx.nix
|
||||||
./pict-rs.nix
|
./pict-rs.nix
|
||||||
|
@@ -17,73 +17,86 @@
|
|||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
# XXX: avatar support works in MUCs but not DMs
|
# XXX: avatar support works in MUCs but not DMs
|
||||||
# lib.mkIf false
|
let
|
||||||
|
# TODO: this range could be larger, but right now that's costly because each element is its own UPnP forward
|
||||||
|
# TURN port range (inclusive)
|
||||||
|
turnPortLow = 49152;
|
||||||
|
turnPortHigh = 49167;
|
||||||
|
turnPortRange = lib.range turnPortLow turnPortHigh;
|
||||||
|
in
|
||||||
{
|
{
|
||||||
sane.persist.sys.plaintext = [
|
sane.persist.sys.plaintext = [
|
||||||
{ user = "ejabberd"; group = "ejabberd"; path = "/var/lib/ejabberd"; }
|
{ user = "ejabberd"; group = "ejabberd"; path = "/var/lib/ejabberd"; }
|
||||||
];
|
];
|
||||||
sane.ports.ports."3478" = {
|
sane.ports.ports = lib.mkMerge ([
|
||||||
protocol = [ "tcp" "udp" ];
|
{
|
||||||
visibleTo.lan = true;
|
"3478" = {
|
||||||
visibleTo.wan = true;
|
protocol = [ "tcp" "udp" ];
|
||||||
description = "colin-xmpp-stun-turn";
|
visibleTo.lan = true;
|
||||||
};
|
visibleTo.wan = true;
|
||||||
sane.ports.ports."5222" = {
|
description = "colin-xmpp-stun-turn";
|
||||||
protocol = [ "tcp" ];
|
};
|
||||||
visibleTo.lan = true;
|
"5222" = {
|
||||||
visibleTo.wan = true;
|
protocol = [ "tcp" ];
|
||||||
description = "colin-xmpp-client-to-server";
|
visibleTo.lan = true;
|
||||||
};
|
visibleTo.wan = true;
|
||||||
sane.ports.ports."5223" = {
|
description = "colin-xmpp-client-to-server";
|
||||||
protocol = [ "tcp" ];
|
};
|
||||||
visibleTo.lan = true;
|
"5223" = {
|
||||||
visibleTo.wan = true;
|
protocol = [ "tcp" ];
|
||||||
description = "colin-xmpps-client-to-server"; # XMPP over TLS
|
visibleTo.lan = true;
|
||||||
};
|
visibleTo.wan = true;
|
||||||
sane.ports.ports."5269" = {
|
description = "colin-xmpps-client-to-server"; # XMPP over TLS
|
||||||
protocol = [ "tcp" ];
|
};
|
||||||
visibleTo.wan = true;
|
"5269" = {
|
||||||
description = "colin-xmpp-server-to-server";
|
protocol = [ "tcp" ];
|
||||||
};
|
visibleTo.wan = true;
|
||||||
sane.ports.ports."5270" = {
|
description = "colin-xmpp-server-to-server";
|
||||||
protocol = [ "tcp" ];
|
};
|
||||||
visibleTo.wan = true;
|
"5270" = {
|
||||||
description = "colin-xmpps-server-to-server"; # XMPP over TLS
|
protocol = [ "tcp" ];
|
||||||
};
|
visibleTo.wan = true;
|
||||||
sane.ports.ports."5280" = {
|
description = "colin-xmpps-server-to-server"; # XMPP over TLS
|
||||||
protocol = [ "tcp" ];
|
};
|
||||||
visibleTo.lan = true;
|
"5280" = {
|
||||||
visibleTo.wan = true;
|
protocol = [ "tcp" ];
|
||||||
description = "colin-xmpp-bosh";
|
visibleTo.lan = true;
|
||||||
};
|
visibleTo.wan = true;
|
||||||
sane.ports.ports."5281" = {
|
description = "colin-xmpp-bosh";
|
||||||
protocol = [ "tcp" ];
|
};
|
||||||
visibleTo.lan = true;
|
"5281" = {
|
||||||
visibleTo.wan = true;
|
protocol = [ "tcp" ];
|
||||||
description = "colin-xmpp-bosh-https";
|
visibleTo.lan = true;
|
||||||
};
|
visibleTo.wan = true;
|
||||||
sane.ports.ports."5349" = {
|
description = "colin-xmpp-bosh-https";
|
||||||
protocol = [ "tcp" ];
|
};
|
||||||
visibleTo.lan = true;
|
"5349" = {
|
||||||
visibleTo.wan = true;
|
protocol = [ "tcp" ];
|
||||||
description = "colin-xmpp-stun-turn-over-tls";
|
visibleTo.lan = true;
|
||||||
};
|
visibleTo.wan = true;
|
||||||
sane.ports.ports."5443" = {
|
description = "colin-xmpp-stun-turn-over-tls";
|
||||||
protocol = [ "tcp" ];
|
};
|
||||||
visibleTo.lan = true;
|
"5443" = {
|
||||||
visibleTo.wan = true;
|
protocol = [ "tcp" ];
|
||||||
description = "colin-xmpp-web-services"; # file uploads, websockets, admin
|
visibleTo.lan = true;
|
||||||
};
|
visibleTo.wan = true;
|
||||||
|
description = "colin-xmpp-web-services"; # file uploads, websockets, admin
|
||||||
# TODO: forward these TURN ports!
|
};
|
||||||
networking.firewall.allowedTCPPortRanges = [{
|
}
|
||||||
from = 49152; # TURN
|
] ++ (builtins.map
|
||||||
to = 49408;
|
(port: {
|
||||||
}];
|
"${builtins.toString port}" = let
|
||||||
networking.firewall.allowedUDPPortRanges = [{
|
count = port - turnPortLow + 1;
|
||||||
from = 49152; # TURN
|
numPorts = turnPortHigh - turnPortLow + 1;
|
||||||
to = 49408;
|
in {
|
||||||
}];
|
protocol = [ "tcp" "udp" ];
|
||||||
|
visibleTo.lan = true;
|
||||||
|
visibleTo.wan = true;
|
||||||
|
description = "colin-xmpp-turn-${builtins.toString count}-of-${builtins.toString numPorts}";
|
||||||
|
};
|
||||||
|
})
|
||||||
|
turnPortRange
|
||||||
|
));
|
||||||
|
|
||||||
# provide access to certs
|
# provide access to certs
|
||||||
# TODO: this should just be `acme`. then we also add nginx to the `acme` group.
|
# TODO: this should just be `acme`. then we also add nginx to the `acme` group.
|
||||||
@@ -272,8 +285,8 @@
|
|||||||
module: ejabberd_stun
|
module: ejabberd_stun
|
||||||
transport: tcp
|
transport: tcp
|
||||||
use_turn: true
|
use_turn: true
|
||||||
turn_min_port: 49152
|
turn_min_port: ${builtins.toString turnPortLow}
|
||||||
turn_max_port: 65535
|
turn_max_port: ${builtins.toString turnPortHigh}
|
||||||
turn_ipv4_address: %ANATIVE%
|
turn_ipv4_address: %ANATIVE%
|
||||||
-
|
-
|
||||||
# STUN+TURN UDP
|
# STUN+TURN UDP
|
||||||
@@ -281,8 +294,8 @@
|
|||||||
module: ejabberd_stun
|
module: ejabberd_stun
|
||||||
transport: udp
|
transport: udp
|
||||||
use_turn: true
|
use_turn: true
|
||||||
turn_min_port: 49152
|
turn_min_port: ${builtins.toString turnPortLow}
|
||||||
turn_max_port: 65535
|
turn_max_port: ${builtins.toString turnPortHigh}
|
||||||
turn_ipv4_address: %ANATIVE%
|
turn_ipv4_address: %ANATIVE%
|
||||||
-
|
-
|
||||||
# STUN+TURN TLS over TCP
|
# STUN+TURN TLS over TCP
|
||||||
@@ -292,8 +305,8 @@
|
|||||||
tls: true
|
tls: true
|
||||||
certfile: /var/lib/acme/uninsane.org/full.pem
|
certfile: /var/lib/acme/uninsane.org/full.pem
|
||||||
use_turn: true
|
use_turn: true
|
||||||
turn_min_port: 49152
|
turn_min_port: ${builtins.toString turnPortLow}
|
||||||
turn_max_port: 65535
|
turn_max_port: ${builtins.toString turnPortHigh}
|
||||||
turn_ipv4_address: %ANATIVE%
|
turn_ipv4_address: %ANATIVE%
|
||||||
|
|
||||||
# TODO: enable mod_fail2ban
|
# TODO: enable mod_fail2ban
|
||||||
|
42
hosts/by-name/servo/services/export/default.nix
Normal file
42
hosts/by-name/servo/services/export/default.nix
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
{ config, ... }:
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./nfs.nix
|
||||||
|
./sftpgo.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
fileSystems."/var/export/media" = {
|
||||||
|
# everything in here could be considered publicly readable (based on the viewer's legal jurisdiction)
|
||||||
|
device = "/var/lib/uninsane/media";
|
||||||
|
options = [ "rbind" ];
|
||||||
|
};
|
||||||
|
fileSystems."/var/export/playground" = {
|
||||||
|
device = config.fileSystems."/mnt/persist/ext".device;
|
||||||
|
fsType = "btrfs";
|
||||||
|
options = [
|
||||||
|
"subvol=export-playground"
|
||||||
|
"compress=zstd"
|
||||||
|
"defaults"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
sane.fs."/var/export/README.md" = {
|
||||||
|
wantedBy = [ "nfs.service" "sftpgo.service" ];
|
||||||
|
file.text = ''
|
||||||
|
- media/ read-only: Videos, Music, Books, etc
|
||||||
|
- playground/ read-write: use it to share files with other users of this server
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
# sane.fs."/var/lib/sftpgo/export/playground/README.md" = {
|
||||||
|
# wantedBy = [ "nfs.service" "sftpgo.service" ];
|
||||||
|
# file.text = ''
|
||||||
|
# this directory is intentionally read+write by anyone.
|
||||||
|
# there are no rules, except a server-level quota:
|
||||||
|
# - share files
|
||||||
|
# - write poetry
|
||||||
|
# - be a friendly troll
|
||||||
|
# '';
|
||||||
|
# };
|
||||||
|
}
|
@@ -56,12 +56,6 @@
|
|||||||
#
|
#
|
||||||
# 10.0.0.0/8 to export (readonly) both to LAN (unencrypted) and wg vpn (encrypted)
|
# 10.0.0.0/8 to export (readonly) both to LAN (unencrypted) and wg vpn (encrypted)
|
||||||
services.nfs.server.exports = ''
|
services.nfs.server.exports = ''
|
||||||
/var/nfs/export 10.78.79.0/22(ro,crossmnt,fsid=0,subtree_check) 10.0.10.0/24(rw,no_root_squash,crossmnt,fsid=0,subtree_check)
|
/var/export 10.78.79.0/22(ro,crossmnt,fsid=0,subtree_check) 10.0.10.0/24(rw,no_root_squash,crossmnt,fsid=0,subtree_check)
|
||||||
'';
|
'';
|
||||||
|
|
||||||
fileSystems."/var/nfs/export/media" = {
|
|
||||||
# everything in here could be considered publicly readable (based on the viewer's legal jurisdiction)
|
|
||||||
device = "/var/lib/uninsane/media";
|
|
||||||
options = [ "rbind" ];
|
|
||||||
};
|
|
||||||
}
|
}
|
193
hosts/by-name/servo/services/export/sftpgo.nix
Normal file
193
hosts/by-name/servo/services/export/sftpgo.nix
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
# docs:
|
||||||
|
# - <https://github.com/drakkan/sftpgo>
|
||||||
|
# - config options: <https://github.com/drakkan/sftpgo/blob/main/docs/full-configuration.md>
|
||||||
|
# - config defaults: <https://github.com/drakkan/sftpgo/blob/main/sftpgo.json>
|
||||||
|
# - nixos options: <repo:nixos/nixpkgs:nixos/modules/services/web-apps/sftpgo.nix>
|
||||||
|
# - nixos example: <repo:nixos/nixpkgs:nixos/tests/sftpgo.nix>
|
||||||
|
#
|
||||||
|
# sftpgo is a FTP server that also supports WebDAV, SFTP, and web clients.
|
||||||
|
#
|
||||||
|
# TODO: change umask so sftpgo-created files default to 644.
|
||||||
|
# - it does indeed appear that the 600 is not something sftpgo is explicitly doing.
|
||||||
|
#
|
||||||
|
# TODO: enforce a "quota" by placing /playground on a btrfs subvolume
|
||||||
|
# - sane.persist API could expose a `subvolume` option to make this feel natural
|
||||||
|
|
||||||
|
|
||||||
|
{ config, lib, pkgs, sane-lib, ... }:
|
||||||
|
let
|
||||||
|
# user permissions:
|
||||||
|
# - see <repo:drakkan/sftpgo:internal/dataprovider/user.go>
|
||||||
|
# - "*" = grant all permissions
|
||||||
|
# - read-only perms:
|
||||||
|
# - "list" = list files and directories
|
||||||
|
# - "download"
|
||||||
|
# - rw perms:
|
||||||
|
# - "upload"
|
||||||
|
# - "overwrite" = allow uploads to replace existing files
|
||||||
|
# - "delete" = delete files and directories
|
||||||
|
# - "delete_files"
|
||||||
|
# - "delete_dirs"
|
||||||
|
# - "rename" = rename files and directories
|
||||||
|
# - "rename_files"
|
||||||
|
# - "rename_dirs"
|
||||||
|
# - "create_dirs"
|
||||||
|
# - "create_symlinks"
|
||||||
|
# - "chmod"
|
||||||
|
# - "chown"
|
||||||
|
# - "chtimes" = change atime/mtime (access and modification times)
|
||||||
|
#
|
||||||
|
# home_dir:
|
||||||
|
# - it seems (empirically) that a user can't cd above their home directory.
|
||||||
|
# though i don't have a reference for that in the docs.
|
||||||
|
authResponseSuccess = {
|
||||||
|
status = 1;
|
||||||
|
username = "anonymous";
|
||||||
|
expiration_date = 0;
|
||||||
|
home_dir = "/var/export";
|
||||||
|
# uid/gid 0 means to inherit sftpgo uid.
|
||||||
|
# - i.e. users can't read files which Linux user `sftpgo` can't read
|
||||||
|
# - uploaded files belong to Linux user `sftpgo`
|
||||||
|
# other uid/gid values aren't possible for localfs backend, unless i let sftpgo use `sudo`.
|
||||||
|
uid = 0;
|
||||||
|
gid = 0;
|
||||||
|
# uid = 65534;
|
||||||
|
# gid = 65534;
|
||||||
|
max_sessions = 0;
|
||||||
|
# quota_*: 0 means to not use SFTP's quota system
|
||||||
|
quota_size = 0;
|
||||||
|
quota_files = 0;
|
||||||
|
permissions = {
|
||||||
|
"/" = [ "list" "download" ];
|
||||||
|
"/playground" = [
|
||||||
|
# read-only:
|
||||||
|
"list"
|
||||||
|
"download"
|
||||||
|
# write:
|
||||||
|
"upload"
|
||||||
|
"overwrite"
|
||||||
|
"delete"
|
||||||
|
"rename"
|
||||||
|
"create_dirs"
|
||||||
|
"create_symlinks"
|
||||||
|
# intentionally omitted:
|
||||||
|
# "chmod"
|
||||||
|
# "chown"
|
||||||
|
# "chtimes"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
upload_bandwidth = 0;
|
||||||
|
download_bandwidth = 0;
|
||||||
|
filters = {
|
||||||
|
allowed_ip = [];
|
||||||
|
denied_ip = [];
|
||||||
|
};
|
||||||
|
public_keys = [];
|
||||||
|
# other fields:
|
||||||
|
# ? groups
|
||||||
|
# ? virtual_folders
|
||||||
|
};
|
||||||
|
authResponseFail = {
|
||||||
|
username = "";
|
||||||
|
};
|
||||||
|
authSuccessJson = pkgs.writeText "sftp-auth-success.json" (builtins.toJSON authResponseSuccess);
|
||||||
|
authFailJson = pkgs.writeText "sftp-auth-fail.json" (builtins.toJSON authResponseFail);
|
||||||
|
unwrappedAuthProgram = pkgs.static-nix-shell.mkBash {
|
||||||
|
pname = "sftpgo_external_auth_hook";
|
||||||
|
src = ./.;
|
||||||
|
pkgs = [ "coreutils" ];
|
||||||
|
};
|
||||||
|
authProgram = pkgs.writeShellScript "sftpgo-auth-hook" ''
|
||||||
|
${unwrappedAuthProgram}/bin/sftpgo_external_auth_hook ${authFailJson} ${authSuccessJson}
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
{
|
||||||
|
# Client initiates a FTP "control connection" on port 21.
|
||||||
|
# - this handles the client -> server commands, and the server -> client status, but not the actual data
|
||||||
|
# - file data, directory listings, etc need to be transferred on an ephemeral "data port".
|
||||||
|
# - 50000-50100 is a common port range for this.
|
||||||
|
sane.ports.ports = {
|
||||||
|
"21" = {
|
||||||
|
protocol = [ "tcp" ];
|
||||||
|
visibleTo.lan = true;
|
||||||
|
description = "colin-FTP server";
|
||||||
|
};
|
||||||
|
} // (sane-lib.mapToAttrs
|
||||||
|
(port: {
|
||||||
|
name = builtins.toString port;
|
||||||
|
value = {
|
||||||
|
protocol = [ "tcp" ];
|
||||||
|
visibleTo.lan = true;
|
||||||
|
description = "colin-FTP server data port range";
|
||||||
|
};
|
||||||
|
})
|
||||||
|
(lib.range 50000 50100)
|
||||||
|
);
|
||||||
|
|
||||||
|
services.sftpgo = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
ftpd = {
|
||||||
|
bindings = [
|
||||||
|
{
|
||||||
|
# binding this means any wireguard client can connect
|
||||||
|
address = "10.0.10.5";
|
||||||
|
port = 21;
|
||||||
|
debug = true;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
# binding this means any LAN client can connect
|
||||||
|
address = "10.78.79.51";
|
||||||
|
port = 21;
|
||||||
|
debug = true;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
# active mode is susceptible to "bounce attacks", without much benefit over passive mode
|
||||||
|
disable_active_mode = true;
|
||||||
|
hash_support = true;
|
||||||
|
passive_port_range = {
|
||||||
|
start = 50000;
|
||||||
|
end = 50100;
|
||||||
|
};
|
||||||
|
|
||||||
|
banner = ''
|
||||||
|
Welcome, friends, to Colin's read-only FTP server! Also available via NFS on the same host.
|
||||||
|
Username: "anonymous"
|
||||||
|
Password: "anonymous"
|
||||||
|
CONFIGURE YOUR CLIENT FOR "PASSIVE" mode, e.g. `ftp --passive uninsane.org`
|
||||||
|
Please let me know if anything's broken or not as it should be. Otherwise, browse and DL freely :)
|
||||||
|
'';
|
||||||
|
|
||||||
|
};
|
||||||
|
data_provider = {
|
||||||
|
driver = "memory";
|
||||||
|
external_auth_hook = "${authProgram}";
|
||||||
|
# track_quota:
|
||||||
|
# - 0: disable quota tracking
|
||||||
|
# - 1: quota is updated on every upload/delete, even if user has no quota restriction
|
||||||
|
# - 2: quota is updated on every upload/delete, but only if user/folder has a quota restriction (default, i think)
|
||||||
|
# track_quota = 2;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# fileSystems."/var/lib/sftpgo/export/media" = {
|
||||||
|
# # everything in here could be considered publicly readable (based on the viewer's legal jurisdiction)
|
||||||
|
# device = "/var/lib/uninsane/media";
|
||||||
|
# options = [ "rbind" ];
|
||||||
|
# };
|
||||||
|
# sane.persist.sys.plaintext = [
|
||||||
|
# { user = "sftpgo"; group = "sftpgo"; path = "/var/lib/sftpgo/export/playground"; }
|
||||||
|
# ];
|
||||||
|
# sane.fs."/var/lib/sftpgo/export/playground/README.md" = {
|
||||||
|
# wantedBy = [ "sftpgo.service" ];
|
||||||
|
# file.text = ''
|
||||||
|
# this directory is intentionally read+write by anyone.
|
||||||
|
# there are no rules, except a server-level quota:
|
||||||
|
# - share files
|
||||||
|
# - write poetry
|
||||||
|
# - be a friendly troll
|
||||||
|
# '';
|
||||||
|
# };
|
||||||
|
}
|
23
hosts/by-name/servo/services/export/sftpgo_external_auth_hook
Executable file
23
hosts/by-name/servo/services/export/sftpgo_external_auth_hook
Executable file
@@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env nix-shell
|
||||||
|
#!nix-shell -i bash -p coreutils
|
||||||
|
# vim: set filetype=bash :
|
||||||
|
#
|
||||||
|
# available environment variables:
|
||||||
|
# - SFTPGO_AUTHD_USERNAME
|
||||||
|
# - SFTPGO_AUTHD_USER
|
||||||
|
# - SFTPGO_AUTHD_IP
|
||||||
|
# - SFTPGO_AUTHD_PROTOCOL = { "DAV", "FTP", "HTTP", "SSH" }
|
||||||
|
# - SFTPGO_AUTHD_PASSWORD
|
||||||
|
# - SFTPGO_AUTHD_PUBLIC_KEY
|
||||||
|
# - SFTPGO_AUTHD_KEYBOARD_INTERACTIVE
|
||||||
|
# - SFTPGO_AUTHD_TLS_CERT
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# call with <script_name> /path/to/fail/response.json /path/to/success/response.json
|
||||||
|
|
||||||
|
|
||||||
|
if [ "$SFTPGO_AUTHD_USERNAME" = "anonymous" ]; then
|
||||||
|
cat "$2"
|
||||||
|
else
|
||||||
|
cat "$1"
|
||||||
|
fi
|
@@ -1,70 +0,0 @@
|
|||||||
# docs:
|
|
||||||
# - <https://github.com/drakkan/sftpgo>
|
|
||||||
# - config options: <https://github.com/drakkan/sftpgo/blob/main/docs/full-configuration.md>
|
|
||||||
# - config defaults: <https://github.com/drakkan/sftpgo/blob/main/sftpgo.json>
|
|
||||||
# - nixos options: <repo:nixos/nixpkgs:nixos/modules/services/web-apps/sftpgo.nix>
|
|
||||||
#
|
|
||||||
# sftpgo is a FTP server that also supports WebDAV, SFTP, and web clients.
|
|
||||||
|
|
||||||
|
|
||||||
{ lib, pkgs, sane-lib, ... }:
|
|
||||||
let
|
|
||||||
authProgram = pkgs.static-nix-shell.mkBash {
|
|
||||||
pname = "sftpgo_external_auth_hook";
|
|
||||||
src = ./.;
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
# Client initiates a FTP "control connection" on port 21.
|
|
||||||
# - this handles the client -> server commands, and the server -> client status, but not the actual data
|
|
||||||
# - file data, directory listings, etc need to be transferred on an ephemeral "data port".
|
|
||||||
# - 50000-50100 is a common port range for this.
|
|
||||||
sane.ports.ports = {
|
|
||||||
"21" = {
|
|
||||||
protocol = [ "tcp" ];
|
|
||||||
visibleTo.lan = true;
|
|
||||||
description = "colin-FTP server";
|
|
||||||
};
|
|
||||||
} // (sane-lib.mapToAttrs
|
|
||||||
(port: {
|
|
||||||
name = builtins.toString port;
|
|
||||||
value = {
|
|
||||||
protocol = [ "tcp" ];
|
|
||||||
visibleTo.lan = true;
|
|
||||||
description = "colin-FTP server data port range";
|
|
||||||
};
|
|
||||||
})
|
|
||||||
(lib.range 50000 50100)
|
|
||||||
);
|
|
||||||
|
|
||||||
services.sftpgo = {
|
|
||||||
enable = true;
|
|
||||||
settings = {
|
|
||||||
ftpd = {
|
|
||||||
bindings = [{
|
|
||||||
address = "10.0.10.5";
|
|
||||||
port = 21;
|
|
||||||
debug = true;
|
|
||||||
}];
|
|
||||||
|
|
||||||
# active mode is susceptible to "bounce attacks", without much benefit over passive mode
|
|
||||||
disable_active_mode = true;
|
|
||||||
hash_support = true;
|
|
||||||
passive_port_range = {
|
|
||||||
start = 50000;
|
|
||||||
end = 50100;
|
|
||||||
};
|
|
||||||
|
|
||||||
banner = ''
|
|
||||||
Welcome, friends, to Colin's read-only FTP server! Also available via NFS on the same host.
|
|
||||||
Please let me know if anything's broken or not as it should be. Otherwise, browse and DL freely :)
|
|
||||||
'';
|
|
||||||
|
|
||||||
};
|
|
||||||
data_provider = {
|
|
||||||
driver = "memory";
|
|
||||||
external_auth_hook = "${authProgram}/bin/sftpgo_external_auth_hook";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,55 +0,0 @@
|
|||||||
#!/usr/bin/env nix-shell
|
|
||||||
#!nix-shell -i bash
|
|
||||||
# vim: set filetype=bash :
|
|
||||||
#
|
|
||||||
# available environment variables:
|
|
||||||
# - SFTPGO_AUTHD_USERNAME
|
|
||||||
# - SFTPGO_AUTHD_USER
|
|
||||||
# - SFTPGO_AUTHD_IP
|
|
||||||
# - SFTPGO_AUTHD_PROTOCOL = { "DAV", "FTP", "HTTP", "SSH" }
|
|
||||||
# - SFTPGO_AUTHD_PASSWORD
|
|
||||||
# - SFTPGO_AUTHD_PUBLIC_KEY
|
|
||||||
# - SFTPGO_AUTHD_KEYBOARD_INTERACTIVE
|
|
||||||
# - SFTPGO_AUTHD_TLS_CERT
|
|
||||||
#
|
|
||||||
# user permissions:
|
|
||||||
# - see <repo:drakkan/sftpgo:internal/dataprovider/user.go>
|
|
||||||
# - "*" = grant all permissions
|
|
||||||
# - read-only perms:
|
|
||||||
# - "list" = list files and directories
|
|
||||||
# - "download"
|
|
||||||
# - rw perms:
|
|
||||||
# - "upload"
|
|
||||||
# - "overwrite" = allow uploads to replace existing files
|
|
||||||
# - "delete" = delete files and directories
|
|
||||||
# - "delete_files"
|
|
||||||
# - "delete_dirs"
|
|
||||||
# - "rename" = rename files and directories
|
|
||||||
# - "rename_files"
|
|
||||||
# - "rename_dirs"
|
|
||||||
# - "create_dirs"
|
|
||||||
# - "create_symlinks"
|
|
||||||
# - "chmod"
|
|
||||||
# - "chown"
|
|
||||||
# - "chtimes" = change atime/mtime (access and modification times)
|
|
||||||
#
|
|
||||||
# home_dir:
|
|
||||||
# - it seems (empirically) that a user can't cd above their home directory.
|
|
||||||
# though i don't have a reference for that in the docs.
|
|
||||||
# TODO: don't reuse /var/nfs/export here. formalize this some other way.
|
|
||||||
|
|
||||||
|
|
||||||
if [ "$SFTPGO_AUTHD_USERNAME" = "anonymous" ]; then
|
|
||||||
echo '{'
|
|
||||||
echo ' "status":1,'
|
|
||||||
echo ' "username":"anonymous","expiration_date":0,'
|
|
||||||
echo ' "home_dir":"/var/nfs/export","uid":65534,"gid":65534,"max_sessions":0,"quota_size":0,"quota_files":100000,'
|
|
||||||
echo ' "permissions":{'
|
|
||||||
echo ' "/":["list", "download"]'
|
|
||||||
echo ' },'
|
|
||||||
echo ' "upload_bandwidth":0,"download_bandwidth":0,'
|
|
||||||
echo ' "filters":{"allowed_ip":[],"denied_ip":[]},"public_keys":[]'
|
|
||||||
echo '}'
|
|
||||||
else
|
|
||||||
echo '{"username":""}'
|
|
||||||
fi
|
|
@@ -3,13 +3,23 @@
|
|||||||
# - <repo:LemmyNet/lemmy:docker/nginx.conf>
|
# - <repo:LemmyNet/lemmy:docker/nginx.conf>
|
||||||
# - <repo:LemmyNet/lemmy-ansible:templates/nginx.conf>
|
# - <repo:LemmyNet/lemmy-ansible:templates/nginx.conf>
|
||||||
|
|
||||||
{ config, lib, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
let
|
let
|
||||||
inherit (builtins) toString;
|
inherit (builtins) toString;
|
||||||
inherit (lib) mkForce;
|
inherit (lib) mkForce;
|
||||||
uiPort = 1234; # default ui port is 1234
|
uiPort = 1234; # default ui port is 1234
|
||||||
backendPort = 8536; # default backend port is 8536
|
backendPort = 8536; # default backend port is 8536
|
||||||
# - i guess the "backend" port is used for federation?
|
#^ i guess the "backend" port is used for federation?
|
||||||
|
pict-rs = pkgs.pict-rs.overrideAttrs (upstream: {
|
||||||
|
# as of v 0.4.2, all non-GIF video is forcibly transcoded.
|
||||||
|
# that breaks lemmy, because of the request latency.
|
||||||
|
# and it eats up hella CPU.
|
||||||
|
# pict-rs is iffy around video altogether: mp4 seems the best supported.
|
||||||
|
postPatch = (upstream.postPatch or "") + ''
|
||||||
|
substituteInPlace src/validate.rs \
|
||||||
|
--replace 'if transcode_options.needs_reencode() {' 'if false {'
|
||||||
|
'';
|
||||||
|
});
|
||||||
in {
|
in {
|
||||||
services.lemmy = {
|
services.lemmy = {
|
||||||
enable = true;
|
enable = true;
|
||||||
@@ -56,4 +66,20 @@ in {
|
|||||||
};
|
};
|
||||||
|
|
||||||
sane.dns.zones."uninsane.org".inet.CNAME."lemmy" = "native";
|
sane.dns.zones."uninsane.org".inet.CNAME."lemmy" = "native";
|
||||||
|
|
||||||
|
#v DO NOT REMOVE: defaults to 0.3, instead of latest, so always need to explicitly set this.
|
||||||
|
services.pict-rs.package = pict-rs;
|
||||||
|
|
||||||
|
# pict-rs configuration is applied in this order:
|
||||||
|
# - via toml
|
||||||
|
# - via env vars (overrides everything above)
|
||||||
|
# - via CLI flags (overrides everything above)
|
||||||
|
# some of the CLI flags have defaults, making it the only actual way to configure certain things even when docs claim otherwise.
|
||||||
|
# CLI args: <https://git.asonix.dog/asonix/pict-rs#user-content-running>
|
||||||
|
systemd.services.pict-rs.serviceConfig.ExecStart = lib.mkForce (lib.concatStringsSep " " [
|
||||||
|
"${lib.getBin pict-rs}/bin/pict-rs run"
|
||||||
|
"--media-max-frame-count" (builtins.toString (30*60*60))
|
||||||
|
"--media-process-timeout 120"
|
||||||
|
"--media-enable-full-video true" # allow audio
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
@@ -63,6 +63,7 @@ in
|
|||||||
database: "pleroma",
|
database: "pleroma",
|
||||||
hostname: "localhost",
|
hostname: "localhost",
|
||||||
pool_size: 10,
|
pool_size: 10,
|
||||||
|
prepare: :named,
|
||||||
parameters: [
|
parameters: [
|
||||||
plan_cache_mode: "force_custom_plan"
|
plan_cache_mode: "force_custom_plan"
|
||||||
]
|
]
|
||||||
|
@@ -1,12 +1,39 @@
|
|||||||
{ ... }:
|
{ pkgs, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
GiB = n: MiB 1024*n;
|
||||||
|
MiB = n: KiB 1024*n;
|
||||||
|
KiB = n: 1024*n;
|
||||||
|
in
|
||||||
{
|
{
|
||||||
sane.persist.sys.plaintext = [
|
sane.persist.sys.plaintext = [
|
||||||
# TODO: mode?
|
# TODO: mode?
|
||||||
{ user = "postgres"; group = "postgres"; path = "/var/lib/postgresql"; }
|
{ user = "postgres"; group = "postgres"; path = "/var/lib/postgresql"; }
|
||||||
];
|
];
|
||||||
services.postgresql.enable = true;
|
services.postgresql.enable = true;
|
||||||
# services.postgresql.dataDir = "/opt/postgresql/13";
|
|
||||||
|
# HOW TO UPDATE:
|
||||||
|
# postgres version updates are manual and require intervention.
|
||||||
|
# - `sane-stop-all-servo`
|
||||||
|
# - `systemctl start postgresql`
|
||||||
|
# - as `sudo su postgres`:
|
||||||
|
# - `cd /var/log/postgresql`
|
||||||
|
# - `pg_dumpall > state.sql`
|
||||||
|
# - `echo placeholder > <new_version>` # to prevent state from being created earlier than we want
|
||||||
|
# - then, atomically:
|
||||||
|
# - update the `services.postgresql.package` here
|
||||||
|
# - `dataDir` is atomically updated to match package; don't touch
|
||||||
|
# - `nixos-rebuild --flake . switch ; sane-stop-all-servo`
|
||||||
|
# - `sudo rm -rf /var/lib/postgresql/<new_version>`
|
||||||
|
# - `systemctl start postgresql`
|
||||||
|
# - as `sudo su postgres`:
|
||||||
|
# - `cd /var/lib/postgreql`
|
||||||
|
# - `psql -f state.sql`
|
||||||
|
# - restart dependent services (maybe test one at a time)
|
||||||
|
|
||||||
|
services.postgresql.package = pkgs.postgresql_15;
|
||||||
|
|
||||||
|
|
||||||
# XXX colin: for a proper deploy, we'd want to include something for Pleroma here too.
|
# XXX colin: for a proper deploy, we'd want to include something for Pleroma here too.
|
||||||
# services.postgresql.initialScript = pkgs.writeText "synapse-init.sql" ''
|
# services.postgresql.initialScript = pkgs.writeText "synapse-init.sql" ''
|
||||||
# CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD '<password goes here>';
|
# CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD '<password goes here>';
|
||||||
@@ -17,10 +44,33 @@
|
|||||||
# LC_CTYPE = "C";
|
# LC_CTYPE = "C";
|
||||||
# '';
|
# '';
|
||||||
|
|
||||||
# TODO: perf tuning
|
# perf tuning
|
||||||
# - for recommended values see: <https://pgtune.leopard.in.ua/>
|
# - for recommended values see: <https://pgtune.leopard.in.ua/>
|
||||||
# - for official docs (sparse), see: <https://www.postgresql.org/docs/11/config-setting.html#CONFIG-SETTING-CONFIGURATION-FILE>
|
# - for official docs (sparse), see: <https://www.postgresql.org/docs/11/config-setting.html#CONFIG-SETTING-CONFIGURATION-FILE>
|
||||||
# services.postgresql.settings = { ... }
|
services.postgresql.settings = {
|
||||||
|
# DB Version: 15
|
||||||
|
# OS Type: linux
|
||||||
|
# DB Type: web
|
||||||
|
# Total Memory (RAM): 32 GB
|
||||||
|
# CPUs num: 12
|
||||||
|
# Data Storage: ssd
|
||||||
|
max_connections = 200;
|
||||||
|
shared_buffers = "8GB";
|
||||||
|
effective_cache_size = "24GB";
|
||||||
|
maintenance_work_mem = "2GB";
|
||||||
|
checkpoint_completion_target = 0.9;
|
||||||
|
wal_buffers = "16MB";
|
||||||
|
default_statistics_target = 100;
|
||||||
|
random_page_cost = 1.1;
|
||||||
|
effective_io_concurrency = 200;
|
||||||
|
work_mem = "10485kB";
|
||||||
|
min_wal_size = "1GB";
|
||||||
|
max_wal_size = "4GB";
|
||||||
|
max_worker_processes = 12;
|
||||||
|
max_parallel_workers_per_gather = 4;
|
||||||
|
max_parallel_workers = 12;
|
||||||
|
max_parallel_maintenance_workers = 4;
|
||||||
|
};
|
||||||
|
|
||||||
# daily backups to /var/backup
|
# daily backups to /var/backup
|
||||||
services.postgresqlBackup.enable = true;
|
services.postgresqlBackup.enable = true;
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
# where to find good stuff?
|
# where to find good stuff?
|
||||||
|
# - podcasts w/ a community: <https://lemmyverse.net/communities?query=podcast>
|
||||||
# - podcast rec thread: <https://lemmy.ml/post/1565858>
|
# - podcast rec thread: <https://lemmy.ml/post/1565858>
|
||||||
#
|
#
|
||||||
# candidates:
|
# candidates:
|
||||||
@@ -67,7 +68,12 @@ let
|
|||||||
(fromDb "craphound.com" // pol)
|
(fromDb "craphound.com" // pol)
|
||||||
## Maggie Killjoy -- referenced by Cory Doctorow
|
## Maggie Killjoy -- referenced by Cory Doctorow
|
||||||
(fromDb "omny.fm/shows/cool-people-who-did-cool-stuff" // pol)
|
(fromDb "omny.fm/shows/cool-people-who-did-cool-stuff" // pol)
|
||||||
|
## also Maggie Killjoy
|
||||||
|
(fromDb "feeds.megaphone.fm/behindthebastards" // pol)
|
||||||
|
## Jennifer Briney
|
||||||
(fromDb "congressionaldish.libsyn.com" // pol)
|
(fromDb "congressionaldish.libsyn.com" // pol)
|
||||||
|
(fromDb "werenotwrong.fireside.fm" // pol)
|
||||||
|
(fromDb "usefulidiots.substack.com" // pol)
|
||||||
# (mkPod "https://podcasts.la.utexas.edu/this-is-democracy/feed/podcast/" // pol // weekly)
|
# (mkPod "https://podcasts.la.utexas.edu/this-is-democracy/feed/podcast/" // pol // weekly)
|
||||||
## Civboot -- https://anchor.fm/civboot
|
## Civboot -- https://anchor.fm/civboot
|
||||||
(fromDb "anchor.fm/s/34c7232c/podcast/rss" // tech)
|
(fromDb "anchor.fm/s/34c7232c/podcast/rss" // tech)
|
||||||
@@ -125,6 +131,10 @@ let
|
|||||||
(fromDb "feeds.simplecast.com/82FI35Px" // pol)
|
(fromDb "feeds.simplecast.com/82FI35Px" // pol)
|
||||||
## Wireshark Podcast o_0
|
## Wireshark Podcast o_0
|
||||||
(fromDb "sharkbytes.transistor.fm" // tech)
|
(fromDb "sharkbytes.transistor.fm" // tech)
|
||||||
|
## 3/4 German; 1/4 eps are English
|
||||||
|
(fromDb "omegataupodcast.net" // tech)
|
||||||
|
## Lateral with Tom Scott
|
||||||
|
(mkPod "https://audioboom.com/channels/5097784.rss" // tech)
|
||||||
];
|
];
|
||||||
|
|
||||||
texts = [
|
texts = [
|
||||||
|
@@ -1,136 +1,137 @@
|
|||||||
# docs
|
# docs
|
||||||
# - x-systemd options: <https://www.freedesktop.org/software/systemd/man/systemd.mount.html>
|
# - x-systemd options: <https://www.freedesktop.org/software/systemd/man/systemd.mount.html>
|
||||||
|
|
||||||
{ pkgs, sane-lib, ... }:
|
{ lib, pkgs, sane-lib, ... }:
|
||||||
|
|
||||||
let fsOpts = rec {
|
let
|
||||||
common = [
|
fsOpts = rec {
|
||||||
"_netdev"
|
common = [
|
||||||
"noatime"
|
"_netdev"
|
||||||
"user" # allow any user with access to the device to mount the fs
|
"noatime"
|
||||||
"x-systemd.requires=network-online.target"
|
"user" # allow any user with access to the device to mount the fs
|
||||||
"x-systemd.after=network-online.target"
|
"x-systemd.requires=network-online.target"
|
||||||
"x-systemd.mount-timeout=10s" # how long to wait for mount **and** how long to wait for unmount
|
"x-systemd.after=network-online.target"
|
||||||
];
|
"x-systemd.mount-timeout=10s" # how long to wait for mount **and** how long to wait for unmount
|
||||||
auto = [ "x-systemd.automount" ];
|
];
|
||||||
noauto = [ "noauto" ]; # don't mount as part of remote-fs.target
|
auto = [ "x-systemd.automount" ];
|
||||||
wg = [
|
noauto = [ "noauto" ]; # don't mount as part of remote-fs.target
|
||||||
"x-systemd.requires=wireguard-wg-home.service"
|
wg = [
|
||||||
"x-systemd.after=wireguard-wg-home.service"
|
"x-systemd.requires=wireguard-wg-home.service"
|
||||||
];
|
"x-systemd.after=wireguard-wg-home.service"
|
||||||
|
];
|
||||||
|
|
||||||
ssh = common ++ [
|
ssh = common ++ [
|
||||||
"identityfile=/home/colin/.ssh/id_ed25519"
|
"identityfile=/home/colin/.ssh/id_ed25519"
|
||||||
"allow_other"
|
"allow_other"
|
||||||
"default_permissions"
|
"default_permissions"
|
||||||
];
|
];
|
||||||
sshColin = ssh ++ [
|
sshColin = ssh ++ [
|
||||||
"transform_symlinks"
|
"transform_symlinks"
|
||||||
"idmap=user"
|
"idmap=user"
|
||||||
"uid=1000"
|
"uid=1000"
|
||||||
"gid=100"
|
"gid=100"
|
||||||
];
|
];
|
||||||
sshRoot = ssh ++ [
|
sshRoot = ssh ++ [
|
||||||
# we don't transform_symlinks because that breaks the validity of remote /nix stores
|
# we don't transform_symlinks because that breaks the validity of remote /nix stores
|
||||||
"sftp_server=/run/wrappers/bin/sudo\\040/run/current-system/sw/libexec/sftp-server"
|
"sftp_server=/run/wrappers/bin/sudo\\040/run/current-system/sw/libexec/sftp-server"
|
||||||
];
|
];
|
||||||
# in the event of hunt NFS mounts, consider:
|
# in the event of hunt NFS mounts, consider:
|
||||||
# - <https://unix.stackexchange.com/questions/31979/stop-broken-nfs-mounts-from-locking-a-directory>
|
# - <https://unix.stackexchange.com/questions/31979/stop-broken-nfs-mounts-from-locking-a-directory>
|
||||||
|
|
||||||
# NFS options: <https://linux.die.net/man/5/nfs>
|
# NFS options: <https://linux.die.net/man/5/nfs>
|
||||||
# actimeo=n = how long (in seconds) to cache file/dir attributes (default: 3-60s)
|
# actimeo=n = how long (in seconds) to cache file/dir attributes (default: 3-60s)
|
||||||
# bg = retry failed mounts in the background
|
# bg = retry failed mounts in the background
|
||||||
# retry=n = for how many minutes `mount` will retry NFS mount operation
|
# retry=n = for how many minutes `mount` will retry NFS mount operation
|
||||||
# soft = on "major timeout", report I/O error to userspace
|
# soft = on "major timeout", report I/O error to userspace
|
||||||
# retrans=n = how many times to retry a NFS request before giving userspace a "server not responding" error (default: 3)
|
# retrans=n = how many times to retry a NFS request before giving userspace a "server not responding" error (default: 3)
|
||||||
# timeo=n = number of *deciseconds* to wait for a response before retrying it (default: 600)
|
# timeo=n = number of *deciseconds* to wait for a response before retrying it (default: 600)
|
||||||
# note: client uses a linear backup, so the second request will have double this timeout, then triple, etc.
|
# note: client uses a linear backup, so the second request will have double this timeout, then triple, etc.
|
||||||
nfs = common ++ [
|
nfs = common ++ [
|
||||||
# "actimeo=10"
|
# "actimeo=10"
|
||||||
"bg"
|
"bg"
|
||||||
"retrans=4"
|
"retrans=4"
|
||||||
"retry=0"
|
"retry=0"
|
||||||
"soft"
|
"soft"
|
||||||
"timeo=15"
|
"timeo=15"
|
||||||
"nofail" # don't fail remote-fs.target when this mount fails (not an option for sshfs else would be common)
|
"nofail" # don't fail remote-fs.target when this mount fails (not an option for sshfs else would be common)
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
remoteHome = host: {
|
||||||
|
fileSystems."/mnt/${host}-home" = {
|
||||||
|
device = "colin@${host}:/home/colin";
|
||||||
|
fsType = "fuse.sshfs";
|
||||||
|
options = fsOpts.sshColin ++ fsOpts.noauto;
|
||||||
|
noCheck = true;
|
||||||
|
};
|
||||||
|
sane.fs."/mnt/${host}-home" = sane-lib.fs.wantedDir;
|
||||||
|
};
|
||||||
in
|
in
|
||||||
{
|
lib.mkMerge [
|
||||||
# some services which use private directories error if the parent (/var/lib/private) isn't 700.
|
{
|
||||||
sane.fs."/var/lib/private".dir.acl.mode = "0700";
|
# some services which use private directories error if the parent (/var/lib/private) isn't 700.
|
||||||
|
sane.fs."/var/lib/private".dir.acl.mode = "0700";
|
||||||
|
|
||||||
# in-memory compressed RAM
|
# in-memory compressed RAM
|
||||||
# defaults to compressing at most 50% size of RAM
|
# defaults to compressing at most 50% size of RAM
|
||||||
# claimed compression ratio is about 2:1
|
# claimed compression ratio is about 2:1
|
||||||
# - but on moby w/ zstd default i see 4-7:1 (ratio lowers as it fills)
|
# - but on moby w/ zstd default i see 4-7:1 (ratio lowers as it fills)
|
||||||
# note that idle overhead is about 0.05% of capacity (e.g. 2B per 4kB page)
|
# note that idle overhead is about 0.05% of capacity (e.g. 2B per 4kB page)
|
||||||
# docs: <https://www.kernel.org/doc/Documentation/blockdev/zram.txt>
|
# docs: <https://www.kernel.org/doc/Documentation/blockdev/zram.txt>
|
||||||
#
|
#
|
||||||
# to query effectiveness:
|
# to query effectiveness:
|
||||||
# `cat /sys/block/zram0/mm_stat`. whitespace separated fields:
|
# `cat /sys/block/zram0/mm_stat`. whitespace separated fields:
|
||||||
# - *orig_data_size* (bytes)
|
# - *orig_data_size* (bytes)
|
||||||
# - *compr_data_size* (bytes)
|
# - *compr_data_size* (bytes)
|
||||||
# - mem_used_total (bytes)
|
# - mem_used_total (bytes)
|
||||||
# - mem_limit (bytes)
|
# - mem_limit (bytes)
|
||||||
# - mem_used_max (bytes)
|
# - mem_used_max (bytes)
|
||||||
# - *same_pages* (pages which are e.g. all zeros (consumes no additional mem))
|
# - *same_pages* (pages which are e.g. all zeros (consumes no additional mem))
|
||||||
# - *pages_compacted* (pages which have been freed thanks to compression)
|
# - *pages_compacted* (pages which have been freed thanks to compression)
|
||||||
# - huge_pages (incompressible)
|
# - huge_pages (incompressible)
|
||||||
#
|
#
|
||||||
# see also:
|
# see also:
|
||||||
# - `man zramctl`
|
# - `man zramctl`
|
||||||
zramSwap.enable = true;
|
zramSwap.enable = true;
|
||||||
# how much ram can be swapped into the zram device.
|
# how much ram can be swapped into the zram device.
|
||||||
# this shouldn't be higher than the observed compression ratio.
|
# this shouldn't be higher than the observed compression ratio.
|
||||||
# the default is 50% (why?)
|
# the default is 50% (why?)
|
||||||
# 100% should be "guaranteed" safe so long as the data is even *slightly* compressible.
|
# 100% should be "guaranteed" safe so long as the data is even *slightly* compressible.
|
||||||
# but it decreases working memory under the heaviest of loads by however much space the compressed memory occupies (e.g. 50% if 2:1; 25% if 4:1)
|
# but it decreases working memory under the heaviest of loads by however much space the compressed memory occupies (e.g. 50% if 2:1; 25% if 4:1)
|
||||||
zramSwap.memoryPercent = 100;
|
zramSwap.memoryPercent = 100;
|
||||||
|
|
||||||
# fileSystems."/mnt/servo-nfs" = {
|
# fileSystems."/mnt/servo-nfs" = {
|
||||||
# device = "servo-hn:/";
|
# device = "servo-hn:/";
|
||||||
# noCheck = true;
|
# noCheck = true;
|
||||||
# fsType = "nfs";
|
# fsType = "nfs";
|
||||||
# options = fsOpts.nfs ++ fsOpts.auto ++ fsOpts.wg;
|
# options = fsOpts.nfs ++ fsOpts.auto ++ fsOpts.wg;
|
||||||
# };
|
# };
|
||||||
fileSystems."/mnt/servo-nfs/media" = {
|
fileSystems."/mnt/servo-nfs/media" = {
|
||||||
device = "servo-hn:/media";
|
device = "servo-hn:/media";
|
||||||
noCheck = true;
|
noCheck = true;
|
||||||
fsType = "nfs";
|
fsType = "nfs";
|
||||||
options = fsOpts.nfs ++ fsOpts.auto ++ fsOpts.wg;
|
options = fsOpts.nfs ++ fsOpts.auto ++ fsOpts.wg;
|
||||||
};
|
};
|
||||||
# fileSystems."/mnt/servo-media-nfs" = {
|
# fileSystems."/mnt/servo-media-nfs" = {
|
||||||
# device = "servo-hn:/media";
|
# device = "servo-hn:/media";
|
||||||
# noCheck = true;
|
# noCheck = true;
|
||||||
# fsType = "nfs";
|
# fsType = "nfs";
|
||||||
# options = fsOpts.common ++ fsOpts.auto;
|
# options = fsOpts.common ++ fsOpts.auto;
|
||||||
# };
|
# };
|
||||||
sane.fs."/mnt/servo-media" = sane-lib.fs.wantedSymlinkTo "/mnt/servo-nfs/media";
|
sane.fs."/mnt/servo-media" = sane-lib.fs.wantedSymlinkTo "/mnt/servo-nfs/media";
|
||||||
|
|
||||||
fileSystems."/mnt/desko-home" = {
|
environment.pathsToLink = [
|
||||||
device = "colin@desko:/home/colin";
|
# needed to achieve superuser access for user-mounted filesystems (see optionsRoot above)
|
||||||
fsType = "fuse.sshfs";
|
# we can only link whole directories here, even though we're only interested in pkgs.openssh
|
||||||
options = fsOpts.sshColin ++ fsOpts.noauto;
|
"/libexec"
|
||||||
noCheck = true;
|
];
|
||||||
};
|
|
||||||
sane.fs."/mnt/desko-home" = sane-lib.fs.wantedDir;
|
|
||||||
fileSystems."/mnt/desko-root" = {
|
|
||||||
device = "colin@desko:/";
|
|
||||||
fsType = "fuse.sshfs";
|
|
||||||
options = fsOpts.sshRoot ++ fsOpts.noauto;
|
|
||||||
noCheck = true;
|
|
||||||
};
|
|
||||||
sane.fs."/mnt/desko-root" = sane-lib.fs.wantedDir;
|
|
||||||
|
|
||||||
environment.pathsToLink = [
|
environment.systemPackages = [
|
||||||
# needed to achieve superuser access for user-mounted filesystems (see optionsRoot above)
|
pkgs.sshfs-fuse
|
||||||
# we can only link whole directories here, even though we're only interested in pkgs.openssh
|
];
|
||||||
"/libexec"
|
}
|
||||||
];
|
|
||||||
|
|
||||||
environment.systemPackages = [
|
(remoteHome "desko")
|
||||||
pkgs.sshfs-fuse
|
(remoteHome "lappy")
|
||||||
];
|
(remoteHome "moby")
|
||||||
}
|
]
|
||||||
|
|
||||||
|
24
hosts/common/programs/alacritty.nix
Normal file
24
hosts/common/programs/alacritty.nix
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# alacritty terminal emulator
|
||||||
|
# - config options: <https://github.com/alacritty/alacritty/blob/master/extra/man/alacritty.5.scd>
|
||||||
|
# - `man 5 alacritty`
|
||||||
|
# - defaults: <https://github.com/alacritty/alacritty/releases> -> alacritty.yml
|
||||||
|
# - irc: #alacritty on libera.chat
|
||||||
|
{ lib, ... }:
|
||||||
|
{
|
||||||
|
sane.programs.alacritty = {
|
||||||
|
env.TERMINAL = lib.mkDefault "alacritty";
|
||||||
|
# note: alacritty will switch to .toml config in 13.0 release
|
||||||
|
# - run `alacritty migrate` to convert the yaml to toml
|
||||||
|
fs.".config/alacritty/alacritty.yml".symlink.text = ''
|
||||||
|
font:
|
||||||
|
size: 14
|
||||||
|
|
||||||
|
key_bindings:
|
||||||
|
- { key: N, mods: Control, action: CreateNewWindow }
|
||||||
|
- { key: PageUp, mods: Control, action: ScrollPageUp }
|
||||||
|
- { key: PageDown, mods: Control, action: ScrollPageDown }
|
||||||
|
- { key: PageUp, mods: Control|Shift, action: ScrollPageUp }
|
||||||
|
- { key: PageDown, mods: Control|Shift, action: ScrollPageDown }
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
@@ -51,6 +51,7 @@ in
|
|||||||
];
|
];
|
||||||
"sane-scripts.sys-utils" = declPackageSet [
|
"sane-scripts.sys-utils" = declPackageSet [
|
||||||
"sane-scripts.ip-port-forward"
|
"sane-scripts.ip-port-forward"
|
||||||
|
"sane-scripts.sync-music"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
@@ -126,7 +127,7 @@ in
|
|||||||
# "gopass"
|
# "gopass"
|
||||||
# "gopass-jsonapi"
|
# "gopass-jsonapi"
|
||||||
"helix" # text editor
|
"helix" # text editor
|
||||||
"kitty" # TODO: move to GUI, but `ssh servo` from kitty sets `TERM=xterm-kitty` in the remove and breaks things
|
# "kitty" # XXX needs to be in consolueUtils because `ssh servo` from kitty sets `TERM=xterm-kitty` in the remote and breaks things
|
||||||
"libsecret" # for managing user keyrings. TODO: what needs this? lift into the consumer
|
"libsecret" # for managing user keyrings. TODO: what needs this? lift into the consumer
|
||||||
"lm_sensors" # for sensors-detect. TODO: what needs this? lift into the consumer
|
"lm_sensors" # for sensors-detect. TODO: what needs this? lift into the consumer
|
||||||
"lshw"
|
"lshw"
|
||||||
@@ -200,8 +201,6 @@ in
|
|||||||
|
|
||||||
# INDIVIDUAL PACKAGE DEFINITIONS
|
# INDIVIDUAL PACKAGE DEFINITIONS
|
||||||
|
|
||||||
dino.persist.private = [ ".local/share/dino" ];
|
|
||||||
|
|
||||||
# creds, but also 200 MB of node modules, etc
|
# creds, but also 200 MB of node modules, etc
|
||||||
discord.persist.private = [ ".config/discord" ];
|
discord.persist.private = [ ".config/discord" ];
|
||||||
|
|
||||||
|
36
hosts/common/programs/cantata.nix
Normal file
36
hosts/common/programs/cantata.nix
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# cantata is a mpd frontend.
|
||||||
|
# before launching it, run `mopidy` in some tab
|
||||||
|
# TODO: auto-launch mopidy when cantata launches?
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
sane.programs.cantata = {
|
||||||
|
persist.plaintext = [
|
||||||
|
".cache/cantata" # album art
|
||||||
|
".local/share/cantata/library" # library index (?)
|
||||||
|
];
|
||||||
|
fs.".config/cantata/cantata.conf".symlink.text = ''
|
||||||
|
[General]
|
||||||
|
fetchCovers=true
|
||||||
|
storeCoversInMpdDir=false
|
||||||
|
version=2.5.0
|
||||||
|
|
||||||
|
[Connection]
|
||||||
|
allowLocalStreaming=true
|
||||||
|
applyReplayGain=true
|
||||||
|
autoUpdate=false
|
||||||
|
dir=~/Music
|
||||||
|
host=localhost
|
||||||
|
partition=
|
||||||
|
passwd=
|
||||||
|
port=6600
|
||||||
|
replayGain=off
|
||||||
|
streamUrl=
|
||||||
|
|
||||||
|
[LibraryPage]
|
||||||
|
artist\gridZoom=100
|
||||||
|
artist\searchActive=false
|
||||||
|
artist\viewMode=detailedtree
|
||||||
|
'';
|
||||||
|
suggestedPrograms = [ "mopidy" ];
|
||||||
|
};
|
||||||
|
}
|
@@ -38,7 +38,9 @@ in
|
|||||||
suggestedPrograms = [ "gnome-keyring" ];
|
suggestedPrograms = [ "gnome-keyring" ];
|
||||||
persist.private = [
|
persist.private = [
|
||||||
".local/share/chatty" # matrix avatars and files
|
".local/share/chatty" # matrix avatars and files
|
||||||
# ".purple" # XMPP stuff
|
# not just XMPP; without this Chatty will regenerate its device-id every boot.
|
||||||
|
# .purple/ contains XMPP *and* Matrix auth, logs, avatar cache, and a bit more
|
||||||
|
".purple"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -3,9 +3,12 @@
|
|||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./aerc.nix
|
./aerc.nix
|
||||||
|
./alacritty.nix
|
||||||
./assorted.nix
|
./assorted.nix
|
||||||
|
./cantata.nix
|
||||||
./chatty.nix
|
./chatty.nix
|
||||||
./cozy.nix
|
./cozy.nix
|
||||||
|
./dino.nix
|
||||||
./element-desktop.nix
|
./element-desktop.nix
|
||||||
./epiphany.nix
|
./epiphany.nix
|
||||||
./evince.nix
|
./evince.nix
|
||||||
@@ -13,9 +16,11 @@
|
|||||||
./fontconfig.nix
|
./fontconfig.nix
|
||||||
./fractal.nix
|
./fractal.nix
|
||||||
./fwupd.nix
|
./fwupd.nix
|
||||||
|
./g4music.nix
|
||||||
./git.nix
|
./git.nix
|
||||||
./gnome-feeds.nix
|
./gnome-feeds.nix
|
||||||
./gnome-keyring.nix
|
./gnome-keyring.nix
|
||||||
|
./gnome-weather.nix
|
||||||
./gpodder.nix
|
./gpodder.nix
|
||||||
./gthumb.nix
|
./gthumb.nix
|
||||||
./helix.nix
|
./helix.nix
|
||||||
@@ -28,6 +33,7 @@
|
|||||||
./lemoa.nix
|
./lemoa.nix
|
||||||
./megapixels.nix
|
./megapixels.nix
|
||||||
./mepo.nix
|
./mepo.nix
|
||||||
|
./mopidy.nix
|
||||||
./mpv.nix
|
./mpv.nix
|
||||||
./msmtp.nix
|
./msmtp.nix
|
||||||
./neovim.nix
|
./neovim.nix
|
||||||
@@ -36,6 +42,7 @@
|
|||||||
./nix-index.nix
|
./nix-index.nix
|
||||||
./obsidian.nix
|
./obsidian.nix
|
||||||
./offlineimap.nix
|
./offlineimap.nix
|
||||||
|
./rhythmbox.nix
|
||||||
./ripgrep.nix
|
./ripgrep.nix
|
||||||
./sfeed.nix
|
./sfeed.nix
|
||||||
./splatmoji.nix
|
./splatmoji.nix
|
||||||
|
15
hosts/common/programs/dino.nix
Normal file
15
hosts/common/programs/dino.nix
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# usage:
|
||||||
|
# - start a DM with a rando via
|
||||||
|
# - '+' -> 'start conversation'
|
||||||
|
# - add a user to your roster via
|
||||||
|
# - '+' -> 'start conversation' -> '+' (opens the "add contact" dialog)
|
||||||
|
# - this triggers a popup on the remote side asking them for confirmation
|
||||||
|
# - after the remote's confirmation there will be a local popup for you to allow them to add you to their roster
|
||||||
|
# - to make a call:
|
||||||
|
# - ensure the other party is in your roster
|
||||||
|
# - open a DM with the party
|
||||||
|
# - click the phone icon at top (only visible if other party is in your roster)
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
sane.programs.dino.persist.private = [ ".local/share/dino" ];
|
||||||
|
}
|
16
hosts/common/programs/g4music.nix
Normal file
16
hosts/common/programs/g4music.nix
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# N.B.: requires first-run setup on moby:
|
||||||
|
# - UI will render transparent
|
||||||
|
# - click the hamburger (top-right: immediately left from close button)
|
||||||
|
# > Preferences
|
||||||
|
# > Background-blur mode: change from "Always" to "Never"
|
||||||
|
#
|
||||||
|
# the background blur is probably some dconf setting somewhere.
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
sane.programs.g4music = {
|
||||||
|
persist.plaintext = [
|
||||||
|
# index?
|
||||||
|
".cache/com.github.neithern.g4music"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
10
hosts/common/programs/gnome-weather.nix
Normal file
10
hosts/common/programs/gnome-weather.nix
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# preferences are saved via dconf; see `dconf dump /`
|
||||||
|
# cache dir is just for weather data (or maybe a http cache)
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
sane.programs.gnome-weather = {
|
||||||
|
persist.plaintext = [
|
||||||
|
".cache/libgweather"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
@@ -4,10 +4,12 @@
|
|||||||
# compile without webservices to avoid the expensive webkitgtk dependency
|
# compile without webservices to avoid the expensive webkitgtk dependency
|
||||||
package = pkgs.gthumb.override { withWebservices = false; };
|
package = pkgs.gthumb.override { withWebservices = false; };
|
||||||
mime.associations = {
|
mime.associations = {
|
||||||
|
"image/gif" = "org.gnome.gThumb.desktop";
|
||||||
"image/heif" = "org.gnome.gThumb.desktop"; # apple codec
|
"image/heif" = "org.gnome.gThumb.desktop"; # apple codec
|
||||||
"image/png" = "org.gnome.gThumb.desktop";
|
"image/png" = "org.gnome.gThumb.desktop";
|
||||||
"image/jpeg" = "org.gnome.gThumb.desktop";
|
"image/jpeg" = "org.gnome.gThumb.desktop";
|
||||||
"image/svg+xml" = "org.gnome.gThumb.desktop";
|
"image/svg+xml" = "org.gnome.gThumb.desktop";
|
||||||
|
"image/webp" = "org.gnome.gThumb.desktop";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
56
hosts/common/programs/mopidy.nix
Normal file
56
hosts/common/programs/mopidy.nix
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# chat: <https://mopidy.zulipchat.com/>
|
||||||
|
# config docs: <https://docs.mopidy.com/en/latest/config/>
|
||||||
|
# web client: <http://localhost:6680>
|
||||||
|
# mpd: hosted on `localhost:6600`, no password`
|
||||||
|
#
|
||||||
|
# dump config:
|
||||||
|
# - `mopidy config`
|
||||||
|
# update local file index with
|
||||||
|
# - `mopidy local scan`
|
||||||
|
#
|
||||||
|
# if running as service, those commands are `mopidy --config ... <command>`
|
||||||
|
# and config path is found by `systemctl cat mopidy`
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
# TODO: upstream this as `mopidy.withExtensions`
|
||||||
|
# this is borrowed from the nixos mopidy service
|
||||||
|
mopidyWithExtensions = extensions: with pkgs; buildEnv {
|
||||||
|
name = "mopidy-with-extensions-${mopidy.version}";
|
||||||
|
|
||||||
|
paths = lib.closePropagation extensions;
|
||||||
|
pathsToLink = [ "/${mopidyPackages.python.sitePackages}" ];
|
||||||
|
nativeBuildInputs = [ makeWrapper ];
|
||||||
|
postBuild = ''
|
||||||
|
makeWrapper ${mopidy}/bin/mopidy $out/bin/mopidy \
|
||||||
|
--prefix PYTHONPATH : $out/${mopidyPackages.python.sitePackages}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
sane.programs.mopidy = {
|
||||||
|
package = mopidyWithExtensions (with pkgs; [
|
||||||
|
mopidy-iris # web client: <https://github.com/jaedb/Iris>
|
||||||
|
mopidy-jellyfin
|
||||||
|
mopidy-local
|
||||||
|
mopidy-mpd
|
||||||
|
mopidy-mpris
|
||||||
|
mopidy-spotify
|
||||||
|
# TODO: mopidy-podcast, mopidy-youtube
|
||||||
|
|
||||||
|
# alternate web clients:
|
||||||
|
# mopidy-moped: <https://github.com/martijnboland/moped>
|
||||||
|
# mopidy-muse: <https://github.com/cristianpb/muse>
|
||||||
|
]);
|
||||||
|
persist.plaintext = [
|
||||||
|
".local/share/mopidy/local" # thumbs, library db
|
||||||
|
];
|
||||||
|
persist.private = [
|
||||||
|
".local/share/mopidy/http" # cookie
|
||||||
|
];
|
||||||
|
secrets.".config/mopidy/mopidy.conf" = ../../../secrets/common/mopidy.conf.bin;
|
||||||
|
# other folders:
|
||||||
|
# - .cache/mopidy
|
||||||
|
# - .config/mopidy
|
||||||
|
};
|
||||||
|
}
|
@@ -14,6 +14,29 @@
|
|||||||
# uosc
|
# uosc
|
||||||
pkgs.mpv-uosc-latest
|
pkgs.mpv-uosc-latest
|
||||||
];
|
];
|
||||||
|
extraMakeWrapperArgs = [
|
||||||
|
# 2023/08/29: fixes an error where mpv on moby launches with the message
|
||||||
|
# "DRM_IOCTL_MODE_CREATE_DUMB failed: Cannot allocate memory"
|
||||||
|
# audio still works, and controls, screenshotting, etc -- just not the actual rendering
|
||||||
|
# this is likely a regression for mpv 0.36.0.
|
||||||
|
# the actual error message *appears* to come from the mesa library, but it's tough to trace.
|
||||||
|
# run with `--vo=help` to see a list of all output options.
|
||||||
|
# non-exhaustive (F=fails, W=works)
|
||||||
|
# ? libmpv render API for libmpv
|
||||||
|
# ? gpu Shader-based GPU Renderer
|
||||||
|
# ? gpu-next Video output based on libplacebo
|
||||||
|
# ? vdpau VDPAU with X11
|
||||||
|
# ? wlshm Wayland SHM video output (software scaling)
|
||||||
|
# ? xv X11/Xv
|
||||||
|
# W sdl SDL 2.0 Renderer
|
||||||
|
# F dmabuf-wayland Wayland dmabuf video output
|
||||||
|
# ? vaapi VA API with X11
|
||||||
|
# ? x11 X11 (software scaling)
|
||||||
|
# ? null Null video output
|
||||||
|
# ? caca libcaca
|
||||||
|
# F drm Direct Rendering Manager (software scaling)
|
||||||
|
"--add-flags" "--vo=sdl"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
persist.plaintext = [ ".config/mpv/watch_later" ];
|
persist.plaintext = [ ".config/mpv/watch_later" ];
|
||||||
fs.".config/mpv/input.conf".symlink.text = ''
|
fs.".config/mpv/input.conf".symlink.text = ''
|
||||||
@@ -26,6 +49,10 @@
|
|||||||
save-position-on-quit=yes
|
save-position-on-quit=yes
|
||||||
keep-open=yes
|
keep-open=yes
|
||||||
|
|
||||||
|
# force GUI, even for tracks w/o album art
|
||||||
|
# see: <https://www.reddit.com/r/mpv/comments/rvrrpt/oscosdgui_and_arch_linux/>
|
||||||
|
player-operation-mode=pseudo-gui
|
||||||
|
|
||||||
# use uosc instead (for On Screen Controls)
|
# use uosc instead (for On Screen Controls)
|
||||||
osc=no
|
osc=no
|
||||||
# uosc provides its own seeking/volume indicators, so you also don't need this
|
# uosc provides its own seeking/volume indicators, so you also don't need this
|
||||||
|
11
hosts/common/programs/rhythmbox.nix
Normal file
11
hosts/common/programs/rhythmbox.nix
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
sane.programs.rhythmbox = {
|
||||||
|
persist.plaintext = [
|
||||||
|
# playlists; index
|
||||||
|
".local/share/rhythmbox"
|
||||||
|
# album art
|
||||||
|
".cache/rhythmbox"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
@@ -7,6 +7,7 @@
|
|||||||
# - $ZDOTDIR/.zprofile
|
# - $ZDOTDIR/.zprofile
|
||||||
# - if interactive:
|
# - if interactive:
|
||||||
# - /etc/zshrc
|
# - /etc/zshrc
|
||||||
|
# -> /etc/zinputrc
|
||||||
# - $ZDOTDIR/.zshrc
|
# - $ZDOTDIR/.zshrc
|
||||||
# - if login (again):
|
# - if login (again):
|
||||||
# - /etc/zlogin
|
# - /etc/zlogin
|
||||||
@@ -79,6 +80,18 @@ in
|
|||||||
hash -d tmp="/home/colin/tmp"
|
hash -d tmp="/home/colin/tmp"
|
||||||
hash -d uninsane="/home/colin/dev/uninsane"
|
hash -d uninsane="/home/colin/dev/uninsane"
|
||||||
hash -d Videos="/home/colin/Videos"
|
hash -d Videos="/home/colin/Videos"
|
||||||
|
|
||||||
|
# emulate bash keybindings
|
||||||
|
bindkey -e
|
||||||
|
|
||||||
|
# or manually recreate what i care about...
|
||||||
|
# key[Left]=''${terminfo[kcub1]}
|
||||||
|
# key[Right]=''${terminfo[kcuf1]}
|
||||||
|
# bindkey '^R' history-incremental-search-backward
|
||||||
|
# bindkey '^A' beginning-of-line
|
||||||
|
# bindkey '^E' end-of-line
|
||||||
|
# bindkey "^''${key[Left]}" backward-word
|
||||||
|
# bindkey "^''${key[Right]}" forward-word
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
@@ -83,7 +83,7 @@
|
|||||||
fs."Books/servo".symlink.target = "/mnt/servo-media/Books";
|
fs."Books/servo".symlink.target = "/mnt/servo-media/Books";
|
||||||
fs."Videos/servo".symlink.target = "/mnt/servo-media/Videos";
|
fs."Videos/servo".symlink.target = "/mnt/servo-media/Videos";
|
||||||
fs."Videos/servo-incomplete".symlink.target = "/mnt/servo-media/incomplete";
|
fs."Videos/servo-incomplete".symlink.target = "/mnt/servo-media/incomplete";
|
||||||
fs."Music/servo".symlink.target = "/mnt/servo-media/Music";
|
# fs."Music/servo".symlink.target = "/mnt/servo-media/Music";
|
||||||
fs."Pictures/servo-macros".symlink.target = "/mnt/servo-media/Pictures/macros";
|
fs."Pictures/servo-macros".symlink.target = "/mnt/servo-media/Pictures/macros";
|
||||||
|
|
||||||
# used by password managers, e.g. unix `pass`
|
# used by password managers, e.g. unix `pass`
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
# package sets
|
# package sets
|
||||||
"tuiApps"
|
"tuiApps"
|
||||||
] ++ [
|
] ++ [
|
||||||
|
"alacritty" # terminal emulator
|
||||||
# "celluloid" # mpv frontend
|
# "celluloid" # mpv frontend
|
||||||
"chatty" # matrix/xmpp/irc client
|
"chatty" # matrix/xmpp/irc client
|
||||||
"cozy" # audiobook player
|
"cozy" # audiobook player
|
||||||
@@ -25,6 +26,7 @@
|
|||||||
"firefox"
|
"firefox"
|
||||||
# "foliate" # e-book reader
|
# "foliate" # e-book reader
|
||||||
# "fractal" # matrix client
|
# "fractal" # matrix client
|
||||||
|
"g4music" # local music player
|
||||||
# "gnome.cheese"
|
# "gnome.cheese"
|
||||||
# "gnome-feeds" # RSS reader (with claimed mobile support)
|
# "gnome-feeds" # RSS reader (with claimed mobile support)
|
||||||
# "gnome.file-roller"
|
# "gnome.file-roller"
|
||||||
@@ -32,16 +34,16 @@
|
|||||||
# "gnome-podcasts"
|
# "gnome-podcasts"
|
||||||
# "gnome.gnome-system-monitor"
|
# "gnome.gnome-system-monitor"
|
||||||
# "gnome.gnome-terminal" # works on phosh
|
# "gnome.gnome-terminal" # works on phosh
|
||||||
# "gnome.gnome-weather"
|
"gnome.gnome-weather"
|
||||||
"gpodder"
|
"gpodder"
|
||||||
"gthumb"
|
"gthumb"
|
||||||
"komikku"
|
"komikku"
|
||||||
"koreader"
|
"koreader"
|
||||||
"lemoa" # lemmy app
|
"lemoa" # lemmy app
|
||||||
# "lollypop"
|
# "lollypop"
|
||||||
|
"mate.engrampa" # archive manager
|
||||||
"mepo" # maps viewer
|
"mepo" # maps viewer
|
||||||
"mpv"
|
"mpv"
|
||||||
"nheko"
|
|
||||||
# "networkmanagerapplet"
|
# "networkmanagerapplet"
|
||||||
# "newsflash"
|
# "newsflash"
|
||||||
"pavucontrol"
|
"pavucontrol"
|
||||||
@@ -64,28 +66,31 @@
|
|||||||
"audacity"
|
"audacity"
|
||||||
"blanket" # ambient noise generator
|
"blanket" # ambient noise generator
|
||||||
"brave" # for the integrated wallet -- as a backup
|
"brave" # for the integrated wallet -- as a backup
|
||||||
|
"cantata" # music player (mpd frontend)
|
||||||
# "chromium" # chromium takes hours to build. brave is chromium-based, distributed in binary form, so prefer it.
|
# "chromium" # chromium takes hours to build. brave is chromium-based, distributed in binary form, so prefer it.
|
||||||
# "dino" # XMPP client
|
"dino" # XMPP client
|
||||||
"electrum"
|
"electrum"
|
||||||
"element-desktop"
|
"element-desktop"
|
||||||
# "font-manager" #< depends on webkitgtk4_0 (expensive to build)
|
# "font-manager" #< depends on webkitgtk4_0 (expensive to build)
|
||||||
# "gajim" # XMPP client
|
# "gajim" # XMPP client
|
||||||
"gimp" # broken on phosh
|
"gimp" # broken on phosh
|
||||||
"gnome.dconf-editor"
|
"gnome.dconf-editor"
|
||||||
"gnome.file-roller"
|
# "gnome.file-roller"
|
||||||
"gnome.gnome-disk-utility"
|
"gnome.gnome-disk-utility"
|
||||||
"gnome.nautilus" # file browser
|
"gnome.nautilus" # file browser
|
||||||
# "gnome.totem" # video player, supposedly supports UPnP
|
# "gnome.totem" # video player, supposedly supports UPnP
|
||||||
"handbrake"
|
"handbrake"
|
||||||
"hase"
|
"hase"
|
||||||
"inkscape"
|
"inkscape"
|
||||||
"jellyfin-media-player"
|
# "jellyfin-media-player"
|
||||||
"kdenlive"
|
"kdenlive"
|
||||||
"kid3" # audio tagging
|
"kid3" # audio tagging
|
||||||
"krita"
|
"krita"
|
||||||
"libreoffice" # TODO: replace with an office suite that uses saner packaging?
|
"libreoffice" # TODO: replace with an office suite that uses saner packaging?
|
||||||
"mumble"
|
"mumble"
|
||||||
|
"nheko"
|
||||||
"obsidian"
|
"obsidian"
|
||||||
|
"rhythmbox" # local music player
|
||||||
"slic3r"
|
"slic3r"
|
||||||
"steam"
|
"steam"
|
||||||
"vlc"
|
"vlc"
|
||||||
|
@@ -5,11 +5,15 @@ https://nixos.org/manual/nix/stable/language/builtins.html
|
|||||||
https://github.com/nixos/nixpkgs/pulls?q=
|
https://github.com/nixos/nixpkgs/pulls?q=
|
||||||
https://nur.nix-community.org/
|
https://nur.nix-community.org/
|
||||||
https://nix-community.github.io/home-manager/options.html
|
https://nix-community.github.io/home-manager/options.html
|
||||||
|
https://lists.sr.ht/~mil/sxmo-devel
|
||||||
https://w.uninsane.org/viewer#search?books.name=wikipedia_en_all_maxi_2022-05&pattern=
|
https://w.uninsane.org/viewer#search?books.name=wikipedia_en_all_maxi_2022-05&pattern=
|
||||||
https://jackett.uninsane.org/UI/Dashboard#search=
|
https://jackett.uninsane.org/UI/Dashboard#search=
|
||||||
|
https://lemmy.uninsane.org
|
||||||
https://fed.uninsane.org
|
https://fed.uninsane.org
|
||||||
|
https://jelly.uninsane.org
|
||||||
https://bt.uninsane.org
|
https://bt.uninsane.org
|
||||||
https://sci-hub.se
|
https://sci-hub.se
|
||||||
https://archive.is
|
https://archive.is
|
||||||
https://news.ycombinator.com
|
https://news.ycombinator.com
|
||||||
http://10.78.79.1 # Router/Firewall
|
http://10.78.79.1 # router/firewall
|
||||||
|
https://jochen-hoenicke.de/queue # johoe's mempool (bitcoin/ethereum)
|
||||||
|
@@ -3,9 +3,8 @@ let
|
|||||||
fuzzel = "${pkgs.fuzzel}/bin/fuzzel";
|
fuzzel = "${pkgs.fuzzel}/bin/fuzzel";
|
||||||
sed = "${pkgs.gnused}/bin/sed";
|
sed = "${pkgs.gnused}/bin/sed";
|
||||||
wtype = "${pkgs.wtype}/bin/wtype";
|
wtype = "${pkgs.wtype}/bin/wtype";
|
||||||
kitty = "${pkgs.kitty}/bin/kitty";
|
|
||||||
launcher-cmd = fuzzel;
|
launcher-cmd = fuzzel;
|
||||||
terminal-cmd = kitty;
|
terminal-cmd = "${pkgs.xdg-terminal-exec}/bin/xdg-terminal-exec";
|
||||||
lock-cmd = "${pkgs.swaylock}/bin/swaylock --indicator-idle-visible --indicator-radius 100 --indicator-thickness 30";
|
lock-cmd = "${pkgs.swaylock}/bin/swaylock --indicator-idle-visible --indicator-radius 100 --indicator-thickness 30";
|
||||||
vol-up-cmd = "${pkgs.pulsemixer}/bin/pulsemixer --change-volume +5";
|
vol-up-cmd = "${pkgs.pulsemixer}/bin/pulsemixer --change-volume +5";
|
||||||
vol-down-cmd = "${pkgs.pulsemixer}/bin/pulsemixer --change-volume -5";
|
vol-down-cmd = "${pkgs.pulsemixer}/bin/pulsemixer --change-volume -5";
|
||||||
|
@@ -1,5 +1,3 @@
|
|||||||
-- configversion: 737cb1de0389cee32a04785691a446a2
|
|
||||||
|
|
||||||
-- docs: <https://conky.cc/variables>
|
-- docs: <https://conky.cc/variables>
|
||||||
-- color names are X11 colors: <https://en.wikipedia.org/wiki/X11_color_names#Color_name_chart>
|
-- color names are X11 colors: <https://en.wikipedia.org/wiki/X11_color_names#Color_name_chart>
|
||||||
-- - can also use #rrggbb syntax
|
-- - can also use #rrggbb syntax
|
||||||
@@ -37,12 +35,14 @@ conky.config = {
|
|||||||
color2 = '404040',
|
color2 = '404040',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- texeci <interval_sec> <cmd>: run the command periodically, _in a separate thread_ so as not to block rendering
|
||||||
conky.text = [[
|
conky.text = [[
|
||||||
${color1}${shadecolor 707070}${font Sxmo:size=50:style=Bold}${alignc}${exec date +"%H:%M"}${font}
|
${color1}${shadecolor 707070}${font Sxmo:size=50:style=Bold}${alignc}${exec date +"%H:%M"}${font}
|
||||||
${color2}${shadecolor a4d7d0}${font Sxmo:size=20}${alignc}${exec date +"%a %d %b"}${font}
|
${color2}${shadecolor a4d7d0}${font Sxmo:size=20}${alignc}${exec date +"%a %d %b"}${font}
|
||||||
|
|
||||||
|
|
||||||
${color1}${shadecolor}${font Sxmo:size=22:style=Bold}${alignc}${exec @bat@ }${font}
|
${color1}${shadecolor}${font Sxmo:size=22:style=Bold}${alignc}${exec @bat@ }${font}
|
||||||
|
${color1}${shadecolor}${font Sxmo:size=20:style=Bold}${alignc}${texeci 600 @weather@ }${font}
|
||||||
|
|
||||||
|
|
||||||
${color2}${shadecolor a4d7d0}${font Sxmo:size=16}${alignc}⇅ ${downspeedf wlan0}K/s${font}
|
${color2}${shadecolor a4d7d0}${font Sxmo:size=16}${alignc}⇅ ${downspeedf wlan0}K/s${font}
|
||||||
|
@@ -37,7 +37,7 @@
|
|||||||
# - live in ~/.local/state/sxmo.log
|
# - live in ~/.local/state/sxmo.log
|
||||||
# - ~/.local/state/superd.log
|
# - ~/.local/state/superd.log
|
||||||
# - ~/.local/state/superd/logs/<daemon>.log
|
# - ~/.local/state/superd/logs/<daemon>.log
|
||||||
# - `journalctl --user --boot` (lightm redirects the sxmo session stdout => systemd)
|
# - `journalctl --user --boot` (lightdm redirects the sxmo session stdout => systemd)
|
||||||
#
|
#
|
||||||
# - default components:
|
# - default components:
|
||||||
# - DE: sway (if wayland), dwm (if X)
|
# - DE: sway (if wayland), dwm (if X)
|
||||||
@@ -57,6 +57,12 @@ let
|
|||||||
knownTerminals = {
|
knownTerminals = {
|
||||||
vte = "vte-2.91";
|
vte = "vte-2.91";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
systemd-cat = "${pkgs.systemd}/bin/systemd-cat";
|
||||||
|
runWithLogger = identifier: cmd: pkgs.writeShellScript identifier ''
|
||||||
|
echo "launching ${identifier}..." | ${systemd-cat} --identifier=${identifier}
|
||||||
|
${cmd} 2>&1 | ${systemd-cat} --identifier=${identifier}
|
||||||
|
'';
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options = with lib; {
|
options = with lib; {
|
||||||
@@ -65,17 +71,31 @@ in
|
|||||||
type = types.bool;
|
type = types.bool;
|
||||||
};
|
};
|
||||||
sane.gui.sxmo.greeter = mkOption {
|
sane.gui.sxmo.greeter = mkOption {
|
||||||
type = types.enum [ "lightdm-mobile" "sway" ];
|
type = types.enum [
|
||||||
default = "lightdm-mobile";
|
"greetd-phog"
|
||||||
|
"greetd-sway-phog"
|
||||||
|
"greetd-sxmo"
|
||||||
|
"lightdm-mobile"
|
||||||
|
"sway-gtkgreet"
|
||||||
|
];
|
||||||
|
# default = "lightdm-mobile";
|
||||||
|
default = "greetd-sway-phog";
|
||||||
description = ''
|
description = ''
|
||||||
which greeter to use.
|
which greeter to use.
|
||||||
"lightdm-mobile" => keypad style greeter. can only enter digits 0-9 as password.
|
"greetd-phog" => phosh-based greeter. keypad (0-9) with option to open an on-screen keyboard.
|
||||||
"sway" => layered sway greeter. behaves as if you booted to swaylock.
|
"greetd-sway-phog" => phog, but uses sway as the compositor instead of phoc.
|
||||||
|
requires a patched phog, since sway doesn't provide the Wayland global "zphoc_layer_shell_effects_v1".
|
||||||
|
"greetd-sxmo" => launch sxmo directly from greetd, no auth.
|
||||||
|
this means no keychain unlocked or encrypted home mounted.
|
||||||
|
"lightdm-mobile" => keypad style greeter. can only enter digits 0-9 as password.
|
||||||
|
"sway-gtkgreet" => layered sway greeter. behaves as if you booted to swaylock.
|
||||||
|
this isn't practically usable on mobile because of keyboard input.
|
||||||
|
also, it takes literally 6 minutes to appear
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
sane.gui.sxmo.package = mkOption {
|
sane.gui.sxmo.package = mkOption {
|
||||||
type = types.package;
|
type = types.package;
|
||||||
default = pkgs.sxmo-utils;
|
default = pkgs.sxmo-utils-latest;
|
||||||
description = ''
|
description = ''
|
||||||
sxmo base scripts and hooks collection.
|
sxmo base scripts and hooks collection.
|
||||||
consider overriding the outputs under /share/sxmo/default_hooks
|
consider overriding the outputs under /share/sxmo/default_hooks
|
||||||
@@ -116,6 +136,7 @@ in
|
|||||||
};
|
};
|
||||||
in {
|
in {
|
||||||
SXMO_BAR_SHOW_BAT_PER = mkSettingsOpt "1" "show battery percentage in statusbar";
|
SXMO_BAR_SHOW_BAT_PER = mkSettingsOpt "1" "show battery percentage in statusbar";
|
||||||
|
SXMO_DISABLE_CONFIGVERSION_CHECK = mkSettingsOpt "1" "allow omitting the configversion line from user-provided sxmo dotfiles";
|
||||||
SXMO_UNLOCK_IDLE_TIME = mkSettingsOpt "300" "how many seconds of inactivity before locking the screen"; # lock -> screenoff happens 8s later, not configurable
|
SXMO_UNLOCK_IDLE_TIME = mkSettingsOpt "300" "how many seconds of inactivity before locking the screen"; # lock -> screenoff happens 8s later, not configurable
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -175,6 +196,8 @@ in
|
|||||||
hardware.bluetooth.enable = true;
|
hardware.bluetooth.enable = true;
|
||||||
services.blueman.enable = true;
|
services.blueman.enable = true;
|
||||||
|
|
||||||
|
hardware.opengl.enable = true;
|
||||||
|
|
||||||
# TODO: nerdfonts is 4GB. it accepts an option to ship only some fonts: probably want to use that.
|
# TODO: nerdfonts is 4GB. it accepts an option to ship only some fonts: probably want to use that.
|
||||||
fonts.packages = [ pkgs.nerdfonts ];
|
fonts.packages = [ pkgs.nerdfonts ];
|
||||||
|
|
||||||
@@ -204,7 +227,10 @@ in
|
|||||||
# TODO: only need the share/sxmo directly linked
|
# TODO: only need the share/sxmo directly linked
|
||||||
"${cfg.package}/share"
|
"${cfg.package}/share"
|
||||||
];
|
];
|
||||||
};
|
} // (lib.filterAttrs # certain settings are read before the `profile` is sourced
|
||||||
|
(k: v: k == "SXMO_DISABLE_CONFIGVERSION_CHECK")
|
||||||
|
cfg.settings
|
||||||
|
);
|
||||||
|
|
||||||
systemd.services."sxmo-set-permissions" = {
|
systemd.services."sxmo-set-permissions" = {
|
||||||
description = "configure specific /sys and /dev nodes to be writable by sxmo scripts";
|
description = "configure specific /sys and /dev nodes to be writable by sxmo scripts";
|
||||||
@@ -248,14 +274,8 @@ in
|
|||||||
};
|
};
|
||||||
sane.user.fs.".config/sxmo/profile".symlink.text = let
|
sane.user.fs.".config/sxmo/profile".symlink.text = let
|
||||||
mkKeyValue = key: value: ''export ${key}="${value}"'';
|
mkKeyValue = key: value: ''export ${key}="${value}"'';
|
||||||
userConfig = lib.generators.toKeyValue { inherit mkKeyValue; } cfg.settings;
|
in
|
||||||
in ''
|
lib.generators.toKeyValue { inherit mkKeyValue; } cfg.settings;
|
||||||
# configversion: 4284f96d91e9550ff8f3b25823e402ad
|
|
||||||
# ^ upstream adds new options every now and then, expects user config file
|
|
||||||
# to include the md5sum of the template it's based on.
|
|
||||||
# see `setup_config_version.sh`
|
|
||||||
${userConfig}
|
|
||||||
'';
|
|
||||||
|
|
||||||
sane.user.fs.".config/sxmo/sway".symlink.target = pkgs.substituteAll {
|
sane.user.fs.".config/sxmo/sway".symlink.target = pkgs.substituteAll {
|
||||||
src = ./sway-config;
|
src = ./sway-config;
|
||||||
@@ -279,6 +299,7 @@ in
|
|||||||
in pkgs.substituteAll {
|
in pkgs.substituteAll {
|
||||||
src = ./conky-config;
|
src = ./conky-config;
|
||||||
bat = "${battery_estimate}/bin/battery_estimate";
|
bat = "${battery_estimate}/bin/battery_estimate";
|
||||||
|
weather = "timeout 20 ${pkgs.sane-weather}/bin/sane-weather";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,16 +334,14 @@ in
|
|||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
|
||||||
(lib.mkIf (cfg.greeter == "sway") {
|
(lib.mkIf (cfg.greeter == "sway-gtkgreet") {
|
||||||
services.greetd = {
|
services.greetd = {
|
||||||
enable = true;
|
enable = true;
|
||||||
# borrowed from gui/sway
|
# borrowed from gui/sway
|
||||||
settings.default_session.command =
|
settings.default_session.command =
|
||||||
let
|
let
|
||||||
# start sway and have it construct the gtkgreeter
|
# start sway and have it construct the gtkgreeter
|
||||||
sway-as-greeter = pkgs.writeShellScriptBin "sway-as-greeter" ''
|
sway-as-greeter = runWithLogger "sway-as-greeter" "${pkgs.sway}/bin/sway --debug --config ${sway-config-into-gtkgreet}";
|
||||||
${pkgs.sway}/bin/sway --debug --config ${sway-config-into-gtkgreet} > /var/log/sway/sway-as-greeter.log 2>&1
|
|
||||||
'';
|
|
||||||
# (config file for the above)
|
# (config file for the above)
|
||||||
sway-config-into-gtkgreet = pkgs.writeText "greetd-sway-config" ''
|
sway-config-into-gtkgreet = pkgs.writeText "greetd-sway-config" ''
|
||||||
exec "${gtkgreet-launcher}"
|
exec "${gtkgreet-launcher}"
|
||||||
@@ -333,12 +352,60 @@ in
|
|||||||
# so that command must exist on the specific user's path who is logging in. it doesn't need to exist system-wide.
|
# so that command must exist on the specific user's path who is logging in. it doesn't need to exist system-wide.
|
||||||
${pkgs.greetd.gtkgreet}/bin/gtkgreet --layer-shell --command sxmo_winit.sh
|
${pkgs.greetd.gtkgreet}/bin/gtkgreet --layer-shell --command sxmo_winit.sh
|
||||||
'';
|
'';
|
||||||
in "${sway-as-greeter}/bin/sway-as-greeter";
|
in "${sway-as-greeter}";
|
||||||
};
|
};
|
||||||
|
})
|
||||||
|
|
||||||
sane.fs."/var/log/sway" = {
|
(lib.mkIf (cfg.greeter == "greetd-sway-phog") {
|
||||||
dir.acl.mode = "0777";
|
services.greetd = {
|
||||||
wantedBeforeBy = [ "greetd.service" "display-manager.service" ];
|
enable = true;
|
||||||
|
# borrowed from gui/sway
|
||||||
|
settings.default_session.command =
|
||||||
|
let
|
||||||
|
# start sway and have it construct the greeter
|
||||||
|
sway-as-greeter = runWithLogger "sway-as-greeter" "${pkgs.sway}/bin/sway --debug --config ${sway-config-into-phog}";
|
||||||
|
# (config file for the above)
|
||||||
|
sway-config-into-phog = pkgs.writeText "greetd-sway-config" ''
|
||||||
|
exec "${pkgs.phog}/libexec/phog"
|
||||||
|
'';
|
||||||
|
in "${sway-as-greeter}";
|
||||||
|
};
|
||||||
|
# phog locates sxmo_winit.sh via <env>/share/wayland-sessions
|
||||||
|
environment.pathsToLink = [ "/share/wayland-sessions" ];
|
||||||
|
|
||||||
|
# persisting fontconfig & mesa_shader_cache improves start time from like 6 minutes to 1 minute
|
||||||
|
# TODO: this should apply to any greetd implementation
|
||||||
|
users.users.greeter.home = "/var/lib/greeter";
|
||||||
|
sane.persist.sys.plaintext = [
|
||||||
|
{ user = "greeter"; group = "greeter"; path = "/var/lib/greeter/.cache/fontconfig"; }
|
||||||
|
{ user = "greeter"; group = "greeter"; path = "/var/lib/greeter/.cache/mesa_shader_cache"; }
|
||||||
|
];
|
||||||
|
})
|
||||||
|
|
||||||
|
(lib.mkIf (cfg.greeter == "greetd-phog") {
|
||||||
|
services.greetd = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
# launch directly: but stdout/stderr gets dropped
|
||||||
|
# settings.default_session.command = "${pkgs.phog}/bin/phog";
|
||||||
|
|
||||||
|
# wrapper to launch phog and redirect logs to system journal.
|
||||||
|
settings.default_session.command = let
|
||||||
|
launch-phog = runWithLogger "phog" "${pkgs.phog}/bin/phog";
|
||||||
|
in "${launch-phog}";
|
||||||
|
};
|
||||||
|
environment.pathsToLink = [ "/share/wayland-sessions" ];
|
||||||
|
})
|
||||||
|
|
||||||
|
(lib.mkIf (cfg.greeter == "greetd-sxmo") {
|
||||||
|
services.greetd = {
|
||||||
|
enable = true;
|
||||||
|
settings.default_session = {
|
||||||
|
command = let
|
||||||
|
launch-sxmo = runWithLogger "sxmo" "${cfg.package}/bin/sxmo_winit.sh";
|
||||||
|
in "${launch-sxmo}";
|
||||||
|
user = "colin";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -352,16 +419,6 @@ in
|
|||||||
# '';
|
# '';
|
||||||
# }];
|
# }];
|
||||||
# services.xserver.enable = true;
|
# services.xserver.enable = true;
|
||||||
|
|
||||||
# services.greetd = {
|
|
||||||
# enable = true;
|
|
||||||
# settings = {
|
|
||||||
# default_session = {
|
|
||||||
# command = "${cfg.package}/bin/sxmo_winit.sh";
|
|
||||||
# user = "colin";
|
|
||||||
# };
|
|
||||||
# };
|
|
||||||
# };
|
|
||||||
]))
|
]))
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +1,8 @@
|
|||||||
# Default config for sway
|
|
||||||
# configversion: 5eff902ecca36b4e75567322335cc81c
|
|
||||||
#
|
|
||||||
# Copy this to ~/.config/sway/config and edit it to your liking.
|
|
||||||
#
|
|
||||||
# Read `man 5 sway` for a complete reference.
|
# Read `man 5 sway` for a complete reference.
|
||||||
|
|
||||||
|
# TODO: use stock sxmo config & override via /etc/sway/config.d/*
|
||||||
|
# especially, this will let me avoid issues around `configversion`
|
||||||
|
|
||||||
### Variables
|
### Variables
|
||||||
#
|
#
|
||||||
# Mod4 = Logo key
|
# Mod4 = Logo key
|
||||||
@@ -47,25 +45,33 @@ titlebar_border_thickness 1
|
|||||||
titlebar_padding 12 1
|
titlebar_padding 12 1
|
||||||
title_align center
|
title_align center
|
||||||
|
|
||||||
|
# tabbed windows by default
|
||||||
|
workspace_layout tabbed
|
||||||
|
|
||||||
### tab colors (#border #background #text [#indicator #childBorder])
|
### tab colors (#border #background #text [#indicator #childBorder])
|
||||||
# fucused & unfocused are the main interest
|
# focused & unfocused are the main interest
|
||||||
|
# urgent is used when an inactive window wants attention (e.g. terminal rings a bell)
|
||||||
|
# colors are synchronized with waybar and mpv
|
||||||
client.focused #1f5e54 #418379 #ffffff
|
client.focused #1f5e54 #418379 #ffffff
|
||||||
client.focused_inactive #1f5e54 #5f676a #ffffff
|
client.focused_inactive #1f5e54 #5f676a #ffffff
|
||||||
client.unfocused #1f5e54 #1f554c #b4b4b4
|
client.unfocused #1f5e54 #1f554c #b4b4b4
|
||||||
client.urgent #e64291 #e64291 #ffffff
|
client.urgent #ff8080 #ff8080 #ffffff
|
||||||
|
|
||||||
### Key bindings
|
### Key bindings
|
||||||
#
|
#
|
||||||
# Basics:
|
# Basics:
|
||||||
#
|
#
|
||||||
|
input * xkb_options compose:ralt
|
||||||
|
|
||||||
# Start a terminal
|
# Start a terminal
|
||||||
bindsym $mod+Return exec $term
|
bindsym $mod+Return exec $term
|
||||||
|
|
||||||
# Launch appmenu
|
# Launch appmenu
|
||||||
bindsym $mod+p exec sxmo_appmenu.sh
|
bindsym $mod+p exec sxmo_appmenu.sh
|
||||||
|
bindsym $mod+Shift+p exec sxmo_appmenu.sh sys
|
||||||
|
|
||||||
# Launch scripts menu
|
# Wm menu switcher
|
||||||
bindsym $mod+i exec sxmo_appmenu.sh scripts
|
bindsym $mod+i exec sxmo_wmmenu.sh windowswitcher
|
||||||
|
|
||||||
# Kill focused window
|
# Kill focused window
|
||||||
bindsym $mod+Shift+q kill
|
bindsym $mod+Shift+q kill
|
||||||
@@ -157,7 +163,7 @@ client.urgent #e64291 #e64291 #ffffff
|
|||||||
bindsym $mod+e layout toggle split
|
bindsym $mod+e layout toggle split
|
||||||
|
|
||||||
# Make the current focus fullscreen
|
# Make the current focus fullscreen
|
||||||
# bindsym $mod+f fullscreen
|
bindsym $mod+f fullscreen
|
||||||
|
|
||||||
# Toggle the current focus between tiling and floating mode
|
# Toggle the current focus between tiling and floating mode
|
||||||
bindsym $mod+Shift+space floating toggle
|
bindsym $mod+Shift+space floating toggle
|
||||||
@@ -167,6 +173,12 @@ client.urgent #e64291 #e64291 #ffffff
|
|||||||
|
|
||||||
# Move focus to the parent container
|
# Move focus to the parent container
|
||||||
bindsym $mod+a focus parent
|
bindsym $mod+a focus parent
|
||||||
|
|
||||||
|
# Manual locker
|
||||||
|
bindsym $mod+g exec sxmo_hook_locker.sh
|
||||||
|
|
||||||
|
# Shutdown
|
||||||
|
bindsym $mod+t exec sxmo_appmenu.sh power
|
||||||
#
|
#
|
||||||
# Scratchpad:
|
# Scratchpad:
|
||||||
#
|
#
|
||||||
@@ -187,16 +199,16 @@ mode "resize" {
|
|||||||
# right will grow the containers width
|
# right will grow the containers width
|
||||||
# up will shrink the containers height
|
# up will shrink the containers height
|
||||||
# down will grow the containers height
|
# down will grow the containers height
|
||||||
bindsym $left resize shrink width 10px
|
bindsym $left resize shrink width 30px
|
||||||
bindsym $down resize grow height 10px
|
bindsym $down resize grow height 30px
|
||||||
bindsym $up resize shrink height 10px
|
bindsym $up resize shrink height 30px
|
||||||
bindsym $right resize grow width 10px
|
bindsym $right resize grow width 30px
|
||||||
|
|
||||||
# Ditto, with arrow keys
|
# Ditto, with arrow keys
|
||||||
bindsym Left resize shrink width 10px
|
bindsym Left resize shrink width 30px
|
||||||
bindsym Down resize grow height 10px
|
bindsym Down resize grow height 30px
|
||||||
bindsym Up resize shrink height 10px
|
bindsym Up resize shrink height 30px
|
||||||
bindsym Right resize grow width 10px
|
bindsym Right resize grow width 30px
|
||||||
|
|
||||||
# Return to default mode
|
# Return to default mode
|
||||||
bindsym Return mode "default"
|
bindsym Return mode "default"
|
||||||
@@ -222,13 +234,31 @@ bar {
|
|||||||
statusline #ffffff
|
statusline #ffffff
|
||||||
background #323232
|
background #323232
|
||||||
inactive_workspace #32323200 #32323200 #5c5c5c
|
inactive_workspace #32323200 #32323200 #5c5c5c
|
||||||
font "Sxmo"
|
font "Sxmo 10"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for_window [app_id="pinentry-.*"] floating true
|
||||||
for_window [app_id="foot" title=".*sxmo/modem/.*/draft.txt.*"] resize set height 25
|
for_window [app_id="foot" title=".*sxmo/modem/.*/draft.txt.*"] resize set height 25
|
||||||
for_window [title="megapixels"] inhibit_idle open
|
for_window [title="megapixels"] inhibit_idle open
|
||||||
|
|
||||||
|
# Need playerctl installed and running
|
||||||
|
bindsym XF86AudioPlay exec playerctl play-pause
|
||||||
|
bindsym XF86AudioStop exec playerctl stop
|
||||||
|
bindsym XF86AudioNext exec playerctl next
|
||||||
|
bindsym XF86AudioPrev exec playerctl previous
|
||||||
|
|
||||||
|
bindsym XF86MonBrightnessUp exec sxmo_brightness.sh up
|
||||||
|
bindsym XF86MonBrightnessDown exec sxmo_brightness.sh down
|
||||||
|
|
||||||
|
bindsym Print exec sxmo_screenshot.sh
|
||||||
|
|
||||||
|
bindsym button2 kill
|
||||||
|
|
||||||
|
bindswitch lid:on exec sxmo_wm.sh dpms on
|
||||||
|
bindswitch lid:off exec sxmo_wm.sh dpms off
|
||||||
|
|
||||||
|
|
||||||
include /etc/sway/config.d/*
|
include /etc/sway/config.d/*
|
||||||
|
|
||||||
exec 'printf %s "$SWAYSOCK" > "$XDG_RUNTIME_DIR"/sxmo.swaysock'
|
exec 'printf %s "$SWAYSOCK" > "$XDG_RUNTIME_DIR"/sxmo.swaysock'
|
||||||
|
@@ -24,8 +24,7 @@ in
|
|||||||
(mkIf cfg {
|
(mkIf cfg {
|
||||||
sane.programs.docsets.enableFor.system = true;
|
sane.programs.docsets.enableFor.system = true;
|
||||||
sane.programs.ldd-aarch64.enableFor.user.colin = true;
|
sane.programs.ldd-aarch64.enableFor.user.colin = true;
|
||||||
# TODO: migrate this to `sane.user.programs.zeal.enable = true`
|
# sane.programs.zeal.enableFor.user.colin = true;
|
||||||
sane.programs.zeal.enableFor.user.colin = true;
|
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"bozo": 0,
|
||||||
|
"content_length": 3520653,
|
||||||
|
"content_type": "application/xml; charset=utf-8",
|
||||||
|
"description": "There\u2019s a reason the History Channel has produced hundreds of documentaries about Hitler but only a few about Dwight D. Eisenhower. Bad guys (and gals) are eternally fascinating. Behind the Bastards dives in past the Cliffs Notes of the worst humans in history and exposes the bizarre realities of their lives. Listeners will learn about the young adult novels that helped Hitler form his monstrous ideology, the founder of Blackwater\u2019s insane quest to build his own Air Force, the bizarre lives of the sons and daughters of dictators and Saddam Hussein\u2019s side career as a trashy romance novelist.",
|
||||||
|
"favicon": "",
|
||||||
|
"favicon_data_uri": "",
|
||||||
|
"hubs": [],
|
||||||
|
"is_podcast": true,
|
||||||
|
"is_push": false,
|
||||||
|
"item_count": 689,
|
||||||
|
"last_updated": "2023-08-15T04:00:00+00:00",
|
||||||
|
"score": 8,
|
||||||
|
"self_url": "https://www.omnycontent.com/d/playlist/e73c998e-6e60-432f-8610-ae210140c5b1/e5f91208-cc7e-4726-a312-ae280140ad11/d64f756d-6d5e-4fae-b24f-ae280140ad36/podcast.rss",
|
||||||
|
"site_name": "",
|
||||||
|
"site_url": "",
|
||||||
|
"title": "Behind the Bastards",
|
||||||
|
"url": "https://omnycontent.com/d/playlist/e73c998e-6e60-432f-8610-ae210140c5b1/E5F91208-CC7E-4726-A312-AE280140AD11/D64F756D-6D5E-4FAE-B24F-AE280140AD36/podcast.rss",
|
||||||
|
"velocity": 0.35,
|
||||||
|
"version": "rss20"
|
||||||
|
}
|
21
modules/data/feeds/sources/omegataupodcast.net/default.json
Normal file
21
modules/data/feeds/sources/omegataupodcast.net/default.json
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"bozo": 0,
|
||||||
|
"content_length": 805006,
|
||||||
|
"content_type": "application/rss+xml; charset=utf-8",
|
||||||
|
"description": "Wissenschaft und Technik im Kopfhoerer / Science and Engineering in your Headphones",
|
||||||
|
"favicon": "http://omegataupodcast.net/omegatau_fav.png",
|
||||||
|
"favicon_data_uri": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAsTAAALEwEAmpwYAAACC2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDx0aWZmOkNvbXByZXNzaW9uPjE8L3RpZmY6Q29tcHJlc3Npb24+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOlBob3RvbWV0cmljSW50ZXJwcmV0YXRpb24+MjwvdGlmZjpQaG90b21ldHJpY0ludGVycHJldGF0aW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KD0UqkwAAB2BJREFUWAmdV1tvVFUU/ubMmQud0k6vUzrTUsq1twSMmKI+idBIJJFECPAACS9NTLzwYkzwof/BoC8QE30xITHSSIgQVEyEUsDUVkRgqC200HtnmPvd9e1hD6cNmOpuTvc+a6+9Lt9ea501tmPHjhXwH4dpmpiamsKePXvQ29urThcKBdhsNqRSKfT19WF8fBzl5eXIZrOKblVBXj6GYcCMRqPWvZIwLihQP1Ymp9OJJ0+eKOFWul7TiFgsBrvdrnieKbQhny/A6XDA5XYrGeKMqayhIu0FaXzP5/PI5XKKroVog2gEPXjeoGLK4JwXT52yRiaFnKBBmeUuD1ZXVWFmdhYGBXNwQx8KhUJ4/PgxpqenEQ6HkUgkkE6nlTfJZFLRL1y4gOehR1lzc3O4desWJh89wq3hYeSEFqnyYcTmxl1HOUYNF/I0LpeH7dChQ2JDAQ6BhbBR6IYNG9Dc3Iza2lp1j/RWI0WvGhsbkclkUFFRgS1btlBnCT0iNjIyogxWCBFZ4U390o9CLAyBDXaHC8OOOlz+MwiTyik8Eomgrq4OBw4cQCAQQFlZmaITcj2IksvlwubNmzWpNGs+Grh169YSXS0EfvxwAkj8KIFVB5S14nb4FXzz+z2YPECIGxoacPDgQdTU1Kh7pzLCrq+IgkjjO73XiDwvDsjHUZDZEOfSiSRs6RQcCaEZcu/2ekQliDEVgknL4/E4enp6FOQ0hkN7pGetiDNpmq6Yl/3TvMKkdvhuFMQICTdFKcRRyGaAcBomoec9NjU1qRzWwukpD2pP6RX3iBhpKxmS7aJQYkDOpau3wXRWSww4YXdXoMzux47dEvj0eP369WCgEXIqoXIq4vudO3cwMTGhgpMBxthgkdm+fbtCjLxWNHjm9OnTWFhYUPGSkfcKrxfhRBOiERamnFxxAe4KJ1o8Lpj0sr6+XjlEYRwUSGXnz5/HuXPnlCLSNP3UqVPo7OzEyZMnVcASHQ07ZQwNDWFwcFBly/z8PDo6OpCX85NT07gZnESDtxId6/w4c+ZnmPSI6aSV0wCm5NjYGC5fvqwOc08HFo1obW3FwMAALl26hKNHj5ZQ00YykDdu3IjKykr1VFdXIytIzEjet3jc8NdXoVz0dnYGiga4pSxSCQXoMStViilHxSyt1j2WYaasLkTcszrALOHVrlq1Ss38HsSkgN2fmGHaIZnJKoQTKQlCMtFjqwCuqcTqtdUAwr3cKG04Z/JqfvJyHQpFpfJJbDnkvcgEQ+gGvWTAWQcNYGqSbjXMykOhL9pbzheNxZFKZ+AwjSVnGHGSUaYKIKswrgmjDiyrwJWuKYMOhMIROJxSVe2G+jAtcVUsEB1FiLRg7RmzQK/13kpnrTyZTCH49xRsRhEt0vnHoaNNVcKVCl4pH51KC+ShyDyyTFFbsaCtckveC+LsB5RzYkzpc7xcOBk49Lx8/9/eGbx/BSeQSWfhcrAnyKsClErJV1HSMSNZQTSowSTUfNGDa3pAS3UW6L2VzDw/vxDG9GIMgUafKJdT8kzNzOL2H9eViGTbS6ivqynqYbBRkdVTrlma/48BPMOo95a7lRNj98bx7jtv4dMTn5TaM5dcRX//9/j6qy9hMp9ZKJiOetAAVsjlhul9PVuN1jQioM4JwS6RD4SkqfGgvb1Ns6j515orajZYsZanHAWvXr16ydUsOS0vvKYXIcQ+oKi8eEo7x+vmx4gjK9WQw2AbxqJDpdZYYD2nAtKYz1TIh3x8Zxn2eDxKiPUcy7rf34gH92eV52RobgoovuLZYiNL1DkMNpksu9bBzTVr1qC7uxtj8lGiMvYN+mGz6vP5sGnTptIxCqfBNHL3rp1Cn8J3315U+907upfw8SX+tPFRPSEFtre3K++0IGbB3r171VdtcnJSNaxUQDj5IWJf6JXvPK9Pf0t4lqOnZzfOnu3H3XtB7HpzJ1rXrVNI6n3KmZ6eEc5y2Pbt21fw+/04cuSIgpZwkpEzvWE2EBHeHwdpOkWJXltbWyle9DmtSB2Qf1omf5QYUhUXFxfxxq63izr48ykYDKouh/dH6/hQCGcGKQ3gu6ZRsb7DmRl6UmxY9Tkq5FrP+lwuV7z3gYFrGLp5RRCsgL2rq6uPHrHtamlpQVVVtSh6JpDCtSAtVNOIBtOYGUPjqUgXNrFBzhW7Y/KTl8E7OjqK3vc+gm9Nk/BKtki71Mc7ZCASCfYHjG4K5H1zjw+N1Gtei14TiRs3bmJOWq/GRr/iozLrQ8PYK167NogPj3+MB5OzqK/1Ii3xYzt8+DCbVnUwGo1JMxlCTW2dtF3r0BTww1vlRZkYZYoR/KgQBQpjZkwL/MHgKC7+dAXjwWG8/8FxvP7aq/AHGuVMsZBFohE8fDiBq1ev4YvPP0NTaxfWBnyIxhOwi6G2/fv3F5LSGsXjKdU0RGIJzMzJb8OHIbmHuIDnRlmtBxVl8vNMIMxIIVmIJJGRDgfyq89d48XmtT4F72/Xh4W2NKWF8HRUY9vLbYKqU1IwqbohbvwDi4As2ZCohrEAAAAASUVORK5CYII=",
|
||||||
|
"hubs": [],
|
||||||
|
"is_podcast": true,
|
||||||
|
"is_push": false,
|
||||||
|
"item_count": 100,
|
||||||
|
"last_updated": "2023-06-16T09:08:08+00:00",
|
||||||
|
"score": 10,
|
||||||
|
"self_url": "https://omegataupodcast.net/feed/mp3/",
|
||||||
|
"site_name": "omega tau science & engineering podcast",
|
||||||
|
"site_url": "https://omegataupodcast.net",
|
||||||
|
"title": "omega tau science & engineering podcast",
|
||||||
|
"url": "https://omegataupodcast.net/feed/mp3/",
|
||||||
|
"velocity": 0.062,
|
||||||
|
"version": "rss20"
|
||||||
|
}
|
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"bozo": 0,
|
||||||
|
"content_length": 87719,
|
||||||
|
"content_type": "application/xml; charset=utf-8",
|
||||||
|
"description": "Useful Idiots is an informative and irreverent politics podcast.",
|
||||||
|
"favicon": "",
|
||||||
|
"favicon_data_uri": "",
|
||||||
|
"hubs": [],
|
||||||
|
"is_podcast": true,
|
||||||
|
"is_push": false,
|
||||||
|
"item_count": 20,
|
||||||
|
"last_updated": "2023-08-15T14:54:32+00:00",
|
||||||
|
"score": 14,
|
||||||
|
"self_url": "https://usefulidiots.substack.com/feed",
|
||||||
|
"site_name": "Useful Idiots | Substack",
|
||||||
|
"site_url": "https://usefulidiots.substack.com",
|
||||||
|
"title": "Useful Idiots",
|
||||||
|
"url": "https://usefulidiots.substack.com/feed",
|
||||||
|
"velocity": 0.655,
|
||||||
|
"version": "rss20"
|
||||||
|
}
|
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"bozo": 0,
|
||||||
|
"content_length": 232527,
|
||||||
|
"content_type": "application/xml; charset=utf-8",
|
||||||
|
"description": "Not wrong political opinions.",
|
||||||
|
"favicon": "",
|
||||||
|
"favicon_data_uri": "",
|
||||||
|
"hubs": [],
|
||||||
|
"is_podcast": true,
|
||||||
|
"is_push": false,
|
||||||
|
"item_count": 67,
|
||||||
|
"last_updated": "2023-08-09T21:26:55+00:00",
|
||||||
|
"score": -10,
|
||||||
|
"self_url": "https://feeds.acast.com/public/shows/6490a2ce7ded6b001126fa5b",
|
||||||
|
"site_name": "",
|
||||||
|
"site_url": "",
|
||||||
|
"title": "We're Not Wrong",
|
||||||
|
"url": "https://feeds.acast.com/public/shows/6490a2ce7ded6b001126fa5b",
|
||||||
|
"velocity": 0.145,
|
||||||
|
"version": "rss20"
|
||||||
|
}
|
@@ -9,6 +9,10 @@ let
|
|||||||
pname = "ensure-dir";
|
pname = "ensure-dir";
|
||||||
src = ./.;
|
src = ./.;
|
||||||
};
|
};
|
||||||
|
ensure-file = pkgs.static-nix-shell.mkBash {
|
||||||
|
pname = "ensure-file";
|
||||||
|
src = ./.;
|
||||||
|
};
|
||||||
ensure-symlink = pkgs.static-nix-shell.mkBash {
|
ensure-symlink = pkgs.static-nix-shell.mkBash {
|
||||||
pname = "ensure-symlink";
|
pname = "ensure-symlink";
|
||||||
src = ./.;
|
src = ./.;
|
||||||
@@ -33,6 +37,10 @@ let
|
|||||||
type = types.nullOr dirEntry;
|
type = types.nullOr dirEntry;
|
||||||
default = null;
|
default = null;
|
||||||
};
|
};
|
||||||
|
file = mkOption {
|
||||||
|
type = types.nullOr (fileEntryFor name);
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
symlink = mkOption {
|
symlink = mkOption {
|
||||||
type = types.nullOr (symlinkEntryFor name);
|
type = types.nullOr (symlinkEntryFor name);
|
||||||
default = null;
|
default = null;
|
||||||
@@ -81,6 +89,8 @@ let
|
|||||||
default-acl
|
default-acl
|
||||||
(lib.mkIf (config.dir != null)
|
(lib.mkIf (config.dir != null)
|
||||||
(sane-lib.filterNonNull config.dir.acl))
|
(sane-lib.filterNonNull config.dir.acl))
|
||||||
|
(lib.mkIf (config.file != null)
|
||||||
|
(sane-lib.filterNonNull config.file.acl))
|
||||||
(lib.mkIf (config.symlink != null)
|
(lib.mkIf (config.symlink != null)
|
||||||
(sane-lib.filterNonNull config.symlink.acl))
|
(sane-lib.filterNonNull config.symlink.acl))
|
||||||
];
|
];
|
||||||
@@ -88,6 +98,7 @@ let
|
|||||||
# actually generate the item
|
# actually generate the item
|
||||||
generated.command = lib.mkMerge [
|
generated.command = lib.mkMerge [
|
||||||
(lib.mkIf (config.dir != null) [ "${ensure-dir}/bin/ensure-dir" name ])
|
(lib.mkIf (config.dir != null) [ "${ensure-dir}/bin/ensure-dir" name ])
|
||||||
|
(lib.mkIf (config.file != null) [ "${ensure-file}/bin/ensure-file" name config.file.copyFrom ])
|
||||||
(lib.mkIf (config.symlink != null) [ "${ensure-symlink}/bin/ensure-symlink" name config.symlink.target ])
|
(lib.mkIf (config.symlink != null) [ "${ensure-symlink}/bin/ensure-symlink" name config.symlink.target ])
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -124,7 +135,27 @@ let
|
|||||||
# takes no special options
|
# takes no special options
|
||||||
dirEntry = types.submodule propagatedGenerateMod;
|
dirEntry = types.submodule propagatedGenerateMod;
|
||||||
|
|
||||||
symlinkEntryFor = path: types.submodule ({ config, ...}: {
|
fileEntryFor = path: types.submodule ({ config, ... }: {
|
||||||
|
options = {
|
||||||
|
inherit (propagatedGenerateMod.options) acl;
|
||||||
|
text = mkOption {
|
||||||
|
type = types.nullOr types.lines;
|
||||||
|
default = null;
|
||||||
|
description = "create a file with this text, overwriting anything that was there before.";
|
||||||
|
};
|
||||||
|
copyFrom = mkOption {
|
||||||
|
type = types.coercedTo types.package toString types.str;
|
||||||
|
description = "populate the file based on the content at this provided path";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config = {
|
||||||
|
copyFrom = lib.mkIf (config.text != null) (
|
||||||
|
pkgs.writeText (path-lib.leaf path) config.text
|
||||||
|
);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
symlinkEntryFor = path: types.submodule ({ config, ... }: {
|
||||||
options = {
|
options = {
|
||||||
inherit (propagatedGenerateMod.options) acl;
|
inherit (propagatedGenerateMod.options) acl;
|
||||||
target = mkOption {
|
target = mkOption {
|
||||||
|
16
modules/fs/ensure-file
Executable file
16
modules/fs/ensure-file
Executable file
@@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env nix-shell
|
||||||
|
#!nix-shell -i bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
cpto="$1"
|
||||||
|
cpfrom="$2"
|
||||||
|
|
||||||
|
# -f flag in case the destination perms were set to 000
|
||||||
|
# --no-dereference in case the destination already exists as a symlink
|
||||||
|
# however, "no-dereference" has the edge case of copying `cpfrom` to `cpto`
|
||||||
|
# when `cpto` already exists as a symlink to `cpfom`:
|
||||||
|
# "cp: <cpto> and <cpfrom> are the same file"
|
||||||
|
# use `--remove-destination` for that
|
||||||
|
cp --no-dereference -f "$cpfrom" "$cpto" \
|
||||||
|
|| cp --no-dereference --remove-destination "$cpfrom" "$cpto"
|
@@ -46,15 +46,15 @@ let
|
|||||||
upnpServiceForPort = port: portCfg:
|
upnpServiceForPort = port: portCfg:
|
||||||
lib.mkIf portCfg.visibleTo.wan {
|
lib.mkIf portCfg.visibleTo.wan {
|
||||||
"upnp-forward-${port}" = {
|
"upnp-forward-${port}" = {
|
||||||
description = "forward port ${port} from upstream gateway to this host";
|
description = "forward port ${port} (${portCfg.description}) from upstream gateway to this host";
|
||||||
restartTriggers = [(builtins.toJSON portCfg)];
|
restartTriggers = [(builtins.toJSON portCfg)];
|
||||||
|
|
||||||
serviceConfig.Type = "oneshot";
|
serviceConfig = {
|
||||||
serviceConfig.TimeoutSec = "6min";
|
Type = "oneshot";
|
||||||
|
TimeoutSec = "6min";
|
||||||
after = [ "network.target" ];
|
Restart = "on-failure";
|
||||||
wantedBy = [ "upnp-forwards.target" ];
|
RestartSec = "3min";
|
||||||
script =
|
ExecStart =
|
||||||
let
|
let
|
||||||
portFwd = "${pkgs.sane-scripts.ip-port-forward}/bin/sane-ip-port-forward";
|
portFwd = "${pkgs.sane-scripts.ip-port-forward}/bin/sane-ip-port-forward";
|
||||||
forwards = lib.flatten [
|
forwards = lib.flatten [
|
||||||
@@ -65,6 +65,10 @@ let
|
|||||||
${portFwd} -v -d ${builtins.toString cfg.upnpLeaseDuration} \
|
${portFwd} -v -d ${builtins.toString cfg.upnpLeaseDuration} \
|
||||||
${lib.escapeShellArgs forwards}
|
${lib.escapeShellArgs forwards}
|
||||||
'';
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
after = [ "network.target" ];
|
||||||
|
wantedBy = [ "upnp-forwards.target" ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
|
@@ -231,6 +231,7 @@ in
|
|||||||
(lib.mapAttrs' (pkgName: _pkg: { name = "cacert.${pkgName}"; value = {}; }) pkgs.cacert)
|
(lib.mapAttrs' (pkgName: _pkg: { name = "cacert.${pkgName}"; value = {}; }) pkgs.cacert)
|
||||||
(lib.mapAttrs' (pkgName: _pkg: { name = "gnome.${pkgName}"; value = {}; }) pkgs.gnome)
|
(lib.mapAttrs' (pkgName: _pkg: { name = "gnome.${pkgName}"; value = {}; }) pkgs.gnome)
|
||||||
(lib.mapAttrs' (pkgName: _pkg: { name = "libsForQt5.${pkgName}"; value = {}; }) pkgs.libsForQt5)
|
(lib.mapAttrs' (pkgName: _pkg: { name = "libsForQt5.${pkgName}"; value = {}; }) pkgs.libsForQt5)
|
||||||
|
(lib.mapAttrs' (pkgName: _pkg: { name = "mate.${pkgName}"; value = {}; }) pkgs.mate)
|
||||||
(lib.mapAttrs' (pkgName: _pkg: { name = "plasma5Packages.${pkgName}"; value = {}; }) pkgs.plasma5Packages)
|
(lib.mapAttrs' (pkgName: _pkg: { name = "plasma5Packages.${pkgName}"; value = {}; }) pkgs.plasma5Packages)
|
||||||
(lib.mapAttrs' (pkgName: _pkg: { name = "python3Packages.${pkgName}"; value = {}; }) pkgs.python3Packages)
|
(lib.mapAttrs' (pkgName: _pkg: { name = "python3Packages.${pkgName}"; value = {}; }) pkgs.python3Packages)
|
||||||
(lib.mapAttrs' (pkgName: _pkg: { name = "sane-scripts.${pkgName}"; value = {}; }) pkgs.sane-scripts)
|
(lib.mapAttrs' (pkgName: _pkg: { name = "sane-scripts.${pkgName}"; value = {}; }) pkgs.sane-scripts)
|
||||||
|
@@ -2,6 +2,8 @@
|
|||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./dyn-dns.nix
|
./dyn-dns.nix
|
||||||
|
./eg25-control.nix
|
||||||
|
./eg25-manager.nix
|
||||||
./kiwix-serve.nix
|
./kiwix-serve.nix
|
||||||
./mautrix-signal.nix
|
./mautrix-signal.nix
|
||||||
./nixserve.nix
|
./nixserve.nix
|
||||||
|
27
modules/services/eg25-control.nix
Normal file
27
modules/services/eg25-control.nix
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.sane.services.eg25-control;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.sane.services.eg25-control = with lib; {
|
||||||
|
enable = mkEnableOption "Quectel EG25 modem configuration scripts. alternative to eg25-manager";
|
||||||
|
package = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = pkgs.eg25-control;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
systemd.services.eg25-control = {
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
ExecStart = "${cfg.package}/bin/eg25-control --power-on --enable-gps --dump-debug-info --verbose";
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = "60s";
|
||||||
|
};
|
||||||
|
after = [ "ModemManager.service" ];
|
||||||
|
wants = [ "ModemManager.service" ];
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
69
modules/services/eg25-manager.nix
Normal file
69
modules/services/eg25-manager.nix
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
# eg25-manager: <https://gitlab.com/mobian1/eg25-manager>
|
||||||
|
# - used by sxmo, in <configs/default_hooks/sxmo_hook_restart_modem_daemons.sh>
|
||||||
|
# - requires modemmanager (ModemManager.service)
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.sane.services.eg25-manager;
|
||||||
|
eg25-config-toml = pkgs.writeText "eg25-manager-config.toml" ''
|
||||||
|
# config here is applied *on top of* the per-device configs shipped by eg25-manager.
|
||||||
|
# these values take precedence, but there's no need to redefine things if we don't want them changed
|
||||||
|
[at]
|
||||||
|
uart = "/dev/ttyUSB2"
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.sane.services.eg25-manager = with lib; {
|
||||||
|
enable = mkEnableOption "Quectel EG25 modem manager service";
|
||||||
|
package = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = pkgs.eg25-manager;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
# eg25-manager package ships udev rules *and* a systemd service.
|
||||||
|
# for that reason, i think it needs to be on the system path for the systemd service to be enabled.
|
||||||
|
services.udev.packages = [ cfg.package ];
|
||||||
|
|
||||||
|
# but actually, let's define our own systemd service so that we can control config
|
||||||
|
systemd.services.eg25-manager = {
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
ExecStart = "${cfg.package}/bin/eg25-manager --config ${eg25-config-toml}";
|
||||||
|
ExecStartPre = pkgs.writeShellScript "unload-modem-power" ''
|
||||||
|
# see issue: <https://gitlab.com/mobian1/eg25-manager/-/issues/38>
|
||||||
|
${pkgs.kmod}/bin/modprobe -r modem_power && echo "WARNING: kernel configured with CONFIG_MODEM_POWER=y, may be incompatible with eg25-manager" || true
|
||||||
|
'';
|
||||||
|
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = "60s"; # can make this more frequent once stable?
|
||||||
|
|
||||||
|
# sandboxing (taken from the service file shipped by eg25-manager):
|
||||||
|
# TODO: this is too strict and breaks access to e.g. /dev/ttyUSB2!
|
||||||
|
# ProtectControlGroups = true;
|
||||||
|
# ProtectHome = true;
|
||||||
|
# ProtectSystem = "strict";
|
||||||
|
# RestrictSUIDSGID = true;
|
||||||
|
# PrivateTmp = true;
|
||||||
|
# MemoryDenyWriteExecute = true;
|
||||||
|
# PrivateMounts = true;
|
||||||
|
# NoNewPrivileges = true;
|
||||||
|
# CapabilityBoundingSet = [ "" ];
|
||||||
|
# LockPersonality = true;
|
||||||
|
};
|
||||||
|
before = [ "ModemManager.service" ];
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
# systemd.packages = [ pkgs.eg25-manager ];
|
||||||
|
# systemd.services.eg25-manager.wantedBy = [ "multi-user.target" ];
|
||||||
|
# systemd.services.prepare-eg25-manager = {
|
||||||
|
# description = "unload megi's modem_power module to provide gpio access to eg25-manager";
|
||||||
|
# serviceConfig.Type = "oneshot";
|
||||||
|
# wantedBy = [ "eg25-manager.service" ];
|
||||||
|
# before = [ "eg25-manager.service" ];
|
||||||
|
# script = ''
|
||||||
|
# ${pkgs.kmod}/bin/modprobe -r modem_power && echo "WARNING: kernel configured with CONFIG_MODEM_POWER=y, may be incompatible with eg25-manager" || true
|
||||||
|
# '';
|
||||||
|
# };
|
||||||
|
};
|
||||||
|
}
|
@@ -19,6 +19,19 @@ let
|
|||||||
// (if title != null then { name = title; } else {})
|
// (if title != null then { name = title; } else {})
|
||||||
);
|
);
|
||||||
in [
|
in [
|
||||||
|
# (fetchpatch' {
|
||||||
|
# # disabled, at least until the PR is updated to use `pkg-config` instead of `pkgconfig`.
|
||||||
|
# # the latter is an alias, which breaks nix-index
|
||||||
|
# title = "phog: init at 0.1.3";
|
||||||
|
# prUrl = "https://github.com/NixOS/nixpkgs/pull/251249";
|
||||||
|
# hash = "sha256-e38Z7sO7xDQHzE9UOfbptc6vJuONE5eP9JFp2Nzx53E=";
|
||||||
|
# })
|
||||||
|
|
||||||
|
(fetchpatch' {
|
||||||
|
title = "nixos/update-users-groups: fix cross compilation";
|
||||||
|
prUrl = "https://github.com/NixOS/nixpkgs/pull/251850";
|
||||||
|
hash = "sha256-uqx9sJ1zkwys9Ur35iXY3gZKVb52wlnBGkhBB5sc6WQ=";
|
||||||
|
})
|
||||||
|
|
||||||
# (fetchpatch' {
|
# (fetchpatch' {
|
||||||
# # TODO: check back in on this around 2023-10-01
|
# # TODO: check back in on this around 2023-10-01
|
||||||
@@ -144,12 +157,52 @@ in [
|
|||||||
# hash = "sha256-MNG8C0OgdPnFQ8SF2loiEhXJuP2z4n9pkXr8Zh4X7QU=";
|
# hash = "sha256-MNG8C0OgdPnFQ8SF2loiEhXJuP2z4n9pkXr8Zh4X7QU=";
|
||||||
# })
|
# })
|
||||||
|
|
||||||
|
# 2023-08-06: conky wayland + cross compilation patches.
|
||||||
|
# nix path-info shows clean
|
||||||
|
# branch is wip-conky-cross2 on servo
|
||||||
|
# factoring out those feature abstractions was possibly overkill.
|
||||||
|
# the manual wayland-scanner patching is unfortunate, but within
|
||||||
|
# acceptable norms of the existing package.
|
||||||
(fetchpatch' {
|
(fetchpatch' {
|
||||||
title = "conky: support wayland";
|
title = "conky: factor out an abstraction for feature flags";
|
||||||
# saneCommit = "82978099c3a0d5fb4925351da1b0e2598503dc6c";
|
saneCommit = "3ddf13038d6df90ad0db36a41d55e4077818a3e9";
|
||||||
# hash = "sha256-lnDGEDhmeOIXfFnizEIVUiUzI7nMvpoCERbdjhR+Bto=";
|
hash = "sha256-CjLzndFEH1Ng9CqKX8gxCJ6n/wFv5U/sHnQE0FMYILc=";
|
||||||
saneCommit = "3ad928e20b498444e3a106b182e09317cea9a11f";
|
})
|
||||||
hash = "sha256-lvIASvQWVFbjHsQwO2EhEBUTSq1UkHvriaZZ2iS0ulU=";
|
(fetchpatch' {
|
||||||
|
title = "conky: simplify the features even more";
|
||||||
|
saneCommit = "1c4aa404743f1ae7d5b95f18a96c4057ca251a96";
|
||||||
|
hash = "sha256-0zhiw9siIkFgFW4sow+X88NBEa3ggCe1t1HJ5xFH4ac=";
|
||||||
|
})
|
||||||
|
(fetchpatch' {
|
||||||
|
title = "conky: support cross compilation";
|
||||||
|
saneCommit = "01e607e11c7e5bbbfe6ad132fb72394ec29dab0a";
|
||||||
|
hash = "sha256-Bm/XFLvE7gEyLPlBWNSAcU3qwwqKLIRdpoe0/1aHUho=";
|
||||||
|
})
|
||||||
|
(fetchpatch' {
|
||||||
|
title = "conky: add wayland support";
|
||||||
|
saneCommit = "84c51f67e02ebc7f118fd3171bd10f1978d4f1e6";
|
||||||
|
hash = "sha256-gRYbkzCe3q1R7X/FeOcz/haURQkeAfmED1/ZQlCCdWE=";
|
||||||
|
})
|
||||||
|
(fetchpatch' {
|
||||||
|
title = "conky: remove no-op sed patch";
|
||||||
|
saneCommit = "e8b19984a2858ca24b7e8f5acd20be8b7dfe1af0";
|
||||||
|
hash = "sha256-K3mG1kcyB7sQZ7ZRCdlinNsV6mCcl3eIUI2ldSmcbJE=";
|
||||||
|
})
|
||||||
|
|
||||||
|
# (fetchpatch' {
|
||||||
|
# title = "gtk3: compile schemas even when cross compiling";
|
||||||
|
# saneCommit = "5ee69670071f583bdffe2718dc46763fa1698f92";
|
||||||
|
# hash = "sha256-ZX3lY63qUW2XuwCoxffbLYoFxckDImKy+S8mqlYJcvk=";
|
||||||
|
# })
|
||||||
|
# (fetchpatch' {
|
||||||
|
# title = "gtk4: compile schemas even when cross compiling";
|
||||||
|
# saneCommit = "7a1c5e3a5d1ff82c8afa659c7f903d5309d5de6a";
|
||||||
|
# hash = "sha256-Tz8NBcIqGE9rCqbOrixgbvApYDEAHWCg4lZbklL/xXc=";
|
||||||
|
# })
|
||||||
|
(fetchpatch' {
|
||||||
|
title = "gtk{3,4}: compile schemas even when cross compiling";
|
||||||
|
prUrl = "https://github.com/NixOS/nixpkgs/pull/247844";
|
||||||
|
hash = "sha256-1CsjLgMvX0Lx500UDzal5HZi78hb7zBcb+AlNPF6NvA=";
|
||||||
})
|
})
|
||||||
|
|
||||||
# (fetchpatch' {
|
# (fetchpatch' {
|
||||||
@@ -171,16 +224,7 @@ in [
|
|||||||
# includes hare-json and hare-ev as pre-reqs
|
# includes hare-json and hare-ev as pre-reqs
|
||||||
title = "bonsai: init at 1.0.0";
|
title = "bonsai: init at 1.0.0";
|
||||||
prUrl = "https://github.com/NixOS/nixpkgs/pull/233892";
|
prUrl = "https://github.com/NixOS/nixpkgs/pull/233892";
|
||||||
hash = "sha256-f7tdHz0lFsSJO8C0saMuG8e7VzSx8XDy/UXjbqWHP9M=";
|
hash = "sha256-HaTr7GBCfK1I2e7K4k2dUGZ6hZf4PwtEFobLaSz262M=";
|
||||||
})
|
|
||||||
|
|
||||||
# make alsa-project members overridable
|
|
||||||
(fetchpatch' {
|
|
||||||
title = "alsa-project: expose the scope as a top-level package to support overrides";
|
|
||||||
prUrl = "https://github.com/NixOS/nixpkgs/pull/246656";
|
|
||||||
saneCommit = "28f76deae50cc53f5f6a5e846e04426357b8ce2e";
|
|
||||||
# hash = "sha256-dBWStotLBa4LN7JmriTzoFX3/SQr/qxGO8glv3MNyZQ=";
|
|
||||||
hash = "sha256-QvurEnupAdPVVnHYl4DC1OqJronGt31REkTJO/alr60=";
|
|
||||||
})
|
})
|
||||||
|
|
||||||
# pin to a pre-0.17.3 release
|
# pin to a pre-0.17.3 release
|
||||||
@@ -200,13 +244,12 @@ in [
|
|||||||
hash = "sha256-38sND/UNRj5WAYYKpzdrRBIOK4UAT14RzbIv49KmNNw=";
|
hash = "sha256-38sND/UNRj5WAYYKpzdrRBIOK4UAT14RzbIv49KmNNw=";
|
||||||
})
|
})
|
||||||
|
|
||||||
(fetchpatch' {
|
# (fetchpatch' {
|
||||||
# TODO: send this upstream!
|
# title = "mepo: 1.1 -> 1.1.2";
|
||||||
title = "mepo: 1.1 -> 1.1.2";
|
# prUrl = "https://github.com/NixOS/nixpkgs/pull/247866";
|
||||||
saneCommit = "eee68d7146a6cd985481cdd8bca52ffb204de423";
|
# saneCommit = "eee68d7146a6cd985481cdd8bca52ffb204de423";
|
||||||
hash = "sha256-uNerTwyFzivTU+o9bEKmNMFceOmy2AKONfKJWI5qkzo=";
|
# hash = "sha256-uNerTwyFzivTU+o9bEKmNMFceOmy2AKONfKJWI5qkzo=";
|
||||||
})
|
# })
|
||||||
|
|
||||||
|
|
||||||
(fetchpatch' {
|
(fetchpatch' {
|
||||||
title = "gthumb: make the webservices feature be optional";
|
title = "gthumb: make the webservices feature be optional";
|
||||||
@@ -221,23 +264,6 @@ in [
|
|||||||
hash = "sha256-rD0es4uUbaLMrI9ZB2HzPmRLyu/ixNBLAFyDJtFHNko=";
|
hash = "sha256-rD0es4uUbaLMrI9ZB2HzPmRLyu/ixNBLAFyDJtFHNko=";
|
||||||
})
|
})
|
||||||
|
|
||||||
(fetchpatch' {
|
|
||||||
title = "p11-kit: build with meson";
|
|
||||||
prUrl = "https://github.com/NixOS/nixpkgs/pull/244633";
|
|
||||||
hash = "sha256-+z6hosSyt6ynLpUKS0TsHRoLOS8ck/SK9Y7W2zVUnCQ=";
|
|
||||||
})
|
|
||||||
(fetchpatch' {
|
|
||||||
title = "p11-kit: use mesonEmulatorHook for cross compilation";
|
|
||||||
prUrl = "https://github.com/NixOS/nixpkgs/pull/245124";
|
|
||||||
hash = "sha256-8NqqLBbjt1fLj4ZYhat7wPqQSv/aez9IwgSK2b4CfW8=";
|
|
||||||
})
|
|
||||||
|
|
||||||
(fetchpatch' {
|
|
||||||
title = "python310Packages.gssapi: support cross compilation";
|
|
||||||
prUrl = "https://github.com/NixOS/nixpkgs/pull/247048";
|
|
||||||
saneCommit = "4766ae46f863734fbe96dc4e537870b6b3894cf4";
|
|
||||||
hash = "sha256-7JZqAlcNFP6orJZCEqe5eodVxTUHeSLGyniRvw/+PuQ=";
|
|
||||||
})
|
|
||||||
# (fetchpatch' {
|
# (fetchpatch' {
|
||||||
# title = "perlPackages.FileBaseDir: 0.08 -> 0.09";
|
# title = "perlPackages.FileBaseDir: 0.08 -> 0.09";
|
||||||
# saneCommit = "acc990b04bbe8c99587eadccc65f100c326ec204";
|
# saneCommit = "acc990b04bbe8c99587eadccc65f100c326ec204";
|
||||||
@@ -249,10 +275,13 @@ in [
|
|||||||
# hash = "sha256-fAZpduh3JZeFixJ4yX0wkh/GRp0gYKsTT+XkNdpK7CU=";
|
# hash = "sha256-fAZpduh3JZeFixJ4yX0wkh/GRp0gYKsTT+XkNdpK7CU=";
|
||||||
# })
|
# })
|
||||||
(fetchpatch' {
|
(fetchpatch' {
|
||||||
|
# TODO: split this apart for easier reviewing:
|
||||||
|
# - perlPackages.TestFile 1.443 -> 1.993
|
||||||
|
# - perlPackages.FileBaseDir 0.08 -> 0.09
|
||||||
title = "xdg-utils: enable cross compilation";
|
title = "xdg-utils: enable cross compilation";
|
||||||
prUrl = "https://github.com/NixOS/nixpkgs/pull/246954";
|
prUrl = "https://github.com/NixOS/nixpkgs/pull/246954";
|
||||||
saneCommit = "b7aa5e0c1ec06723cf1594de192703a65be21497";
|
saneCommit = "b7aa5e0c1ec06723cf1594de192703a65be21497";
|
||||||
hash = "sha256-jA84RKt4nOEZsBlACaqa0GeBiDdFOBYARgAq4NgTqtY=";
|
hash = "sha256-5iYzyjVlye7mhwhlZOHucVod/aPT3OrXolC9jAnB544=";
|
||||||
})
|
})
|
||||||
# (fetchpatch' {
|
# (fetchpatch' {
|
||||||
# # N.B.: duplicates outstanding, merged PR: <https://github.com/NixOS/nixpkgs/pull/246362>
|
# # N.B.: duplicates outstanding, merged PR: <https://github.com/NixOS/nixpkgs/pull/246362>
|
||||||
@@ -261,69 +290,16 @@ in [
|
|||||||
# saneCommit = "4dc30718fe01e9dbed4ffc2ff375148da218e86b";
|
# saneCommit = "4dc30718fe01e9dbed4ffc2ff375148da218e86b";
|
||||||
# hash = "sha256-Nb2LphSyv8Dayqfwqfua0eKtNzsnaf7PC/KYUhIvnT8=";
|
# hash = "sha256-Nb2LphSyv8Dayqfwqfua0eKtNzsnaf7PC/KYUhIvnT8=";
|
||||||
# })
|
# })
|
||||||
(fetchpatch' {
|
|
||||||
title = "gupnp: fix cross compilation";
|
|
||||||
prUrl = "https://github.com/NixOS/nixpkgs/pull/246931";
|
|
||||||
saneCommit = "3af24c9e517689d048bb62511c6e8acf9bc55684";
|
|
||||||
# hash = "sha256-6yl6I/zOcUe0TDKEi/vjEzyU4OWoGi0PMht3VOKWmQo=";
|
|
||||||
hash = "sha256-NYA72+liKZXnUoAGor3MR62YmZNsNPJ3SEfWGhpeiY4=";
|
|
||||||
})
|
|
||||||
(fetchpatch' {
|
(fetchpatch' {
|
||||||
title = "blueman: support cross compilation";
|
title = "blueman: support cross compilation";
|
||||||
saneCommit = "e070195bdf213dffb0164574397b6a7417f81c9e";
|
saneCommit = "e070195bdf213dffb0164574397b6a7417f81c9e";
|
||||||
hash = "sha256-6JnIJCVBbV4tmFinX7Qv2wO2AThrgxrnyb9T4Ov6p5w=";
|
hash = "sha256-6JnIJCVBbV4tmFinX7Qv2wO2AThrgxrnyb9T4Ov6p5w=";
|
||||||
})
|
})
|
||||||
# (fetchpatch' {
|
|
||||||
# # N.B.: duplicates merged PR: <https://github.com/NixOS/nixpkgs/pull/246369>
|
|
||||||
# title = "tracker: support cross compilation";
|
|
||||||
# saneCommit = "bea390fd0c4fda96db5b1fad06ee071a10561305";
|
|
||||||
# hash = "sha256-Y2tVoTvSIIT9ufghqqsXgmqWq9daH+WKj4JHZgWbWwE=";
|
|
||||||
# })
|
|
||||||
(fetchpatch' {
|
(fetchpatch' {
|
||||||
title = "tracker-miners: support cross compilation";
|
title = "tracker-miners: support cross compilation";
|
||||||
saneCommit = "24b062309ea8baa2d8303c0610c9ec7b8c399e8b";
|
saneCommit = "24b062309ea8baa2d8303c0610c9ec7b8c399e8b";
|
||||||
hash = "sha256-Jj+1z2DeCEY+DqI1J4vYjYJwDDMRcA93CqpZSXzG0wE=";
|
hash = "sha256-Jj+1z2DeCEY+DqI1J4vYjYJwDDMRcA93CqpZSXzG0wE=";
|
||||||
})
|
})
|
||||||
(fetchpatch' {
|
|
||||||
# alternate fix for upower; Arturrin
|
|
||||||
title = "upower: Fix cross";
|
|
||||||
prUrl = "https://github.com/NixOS/nixpkgs/pull/247031";
|
|
||||||
hash = "sha256-Skn1dO+SDXbrWYWn8QpSBzYaTis/KUXLEY+pJxO9pWM=";
|
|
||||||
})
|
|
||||||
# (fetchpatch' {
|
|
||||||
# # PR also includes the nativeBuildInputs fix
|
|
||||||
# title = "upower: fix cross compilation";
|
|
||||||
# prUrl = "https://github.com/NixOS/nixpkgs/pull/246945";
|
|
||||||
# saneCommit = "3ab262456acc016c8dc834df1d1f7e61a00e01e3";
|
|
||||||
# # hash = "sha256-kTFZVu9oDiYH4W4SoQQj0pNuo9hTJk6jUy+hy34HUtA=";
|
|
||||||
# hash = "sha256-PpC9YRMqg/wPfFgAPNV80mwbZWCKxNi4agxNf0yQutI=";
|
|
||||||
# })
|
|
||||||
# (fetchpatch' {
|
|
||||||
# title = "upower: don't pass unnecessary nativeBuildInputs";
|
|
||||||
# saneCommit = "e2cbfb1bc81afadc5d31c18d43e774fa9a985f98";
|
|
||||||
# hash = "sha256-7Q9Fjp7xrw3e887inc5cc01OvuOhThnVYduSLNtv2d0=";
|
|
||||||
# })
|
|
||||||
(fetchpatch' {
|
|
||||||
title = "iio-sensor-proxy: support cross compilation";
|
|
||||||
prUrl = "https://github.com/NixOS/nixpkgs/pull/246947";
|
|
||||||
saneCommit = "dc1c3341fef6c64d5fbc983670819cf7932f5be1";
|
|
||||||
# hash = "sha256-lSVGjNepRLMfLgaAG3zv/BfoEhJg8yX7EqaCgu8/b8I=";
|
|
||||||
hash = "sha256-0rO+qkWgdrZsuHnoRdQ0SqEEW+PYcJaLixrOgJSOssk=";
|
|
||||||
})
|
|
||||||
(fetchpatch' {
|
|
||||||
title = "mpvScripts.mpris: support cross compilation";
|
|
||||||
prUrl = "https://github.com/NixOS/nixpkgs/pull/247087";
|
|
||||||
saneCommit = "f7cd92e2afa26852ccf53f8ca59c13d82bf7bf64";
|
|
||||||
# hash = "sha256-MB3qloOW4pXZmbCIVsUKP2DnPoePmBf+qRc2x/o+nDw=";
|
|
||||||
hash = "sha256-uMbnfO0WY2/AFpvvnHQGKVSTE2rPrm3SCef4f04Bt78=";
|
|
||||||
})
|
|
||||||
(fetchpatch' {
|
|
||||||
title = "wvkbd: support cross compilation";
|
|
||||||
prUrl = "https://github.com/NixOS/nixpkgs/pull/247083";
|
|
||||||
saneCommit = "34379f5770662b483ab0cbe252cf23dd663d84dc";
|
|
||||||
# hash = "sha256-Duim5hPBtfGePBte29ZUtojyRAts9lQlbleUsTJNkwI=";
|
|
||||||
hash = "sha256-aC7zEM4pV4YXh5X0m2nYAkH0vLgVTNq8bgIP8CLZy4I=";
|
|
||||||
})
|
|
||||||
(fetchpatch' {
|
(fetchpatch' {
|
||||||
title = "clapper: support cross compilation";
|
title = "clapper: support cross compilation";
|
||||||
saneCommit = "8a171b49aca406f8220f016e56964b3fae53a3df";
|
saneCommit = "8a171b49aca406f8220f016e56964b3fae53a3df";
|
||||||
@@ -362,24 +338,33 @@ in [
|
|||||||
hash = "sha256-cGhJSby0K+e1hKPdPZjLFRKvwjGaTbq/kb6Fxj2v8g8=";
|
hash = "sha256-cGhJSby0K+e1hKPdPZjLFRKvwjGaTbq/kb6Fxj2v8g8=";
|
||||||
})
|
})
|
||||||
(fetchpatch' {
|
(fetchpatch' {
|
||||||
|
# TODO: send for review once thie libgnt patch above is merged
|
||||||
title = "pidgin: support cross compilation";
|
title = "pidgin: support cross compilation";
|
||||||
saneCommit = "caacbcc54e217f5ee9281422777a7f712765f71a";
|
saneCommit = "caacbcc54e217f5ee9281422777a7f712765f71a";
|
||||||
hash = "sha256-PDCp4GOm6hWcRob4kz7qXZfxAF6YbYrESx9idoS3e/s=";
|
hash = "sha256-PDCp4GOm6hWcRob4kz7qXZfxAF6YbYrESx9idoS3e/s=";
|
||||||
})
|
})
|
||||||
|
|
||||||
(fetchpatch' {
|
|
||||||
title = "dtrx: 8.5.1 -> 8.5.3";
|
|
||||||
prUrl = "https://github.com/NixOS/nixpkgs/pull/246282";
|
|
||||||
saneCommit = "eba9bbc251db942ae27f87824cae643b5f3198c2";
|
|
||||||
# hash = "sha256-wgpjUXQ/ZnRY5AJ9xOL2BToA7hDaokDiMmPkMt0Y5go=";
|
|
||||||
hash = "sha256-awUDlibmxcJcdMZeBXcWR1U+P/GCxCH/lalhwZ5Er90=";
|
|
||||||
})
|
|
||||||
# (fetchpatch' {
|
# (fetchpatch' {
|
||||||
# title = "dtrx: don't double-wrap the binary";
|
# # doesn't cleanly apply. TODO: see if this cross compiles now, thanks to <https://github.com/NixOS/nixpkgs/pull/234615>
|
||||||
# saneCommit = "97a9d12b6c31a58e9067eae7cdcd3f53055c124c";
|
# title = "nixos/dconf: support cross compilation";
|
||||||
# hash = "sha256-g+p96OrBOQAwwH7nwHBuM/KGeIrnBzh9u9lL0M0sYWo=";
|
# prUrl = "https://github.com/NixOS/nixpkgs/pull/249093";
|
||||||
|
# saneCommit = "08f7cdebc58eeaa62cb349dab57db3be7a0c073d";
|
||||||
|
# hash = "sha256-gqHUGeTQnr0f99gqEdd+VANLkWO+joLxz5I0RSarznE=";
|
||||||
# })
|
# })
|
||||||
|
|
||||||
|
(fetchpatch' {
|
||||||
|
title = "playerctl: support cross compilation";
|
||||||
|
prUrl = "https://github.com/NixOS/nixpkgs/pull/249512";
|
||||||
|
saneCommit = "67df31a8984ab3067af5b65446d2808b0aedadc6";
|
||||||
|
hash = "sha256-qY0bjMoFneC5VJ467TeiuOycLYNaVO7Xo/0fCauDZAM=";
|
||||||
|
})
|
||||||
|
(fetchpatch' {
|
||||||
|
title = "libgweather: enable introspection on cross builds";
|
||||||
|
prUrl = "https://github.com/NixOS/nixpkgs/pull/251956";
|
||||||
|
saneCommit = "7a2d0a90cc558ea71dfc78356e61b0675b995634";
|
||||||
|
hash = "sha256-tjO19dXVUrD+V+YpD7z3iWSgNyOirG70HuQ+c+0fZYA=";
|
||||||
|
})
|
||||||
|
|
||||||
# (fetchpatch' {
|
# (fetchpatch' {
|
||||||
# # N.B.: compiles, but runtime error on launch suggestive of some module not being shipped
|
# # N.B.: compiles, but runtime error on launch suggestive of some module not being shipped
|
||||||
# title = "matrix-appservice-irc: 0.38.0 -> 1.0.0";
|
# title = "matrix-appservice-irc: 0.38.0 -> 1.0.0";
|
||||||
|
1083
overlays/cross.nix
1083
overlays/cross.nix
File diff suppressed because it is too large
Load Diff
@@ -63,6 +63,19 @@ in {
|
|||||||
"pyarrow/tests/test_flight.py"
|
"pyarrow/tests/test_flight.py"
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
# 2023/08/09: unclear why it fails; probably can remove after next nixpkgs update
|
||||||
|
pillow = py-prev.pillow.overridePythonAttrs (_upstream: {
|
||||||
|
format = "setuptools";
|
||||||
|
});
|
||||||
|
|
||||||
|
seaborn = py-prev.seaborn.overridePythonAttrs (upstream: {
|
||||||
|
# 2023/08/09
|
||||||
|
disabledTestPaths = (upstream.disabledTestPaths or []) ++ [
|
||||||
|
"tests/test_categorical.py"
|
||||||
|
"tests/test_core.py"
|
||||||
|
];
|
||||||
|
});
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@@ -1,27 +1,45 @@
|
|||||||
# personal preferences
|
# personal preferences
|
||||||
# prefer to encode these in `sane.programs`
|
# prefer to encode these in `sane.programs`
|
||||||
# resort to this method for e.g. system dependencies, or things which are referenced from too many places.
|
# resort to this method for e.g. system dependencies, or things which are referenced from too many places.
|
||||||
(next: prev: {
|
(self: super: with self; {
|
||||||
pipewire = prev.pipewire.override {
|
gnome = super.gnome.overrideScope' (gself: gsuper: with gself; {
|
||||||
|
evolution-data-server = gsuper.evolution-data-server.override {
|
||||||
|
# OAuth depends on webkitgtk_4_1: old, forces an annoying recompilation
|
||||||
|
enableOAuth2 = false;
|
||||||
|
gnome-online-accounts = gnome-online-accounts.override {
|
||||||
|
# avoid webkitgtk_4_1 build
|
||||||
|
enableBackend = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
# gnome-shell = gsuper.gnome-shell.override {
|
||||||
|
# evolution-data-server-gtk4 = evolution-data-server-gtk4.override {
|
||||||
|
# # avoid webkitgtk_6_0 build. lol.
|
||||||
|
# withGtk4 = false;
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
});
|
||||||
|
|
||||||
|
phog = super.phog.override {
|
||||||
|
# disable squeekboard because it takes 20 minutes to compile when emulated
|
||||||
|
squeekboard = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
pipewire = super.pipewire.override {
|
||||||
# avoid a dep on python3.10-PyQt5, which has mixed qt5 versions.
|
# avoid a dep on python3.10-PyQt5, which has mixed qt5 versions.
|
||||||
# this means we lose firewire support (oh well..?)
|
# this means we lose firewire support (oh well..?)
|
||||||
ffadoSupport = false;
|
ffadoSupport = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
pythonPackagesExtensions = prev.pythonPackagesExtensions ++ [
|
pythonPackagesExtensions = super.pythonPackagesExtensions ++ [
|
||||||
(pySelf: pySuper: {
|
(pySelf: pySuper: {
|
||||||
# TODO(2023/08/02): cryptography (a dependency of komikku -> keyring -> secretstorage -> cryptography) doesn't cross compile
|
|
||||||
# so disable it. can be re-enabled in next staging -> master merge.
|
|
||||||
# see:
|
|
||||||
# - <https://github.com/NixOS/nixpkgs/pull/245287/files>
|
|
||||||
# - <https://github.com/NixOS/nixpkgs/pull/244135>
|
|
||||||
keyring = (pySuper.keyring.override {
|
keyring = (pySuper.keyring.override {
|
||||||
secretstorage = null;
|
# jaraco-classes doesn't cross compile, but it looks like `keyring`
|
||||||
jeepney = null;
|
# has some _temporary_ fallback logic for when jaraco-classes isn't
|
||||||
|
# installed (i.e. may break in future).
|
||||||
|
jaraco-classes = null;
|
||||||
}).overrideAttrs (upstream: {
|
}).overrideAttrs (upstream: {
|
||||||
postPatch = (upstream.postPatch or "") + ''
|
postPatch = (upstream.postPatch or "") + ''
|
||||||
sed -i /SecretStorage/d setup.cfg
|
sed -i /jaraco.classes/d setup.cfg
|
||||||
sed -i /jeepney/d setup.cfg
|
|
||||||
'';
|
'';
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@@ -18,6 +18,21 @@ stdenv.mkDerivation rec {
|
|||||||
hash = "sha256-jOtFUpl2/Aa7f8JMZf6g63ayFOi+Ci+i7Ac63k63znc=";
|
hash = "sha256-jOtFUpl2/Aa7f8JMZf6g63ayFOi+Ci+i7Ac63k63znc=";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
postPatch = ''
|
||||||
|
substituteInPlace Makefile \
|
||||||
|
--replace 'hare build' 'hare build $(HARE_TARGET_FLAGS)'
|
||||||
|
'';
|
||||||
|
|
||||||
|
env.HARE_TARGET_FLAGS =
|
||||||
|
if stdenv.hostPlatform.isAarch64 then
|
||||||
|
"-t aarch64"
|
||||||
|
else if stdenv.hostPlatform.isRiscV64 then
|
||||||
|
"-t riscv64"
|
||||||
|
else if stdenv.hostPlatform.isx86_64 then
|
||||||
|
"-t x86_64"
|
||||||
|
else
|
||||||
|
"";
|
||||||
|
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
hare
|
hare
|
||||||
hare-ev
|
hare-ev
|
||||||
@@ -31,7 +46,7 @@ stdenv.mkDerivation rec {
|
|||||||
# export ARFLAGS="-csr"
|
# export ARFLAGS="-csr"
|
||||||
'';
|
'';
|
||||||
|
|
||||||
installFlags = [ "PREFIX=" "DESTDIR=$(out)" ];
|
installFlags = [ "PREFIX=$(out)" ];
|
||||||
|
|
||||||
passthru.updateScript = gitUpdater {
|
passthru.updateScript = gitUpdater {
|
||||||
rev-prefix = "v";
|
rev-prefix = "v";
|
||||||
|
6
pkgs/additional/eg25-control/default.nix
Normal file
6
pkgs/additional/eg25-control/default.nix
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{ static-nix-shell }:
|
||||||
|
static-nix-shell.mkPython3Bin {
|
||||||
|
pname = "eg25-control";
|
||||||
|
src = ./.;
|
||||||
|
pkgs = [ "curl" "modemmanager" ];
|
||||||
|
}
|
429
pkgs/additional/eg25-control/eg25-control
Executable file
429
pkgs/additional/eg25-control/eg25-control
Executable file
@@ -0,0 +1,429 @@
|
|||||||
|
#!/usr/bin/env nix-shell
|
||||||
|
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ])" -p curl -p modemmanager
|
||||||
|
|
||||||
|
# this script should run after ModemManager.service is started.
|
||||||
|
# typical invocation is `eg25_gps_init.py --enable-power --enable-gps`.
|
||||||
|
# after running, the user may `cat /dev/ttyUSB1` to view NMEA-encoded GPS information.
|
||||||
|
# the script attempts to be idempotent, such that it may be run multiple times per boot.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
# the script may also configure other parts of the modem as `eg25-manager` does.
|
||||||
|
# these options are less tested: see `--help` for more.
|
||||||
|
#
|
||||||
|
# PREREQUISITES/DEPENDENCIES:
|
||||||
|
# this script expects to run on megi's kernel, with `CONFIG_MODEM_POWER=y`.
|
||||||
|
# ModemManager must be launched with the `--debug` flag, so that `mmcli --command=...` works.
|
||||||
|
#
|
||||||
|
# ModemManager, and by extension this script, REQUIRES A SIM CARD IN YOUR PHONE.
|
||||||
|
# the sim doesn't need to be "activated". you can buy a $1 SIM and never purchase
|
||||||
|
# service and that works; it's just needed for ModemManager to boot the modem.
|
||||||
|
# this isn't a fundamental requirement; if one did everything via serial instead of
|
||||||
|
# ModemManager the SIM would not be necessary for GPS.
|
||||||
|
#
|
||||||
|
# EXPECTATIONS/TIPS:
|
||||||
|
# - with the right environment, you may get a GPS fix in < 30s.
|
||||||
|
# - the fix is likely to have a *lot* of jitter, like 10+ meters.
|
||||||
|
# - indoors, you shouldn't expect to *ever* get a cold-start GPS fix.
|
||||||
|
# - maybe you'll track 1 satellite if lucky: enough to receive GPS time but not for a GPS fix.
|
||||||
|
# - get a fix outdoors, then walk indoors: GPS is smart enough to maintain a spotty fix.
|
||||||
|
# - outdoors in suburbia, a fix might take 10-20 minutes.
|
||||||
|
# - i have better luck *placing my phone on the roof of my car* than holding it in the air with my hand.
|
||||||
|
# - maybe a big metal plate opposite the sky acts as a dish/antenna?
|
||||||
|
# - in Seattle, i track several GLONASS and GPS sats: about an even split.
|
||||||
|
# - the GPS sats have better SNR.
|
||||||
|
# - modem seems to not show any BeiDou or Galileo sats even if i enable them.
|
||||||
|
#
|
||||||
|
# eg25 modem/GPS docs:
|
||||||
|
# [GNSS-AP-Note]: https://wiki.pine64.org/images/0/09/Quectel_EC2x%26EG9x%26EG2x-G%26EM05_Series_GNSS_Application_Note_V1.3.pdf
|
||||||
|
#
|
||||||
|
# most acronyms are defined inline, particularly near variable/class declarations.
|
||||||
|
# glossary, for those which aren't:
|
||||||
|
#
|
||||||
|
# Global Navigation Satellite Systems (GNSS):
|
||||||
|
# - GPS (US)
|
||||||
|
# - GLONASS (RU)
|
||||||
|
# - Galileo (EU)
|
||||||
|
# - BeiDou (CN)
|
||||||
|
# ^ these are all global systems, usable outside the country that owns them
|
||||||
|
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import datetime
|
||||||
|
import logging
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
POWER_ENDPOINT = "/sys/class/modem-power/modem-power/device/powered"
|
||||||
|
# GNSS-AP-Note 1.4:
|
||||||
|
# also at xtrapath5 and xtrapath6 subdomains.
|
||||||
|
# the AGPS data here is an almanac good for 7 days.
|
||||||
|
AGPS_DATA_URI_BASE = "https://xtrapath4.izatcloud.net"
|
||||||
|
|
||||||
|
class AgpsDataVariant:
|
||||||
|
# GNSS-AP-Note 1.4:
|
||||||
|
gps_glonass = "xtra2.bin"
|
||||||
|
gps_glonass_beidou = "xtra3grc.bin"
|
||||||
|
# N.B.: not supported by all Quectel modems
|
||||||
|
# on stock Pinephone, ModemManager gives "LOC service: general failure"
|
||||||
|
gps_glonass_beidou_galileo = "xtra3grcej.bin"
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
def destructive(fn: callable = None, return_ = None):
|
||||||
|
""" decorate `fn` so that it becomes a no-op when --dry-run is active """
|
||||||
|
def wrapped(self, *args, **kwargs):
|
||||||
|
if self.dry_run:
|
||||||
|
fmt_args = ", ".join(
|
||||||
|
[repr(a) for a in args] +
|
||||||
|
[f"{k}={v}" for k,v in kwargs.items()]
|
||||||
|
)
|
||||||
|
logger.info(f"[dry run] {fn.__name__}({fmt_args})")
|
||||||
|
return return_
|
||||||
|
else:
|
||||||
|
return fn(self, *args, **kwargs)
|
||||||
|
if fn:
|
||||||
|
return wrapped
|
||||||
|
else:
|
||||||
|
return lambda fn: destructive(fn, return_=return_)
|
||||||
|
|
||||||
|
def log_scope(at_enter: str, at_exit: str):
|
||||||
|
""" decorate a function so that it logs at start and end """
|
||||||
|
def decorator(fn: callable):
|
||||||
|
def wrapped(*args, **kwargs):
|
||||||
|
logger.info(at_enter)
|
||||||
|
ret = fn(*args, **kwargs)
|
||||||
|
logger.info(at_exit)
|
||||||
|
return ret
|
||||||
|
return wrapped
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
class Executor:
|
||||||
|
def __init__(self, dry_run: bool = False):
|
||||||
|
self.dry_run = dry_run
|
||||||
|
|
||||||
|
@destructive
|
||||||
|
def write_file(self, path: str, data: bytes) -> None:
|
||||||
|
logger.debug(f"echo {data!r} > {path}")
|
||||||
|
with open(path, 'wb') as f:
|
||||||
|
f.write(data)
|
||||||
|
|
||||||
|
@destructive(return_=b'')
|
||||||
|
def exec(self, cmd: list[str], check: bool = True) -> bytes:
|
||||||
|
logger.debug(" ".join(cmd))
|
||||||
|
res = subprocess.run(cmd, capture_output=True)
|
||||||
|
logger.debug(res.stdout)
|
||||||
|
if res.stderr:
|
||||||
|
logger.warning(res.stderr)
|
||||||
|
if check:
|
||||||
|
res.check_returncode()
|
||||||
|
return res.stdout
|
||||||
|
|
||||||
|
class GNSSConfig:
|
||||||
|
# GNSS-AP-Note 2.2.7
|
||||||
|
# Supported GNSS constellations. GPS is always ON
|
||||||
|
# 0 GLONASS OFF/BeiDou OFF/Galileo OFF
|
||||||
|
# 1 GLONASS ON/BeiDou ON/Galileo ON
|
||||||
|
# 2 GLONASS ON/BeiDou ON/Galileo OFF
|
||||||
|
# 3 GLONASS ON/BeiDou OFF/Galileo ON
|
||||||
|
# 4 GLONASS ON/BeiDou OFF/Galileo OFF
|
||||||
|
# 5 GLONASS OFF/BeiDou ON/Galileo ON
|
||||||
|
# 6 GLONASS OFF/BeiDou OFF/Galileo ON
|
||||||
|
# 7 GLONASS OFF/BeiDou ON/Galileo OFF
|
||||||
|
gps = "0"
|
||||||
|
gps_glonass_beidou_galileo = "1"
|
||||||
|
gps_glonass_beidou = "2"
|
||||||
|
gps_glonass_galilego = "3"
|
||||||
|
gps_glonass = "4"
|
||||||
|
gps_beidou_galileo = "5"
|
||||||
|
gps_galileo = "6"
|
||||||
|
gps_beidou = "7"
|
||||||
|
|
||||||
|
class ODPControl:
|
||||||
|
# GNSS-AP-Note 2.2.8
|
||||||
|
# 0 Disable ODP
|
||||||
|
# 1 Low power mode
|
||||||
|
# 2 Ready mode
|
||||||
|
#
|
||||||
|
# ODP = "On-Demand Positioning"
|
||||||
|
# Low power mode:
|
||||||
|
# - low-frequency background GNSS tracking session
|
||||||
|
# - adjusts interval between 10m (when signal is good) - 60m (when signal is bad)
|
||||||
|
# Ready mode:
|
||||||
|
# - 1 Hz positioning
|
||||||
|
# - keeps GNSS ready so that when application demands position it's immediately ready
|
||||||
|
# - automatically stops positioning after 60s??
|
||||||
|
disable = "0"
|
||||||
|
lower_power_mode = "1"
|
||||||
|
ready_mode = "2"
|
||||||
|
|
||||||
|
class DPOEnable:
|
||||||
|
# GNSS-AP-Note 2.2.9
|
||||||
|
# 0 Disable DPO
|
||||||
|
# 1 Enable the DPO with dynamic duty cycle
|
||||||
|
#
|
||||||
|
# DPO = "Dynamic Power Optimization"
|
||||||
|
# automatically shuts off radio under certain conditions
|
||||||
|
# more info: <https://sixfab.com/wp-content/uploads/2018/09/Quectel_UC20_GNSS_AT_Commands_Manual_V1.1.pdf> 1.4.1
|
||||||
|
disable = "0"
|
||||||
|
enable = "1"
|
||||||
|
|
||||||
|
class GPSNMEAType:
|
||||||
|
# GNSS-AP-Note 2.2.3
|
||||||
|
# Output type of GPS NMEA sentences in ORed.
|
||||||
|
disable = 0
|
||||||
|
gpgga = 1
|
||||||
|
gprmc = 2
|
||||||
|
gpgsv = 4
|
||||||
|
gpgsa = 8
|
||||||
|
gpvtg = 16
|
||||||
|
all = 31
|
||||||
|
|
||||||
|
class GlonassNmeaType:
|
||||||
|
# GNSS-AP-Note 2.2.4
|
||||||
|
# Configure output type of GLONASS NMEA sentences in ORed
|
||||||
|
disable = 0
|
||||||
|
glgsv = 1
|
||||||
|
gngsa = 2
|
||||||
|
gngns = 4
|
||||||
|
all = 7
|
||||||
|
|
||||||
|
class GalileoNmeaType:
|
||||||
|
# GNSS-AP-Note 2.2.5
|
||||||
|
disable = 0
|
||||||
|
gagsv = 1
|
||||||
|
all = 1
|
||||||
|
|
||||||
|
class BeiDouNmeaType:
|
||||||
|
# GNSS-AP-Note 2.2.6
|
||||||
|
disable = 0
|
||||||
|
pqgsa = 1
|
||||||
|
pqgsv = 2
|
||||||
|
all = 3
|
||||||
|
|
||||||
|
class AutoGps:
|
||||||
|
# GNSS-AP-Note 2.2.12
|
||||||
|
# Enable/disable GNSS to run automatically after the module is powered on.
|
||||||
|
disable = "0"
|
||||||
|
enable = "1"
|
||||||
|
|
||||||
|
class Sequencer:
|
||||||
|
AGPS_DATA_URI_BASE = AGPS_DATA_URI_BASE
|
||||||
|
def __init__(self, executor: Executor, modem: str, power_endpoint: str):
|
||||||
|
self.executor = executor
|
||||||
|
self.modem = modem
|
||||||
|
self.power_endpoint = power_endpoint
|
||||||
|
|
||||||
|
def _mmcli(self, args: list[str], check: bool = True) -> str:
|
||||||
|
return self.executor.exec(
|
||||||
|
["mmcli", "--modem", self.modem] + args,
|
||||||
|
check=check
|
||||||
|
).decode('utf-8')
|
||||||
|
|
||||||
|
def _try_mmcli(self, args: list[str]) -> str:
|
||||||
|
try:
|
||||||
|
return self._mmcli(args)
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _at_cmd(self, cmd: str, check: bool = True) -> str:
|
||||||
|
# this returns the mmcli output, which looks like:
|
||||||
|
# response: 'blah'
|
||||||
|
# i.e., quoted, and with a `response: ` prefix
|
||||||
|
return self._mmcli([f"--command=+{cmd}"], check=check)
|
||||||
|
|
||||||
|
def _at_structured_cmd(self, cmd: str, subcmd: str | None = None, value: str | None = None, check: bool = True) -> str:
|
||||||
|
if not subcmd and not value:
|
||||||
|
return self._at_cmd(cmd, check=check)
|
||||||
|
elif not subcmd and value:
|
||||||
|
return self._at_cmd(f"{cmd}={value}", check=check)
|
||||||
|
elif subcmd and not value:
|
||||||
|
return self._at_cmd(f"{cmd}=\"{subcmd}\"", check=check)
|
||||||
|
else:
|
||||||
|
return self._at_cmd(f"{cmd}=\"{subcmd}\",{value}", check=check)
|
||||||
|
|
||||||
|
def _at_gnssconfig(self, cfg: GNSSConfig) -> str:
|
||||||
|
return self._at_structured_cmd("QGPSCFG", "gnssconfig", cfg)
|
||||||
|
|
||||||
|
def _at_odpcontrol(self, control: ODPControl) -> str:
|
||||||
|
return self._at_structured_cmd("QGPSCFG", "odpcontrol", control)
|
||||||
|
|
||||||
|
def _at_dpoenable(self, enable: DPOEnable) -> str:
|
||||||
|
return self._at_structured_cmd("QGPSCFG", "dpoenable", enable)
|
||||||
|
|
||||||
|
def _at_gpsnmeatype(self, ty: GPSNMEAType) -> str:
|
||||||
|
return self._at_structured_cmd("QGPSCFG", "gpsnmeatype", str(ty))
|
||||||
|
|
||||||
|
def _at_glonassnmeatype(self, ty: GlonassNmeaType) -> str:
|
||||||
|
return self._at_structured_cmd("QGPSCFG", "glonassnmeatype", str(ty))
|
||||||
|
|
||||||
|
def _at_galileonmeatype(self, ty: GalileoNmeaType) -> str:
|
||||||
|
return self._at_structured_cmd("QGPSCFG", "galileonmeatype", str(ty))
|
||||||
|
|
||||||
|
def _at_beidounmeatype(self, ty: BeiDouNmeaType) -> str:
|
||||||
|
self._at_structured_cmd("QGPSCFG", "beidounmeatype", str(ty))
|
||||||
|
|
||||||
|
def _at_autogps(self, enable: AutoGps) -> str:
|
||||||
|
return self._at_structured_cmd("QGPSCFG", "autogps", enable)
|
||||||
|
|
||||||
|
def _get_assistance_data(self, variant: AgpsDataVariant) -> str | None:
|
||||||
|
try:
|
||||||
|
self.executor.exec(["curl", f"{self.AGPS_DATA_URI_BASE}/{variant}", "-o", variant])
|
||||||
|
return variant
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
logger.warning(f"AGPS data download failed: {e}")
|
||||||
|
return None # TODO: could be smarter: return cached AGPS data?
|
||||||
|
|
||||||
|
@log_scope("powering modem...", "modem powered")
|
||||||
|
def power_on(self) -> None:
|
||||||
|
self.executor.write_file(self.power_endpoint, b'1')
|
||||||
|
while self._try_mmcli([]) is None:
|
||||||
|
logger.info("modem hasn't appeared: sleeping for 1s")
|
||||||
|
time.sleep(1) # wait for modem to appear
|
||||||
|
|
||||||
|
def at_check(self) -> None:
|
||||||
|
""" sanity check that the modem is listening for AT commands and responding reasonably """
|
||||||
|
hw = self._at_cmd("QGMR")
|
||||||
|
assert 'EG25GGBR07A08M2G' in hw or self.executor.dry_run, hw
|
||||||
|
|
||||||
|
def dump_debug_info(self) -> None:
|
||||||
|
logger.debug('checking if AGPS is enabled (1) or not (0)')
|
||||||
|
self._at_structured_cmd('QGPSXTRA?')
|
||||||
|
# see if the GPS assistance data is still within valid range
|
||||||
|
logger.debug('QGPSXTRADATA: <valid_duration_minutes>,<start_time_of_agps_data>')
|
||||||
|
self._at_structured_cmd('QGPSXTRADATA?')
|
||||||
|
logger.debug('checking what time the modem last synchronized with the network')
|
||||||
|
self._at_structured_cmd('QLTS')
|
||||||
|
logger.debug('checking what time the modem thinks it is (extrapolated from sync)')
|
||||||
|
self._at_structured_cmd('QLTS', value=1)
|
||||||
|
logger.debug('checking what time the modem thinks it is (from RTC)')
|
||||||
|
self._at_structured_cmd('CCLK?')
|
||||||
|
logger.debug('checking if nmea GPS source is enabled')
|
||||||
|
self._at_structured_cmd('QGPSCFG', 'nmeasrc')
|
||||||
|
logger.debug('checking if GPS is enabled (1) or not (0)')
|
||||||
|
self._at_structured_cmd('QGPS?')
|
||||||
|
logger.debug('checking if GPS has a fix. Error 516 if not')
|
||||||
|
self._at_structured_cmd('QGPSLOC', value='0', check=False)
|
||||||
|
logger.debug('dumping AGPS positioning mode bitfield')
|
||||||
|
self._at_structured_cmd('QGPSCFG', 'agpsposmode')
|
||||||
|
|
||||||
|
@log_scope("configuring audio...", "audio configured")
|
||||||
|
def enable_audio(self) -> None:
|
||||||
|
# cribbed from eg25-manager; i don't understand these
|
||||||
|
# QDAI call shouldn't be necessary if using Megi's FW:
|
||||||
|
# - <https://xnux.eu/devices/feature/modem-pp.html>
|
||||||
|
self._at_structured_cmd("QDAI", value="1,1,0,1,0,0,1,1")
|
||||||
|
# RI signaling using physical RI pin
|
||||||
|
self._at_structured_cmd("QCFG", "risignaltype", "\"physical\"")
|
||||||
|
# Enable VoLTE support
|
||||||
|
self._at_structured_cmd("QCFG", "ims", "1")
|
||||||
|
# Enable APREADY for PP 1.2
|
||||||
|
self._at_structured_cmd("QCFG", "apready", "1,0,500")
|
||||||
|
|
||||||
|
@log_scope("configuring urc...", "urc configured")
|
||||||
|
def enable_urc(self) -> None:
|
||||||
|
# cribbed from eg25-manager; i don't even know what URC is
|
||||||
|
# URC configuration for PP 1.2 (APREADY pin connected):
|
||||||
|
# * RING URC: normal pulse length
|
||||||
|
# * Incoming SMS URC: default pulse length
|
||||||
|
# * Other URC: default length
|
||||||
|
# * Report URCs on all ports (serial and USB) for FOSS firmware
|
||||||
|
# * Reporting of URCs without any delay
|
||||||
|
# * Configure URC pin to UART Ring Indicator
|
||||||
|
self._at_structured_cmd("QCFG", "urc/ri/ring", "\"pulse\",120,1000,5000,\"off\",1")
|
||||||
|
self._at_structured_cmd("QCFG", "urc/ri/smsincoming", "\"pulse\",120,1")
|
||||||
|
self._at_structured_cmd("QCFG", "urc/ri/other", "\"off\",1,1")
|
||||||
|
self._at_structured_cmd("QCFG", "urc/delay", "0")
|
||||||
|
self._at_structured_cmd("QCFG", "urc/cache", "0")
|
||||||
|
self._at_structured_cmd("QCFG", "urc/ri/pin", "uart_ri")
|
||||||
|
self._at_structured_cmd("QURCCFG", "urcport", "\"all\"")
|
||||||
|
|
||||||
|
@log_scope("configuring gps...", "gps configured")
|
||||||
|
def enable_gps(self) -> None:
|
||||||
|
# set modem to use UTC time instead of local time.
|
||||||
|
# modemmanager sends CTZU=3 during init and that causes `AT+CCLK?` to return a timestamp that's off by 600+ days
|
||||||
|
# see: <https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/360>
|
||||||
|
self._at_structured_cmd("CTZU", value="1")
|
||||||
|
|
||||||
|
# disable GNSS, because it's only configurable while offline
|
||||||
|
self._at_structured_cmd("QGPSEND", check=False)
|
||||||
|
# self._at_structured_cmd("QGPS", value="0")
|
||||||
|
|
||||||
|
# XXX: ModemManager plugin sets QGPSXTRA=1
|
||||||
|
# self._at_structured_cmd("QGPSXTRA", value="1")
|
||||||
|
|
||||||
|
# now = datetime.datetime.now().strftime('%Y/%m/%d,%H:%M:%S') # UTC
|
||||||
|
# self._at_structured_cmd("QGPSXTRATIME", value=f"0,\"{now}\"")
|
||||||
|
locdata = self._get_assistance_data(AgpsDataVariant.gps_glonass_beidou)
|
||||||
|
if locdata:
|
||||||
|
self._mmcli([f"--location-inject-assistance-data={locdata}"])
|
||||||
|
|
||||||
|
self._at_gnssconfig(GNSSConfig.gps_glonass_beidou_galileo)
|
||||||
|
self._at_odpcontrol(ODPControl.disable)
|
||||||
|
self._at_dpoenable(DPOEnable.disable) # N.B.: eg25-manager uses `DPOEnable.enable`
|
||||||
|
self._at_gpsnmeatype(GPSNMEAType.all)
|
||||||
|
self._at_glonassnmeatype(GlonassNmeaType.all)
|
||||||
|
self._at_galileonmeatype(GalileoNmeaType.all)
|
||||||
|
self._at_beidounmeatype(BeiDouNmeaType.all)
|
||||||
|
self._at_autogps(AutoGps.disable) #< don't start GPS on modem boot
|
||||||
|
# configure so GPS output is readable via /dev/ttyUSB1
|
||||||
|
# self._mmcli(["--location-enable-gps-unmanaged"])
|
||||||
|
# TODO: tune/document these QGPS values; a smarter setting here might reduce jitter?
|
||||||
|
self._at_structured_cmd("QGPS", value="1,255,1000,0,1")
|
||||||
|
|
||||||
|
@log_scope("configuring powersave...", "powersave configured")
|
||||||
|
def enable_powersave(self) -> None:
|
||||||
|
# Allow sleeping for power saving
|
||||||
|
self._at_structured_cmd("QSCLK", value="1")
|
||||||
|
# Disable fast poweroff for stability
|
||||||
|
self._at_structured_cmd("QCFG", "fast/poweroff", "0")
|
||||||
|
# Configure sleep and wake up pin levels to active low
|
||||||
|
self._at_structured_cmd("QCFG", "sleepind/level", "0")
|
||||||
|
self._at_structured_cmd("QCFG", "wakeupin/level", "0,0")
|
||||||
|
# Do not enter RAMDUMP mode, auto-reset instead
|
||||||
|
self._at_structured_cmd("QCFG", "ApRstLevel", "1")
|
||||||
|
self._at_structured_cmd("QCFG", "ModemRstLevel", "1")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
logging.basicConfig()
|
||||||
|
logging.getLogger().setLevel(logging.INFO)
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description="initialize the eg25 Pinephone modem for GPS tracking")
|
||||||
|
parser.add_argument('--modem', default='any', help='name of modem to configure (see mmcli --list-modems)')
|
||||||
|
parser.add_argument('--power-endpoint', default='/sys/class/modem-power/modem-power/device/powered', help='sysfs endpoint that can turn the modem on/off')
|
||||||
|
|
||||||
|
parser.add_argument("--dry-run", action='store_true', help="print commands instead of executing them")
|
||||||
|
parser.add_argument("--verbose", action='store_true', help="log each command before executing")
|
||||||
|
|
||||||
|
parser.add_argument('--power-on', action='store_true', help="enable power to the modem")
|
||||||
|
parser.add_argument('--enable-audio', action='store_true', help="configure audio for calling (?)")
|
||||||
|
parser.add_argument('--enable-urc', action='store_true', help="enable support for Unsolicited Return Codes (?)")
|
||||||
|
parser.add_argument('--enable-gps', action='store_true', help="enable the GPS and acquire tracking until asked to stop")
|
||||||
|
parser.add_argument('--enable-powersave', action='store_true', help="configure modem to sleep when possible")
|
||||||
|
parser.add_argument('--dump-debug-info', action='store_true', help="don't initialize anything, just dump debugging data")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
if args.verbose or args.dump_debug_info:
|
||||||
|
logging.getLogger().setLevel(logging.DEBUG)
|
||||||
|
|
||||||
|
executor = Executor(args.dry_run)
|
||||||
|
sequencer = Sequencer(executor, modem=args.modem, power_endpoint=args.power_endpoint)
|
||||||
|
|
||||||
|
if args.power_on:
|
||||||
|
sequencer.power_on()
|
||||||
|
if args.enable_audio:
|
||||||
|
sequencer.enable_audio()
|
||||||
|
if args.enable_urc:
|
||||||
|
sequencer.enable_urc()
|
||||||
|
if args.enable_gps:
|
||||||
|
sequencer.enable_gps()
|
||||||
|
if args.enable_powersave:
|
||||||
|
sequencer.enable_powersave()
|
||||||
|
if args.dump_debug_info:
|
||||||
|
sequencer.dump_debug_info()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
77
pkgs/additional/eg25-manager/default.nix
Normal file
77
pkgs/additional/eg25-manager/default.nix
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
# package based on:
|
||||||
|
# - <https://github.com/NixOS/mobile-nixos/pull/573>
|
||||||
|
|
||||||
|
{ lib
|
||||||
|
, stdenv
|
||||||
|
, callPackage
|
||||||
|
, fetchFromGitLab
|
||||||
|
, gnugrep
|
||||||
|
, meson
|
||||||
|
, ninja
|
||||||
|
, pkg-config
|
||||||
|
, scdoc
|
||||||
|
, curl
|
||||||
|
, glib
|
||||||
|
, libgudev
|
||||||
|
, libusb1
|
||||||
|
# if true, build with MMGLIB. if false, eg25-manager won't speak to modemmanager and will be usable standalone
|
||||||
|
, withModemManager ? true, modemmanager
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
# eg25-manager needs to be made compatible with libgpiod 2.0 API. see:
|
||||||
|
# - <https://github.com/NixOS/mobile-nixos/pull/573#issuecomment-1666739462>
|
||||||
|
# - <https://gitlab.com/mobian1/eg25-manager/-/issues/45>
|
||||||
|
# nixpkgs libgpiod was bumped 2023-07-29:
|
||||||
|
# - <https://github.com/NixOS/nixpkgs/pull/246018>
|
||||||
|
libgpiod1 = callPackage ./libgpiod1.nix { };
|
||||||
|
in
|
||||||
|
stdenv.mkDerivation rec {
|
||||||
|
pname = "eg25-manager";
|
||||||
|
version = "0.4.6";
|
||||||
|
|
||||||
|
src = fetchFromGitLab {
|
||||||
|
owner = "mobian1";
|
||||||
|
repo = "eg25-manager";
|
||||||
|
rev = version;
|
||||||
|
hash = "sha256-2JsdwK1ZOr7ljNHyuUMzVCpl+HV0C5sA5LAOkmELqag=";
|
||||||
|
};
|
||||||
|
|
||||||
|
postPatch = ''
|
||||||
|
substituteInPlace 'udev/80-modem-eg25.rules' \
|
||||||
|
--replace '/bin/grep' '${gnugrep}/bin/grep'
|
||||||
|
'';
|
||||||
|
|
||||||
|
depsBuildBuild = [
|
||||||
|
pkg-config
|
||||||
|
];
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
glib # Contains gdbus-codegen program
|
||||||
|
meson
|
||||||
|
ninja
|
||||||
|
pkg-config
|
||||||
|
scdoc
|
||||||
|
];
|
||||||
|
|
||||||
|
buildInputs = [
|
||||||
|
curl
|
||||||
|
glib
|
||||||
|
libgpiod1
|
||||||
|
libgudev
|
||||||
|
libusb1
|
||||||
|
] ++ lib.optionals withModemManager [
|
||||||
|
modemmanager
|
||||||
|
];
|
||||||
|
|
||||||
|
passthru = {
|
||||||
|
inherit libgpiod1;
|
||||||
|
};
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
description = "Manager daemon for the Quectel EG25 mobile broadband modem";
|
||||||
|
homepage = "https://gitlab.com/mobian1/eg25-manager";
|
||||||
|
license = licenses.gpl3Plus;
|
||||||
|
platforms = platforms.linux;
|
||||||
|
};
|
||||||
|
}
|
39
pkgs/additional/eg25-manager/libgpiod1.nix
Normal file
39
pkgs/additional/eg25-manager/libgpiod1.nix
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
{ lib, stdenv, fetchurl, autoreconfHook, autoconf-archive, pkg-config, kmod
|
||||||
|
, enable-tools ? true
|
||||||
|
, enablePython ? false, python3, ncurses }:
|
||||||
|
|
||||||
|
stdenv.mkDerivation rec {
|
||||||
|
pname = "libgpiod";
|
||||||
|
version = "1.6.4";
|
||||||
|
|
||||||
|
src = fetchurl {
|
||||||
|
url = "https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/snapshot/libgpiod-${version}.tar.gz";
|
||||||
|
hash = "sha256-gp1KwmjfB4U2CdZ8/H9HbpqnNssqaKYwvpno+tGXvgo=";
|
||||||
|
};
|
||||||
|
|
||||||
|
buildInputs = [ kmod ] ++ lib.optionals enablePython [ python3 ncurses ];
|
||||||
|
nativeBuildInputs = [
|
||||||
|
autoconf-archive
|
||||||
|
pkg-config
|
||||||
|
autoreconfHook
|
||||||
|
];
|
||||||
|
|
||||||
|
configureFlags = [
|
||||||
|
"--enable-tools=${if enable-tools then "yes" else "no"}"
|
||||||
|
"--enable-bindings-cxx"
|
||||||
|
"--prefix=${placeholder "out"}"
|
||||||
|
] ++ lib.optional enablePython "--enable-bindings-python";
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
description = "C library and tools for interacting with the linux GPIO character device";
|
||||||
|
longDescription = ''
|
||||||
|
Since linux 4.8 the GPIO sysfs interface is deprecated. User space should use
|
||||||
|
the character device instead. This library encapsulates the ioctl calls and
|
||||||
|
data structures behind a straightforward API.
|
||||||
|
'';
|
||||||
|
homepage = "https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/about/";
|
||||||
|
license = licenses.lgpl2;
|
||||||
|
maintainers = [ maintainers.expipiplus1 ];
|
||||||
|
platforms = platforms.linux;
|
||||||
|
};
|
||||||
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
{ stdenv
|
{ stdenv
|
||||||
, fetchFromGitHub
|
, fetchFromGitHub
|
||||||
, fetchFromGitea
|
, fetchFromGitea
|
||||||
, gnused
|
|
||||||
, mkYarnModules
|
, mkYarnModules
|
||||||
|
, nodejs
|
||||||
, zip
|
, zip
|
||||||
}:
|
}:
|
||||||
|
|
||||||
@@ -25,7 +25,8 @@ let
|
|||||||
# sha256 = "sha256-dSRZ2ToEOPhzHNvlG8qdewa7689gT8cNB7nXkN3/Avo=";
|
# sha256 = "sha256-dSRZ2ToEOPhzHNvlG8qdewa7689gT8cNB7nXkN3/Avo=";
|
||||||
# };
|
# };
|
||||||
browserpass-extension-yarn-modules = mkYarnModules {
|
browserpass-extension-yarn-modules = mkYarnModules {
|
||||||
inherit pname version;
|
inherit version;
|
||||||
|
pname = "${pname}-modules";
|
||||||
packageJSON = ./package.json;
|
packageJSON = ./package.json;
|
||||||
yarnLock = ./yarn.lock;
|
yarnLock = ./yarn.lock;
|
||||||
# yarnNix is auto-generated. to update: leave unset, then query the package deps and copy it out of the store.
|
# yarnNix is auto-generated. to update: leave unset, then query the package deps and copy it out of the store.
|
||||||
@@ -37,9 +38,20 @@ let
|
|||||||
in stdenv.mkDerivation {
|
in stdenv.mkDerivation {
|
||||||
inherit pname version src;
|
inherit pname version src;
|
||||||
|
|
||||||
|
nativeBuildInputs = [ nodejs zip ];
|
||||||
|
|
||||||
postPatch = ''
|
postPatch = ''
|
||||||
# dependencies are built separately: skip the yarn install
|
# dependencies are built separately: skip the yarn install
|
||||||
${gnused}/bin/sed -i /yarn\ install/d src/Makefile
|
# prettier, lessc, browserify are made available here via the modules,
|
||||||
|
# which are for the host (even the devDependencies are compiled for the host).
|
||||||
|
# but we can just run those via the build node.
|
||||||
|
#
|
||||||
|
# alternative would be to patchShebangs in the node_modules dir.
|
||||||
|
substituteInPlace src/Makefile \
|
||||||
|
--replace "yarn install" "true" \
|
||||||
|
--replace ' $(PRETTIER)' ' node $(PRETTIER)' \
|
||||||
|
--replace ' $(LESSC)' ' node $(LESSC)' \
|
||||||
|
--replace ' $(BROWSERIFY)' ' node $(BROWSERIFY)'
|
||||||
'';
|
'';
|
||||||
|
|
||||||
preBuild = ''
|
preBuild = ''
|
||||||
@@ -48,11 +60,12 @@ in stdenv.mkDerivation {
|
|||||||
|
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
pushd firefox
|
pushd firefox
|
||||||
${zip}/bin/zip -r $out ./*
|
zip -r $out ./*
|
||||||
popd
|
popd
|
||||||
'';
|
'';
|
||||||
|
|
||||||
passthru = {
|
passthru = {
|
||||||
|
yarn-modules = browserpass-extension-yarn-modules;
|
||||||
extid = "browserpass@maximbaz.com";
|
extid = "browserpass@maximbaz.com";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -20,8 +20,10 @@ stdenv.mkDerivation rec {
|
|||||||
./0003-disable-metrics.patch
|
./0003-disable-metrics.patch
|
||||||
];
|
];
|
||||||
|
|
||||||
|
nativeBuildInputs = [ zip ];
|
||||||
|
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
${zip}/bin/zip -r $out ./*
|
zip -r $out ./*
|
||||||
'';
|
'';
|
||||||
|
|
||||||
passthru = {
|
passthru = {
|
||||||
|
@@ -29,7 +29,7 @@ let
|
|||||||
};
|
};
|
||||||
in (stdenv.mkDerivation ({
|
in (stdenv.mkDerivation ({
|
||||||
# heavily borrows from <repo:nixos/nixpkgs:pkgs/build-support/fetchfirefoxaddon/default.nix>
|
# heavily borrows from <repo:nixos/nixpkgs:pkgs/build-support/fetchfirefoxaddon/default.nix>
|
||||||
inherit (addon) name;
|
name = "${addon.name}-wrapped";
|
||||||
unpackPhase = ''
|
unpackPhase = ''
|
||||||
echo "patching firefox addon $name into $out/${extid}.xpi"
|
echo "patching firefox addon $name into $out/${extid}.xpi"
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ let
|
|||||||
'';
|
'';
|
||||||
} // args')).overrideAttrs (final: upstream: {
|
} // args')).overrideAttrs (final: upstream: {
|
||||||
passthru = (upstream.passthru or {}) // {
|
passthru = (upstream.passthru or {}) // {
|
||||||
withAttrs = attrs: wrapAddon final.finalPackage attrs;
|
withAttrs = attrs: wrapAddon addon (args // attrs);
|
||||||
withPostPatch = postPatch: final.passthru.withAttrs { inherit postPatch; };
|
withPostPatch = postPatch: final.passthru.withAttrs { inherit postPatch; };
|
||||||
# given an addon, repackage it without some `perm`ission
|
# given an addon, repackage it without some `perm`ission
|
||||||
withoutPermission = perm: final.passthru.withPostPatch ''
|
withoutPermission = perm: final.passthru.withPostPatch ''
|
||||||
@@ -92,9 +92,9 @@ in lib.makeScope newScope (self: with self; {
|
|||||||
ether-metamask = fetchAddon "ether-metamask" "webextension@metamask.io" "sha256-UI83wUUc33OlQYX+olgujeppoo2D2PAUJ+Wma5mH2O0=";
|
ether-metamask = fetchAddon "ether-metamask" "webextension@metamask.io" "sha256-UI83wUUc33OlQYX+olgujeppoo2D2PAUJ+Wma5mH2O0=";
|
||||||
i2p-in-private-browsing = fetchAddon "i2p-in-private-browsing" "i2ppb@eyedeekay.github.io" "sha256-dJcJ3jxeAeAkRvhODeIVrCflvX+S4E0wT/PyYzQBQWs=";
|
i2p-in-private-browsing = fetchAddon "i2p-in-private-browsing" "i2ppb@eyedeekay.github.io" "sha256-dJcJ3jxeAeAkRvhODeIVrCflvX+S4E0wT/PyYzQBQWs=";
|
||||||
sidebery = fetchAddon "sidebery" "{3c078156-979c-498b-8990-85f7987dd929}" "sha256-YONfK/rIjlsrTgRHIt3km07Q7KnpIW89Z9r92ZSCc6w=";
|
sidebery = fetchAddon "sidebery" "{3c078156-979c-498b-8990-85f7987dd929}" "sha256-YONfK/rIjlsrTgRHIt3km07Q7KnpIW89Z9r92ZSCc6w=";
|
||||||
sponsorblock = fetchAddon "sponsorblock" "sponsorBlocker@ajay.app" "sha256-b/OTFmhSEUZ/CYrYCE4rHVMQmY+Y78k8jSGMoR8vsZA=";
|
sponsorblock = fetchAddon "sponsorblock" "sponsorBlocker@ajay.app" "sha256-kIVx/Yl2IZ0/0RqLMf4+HJojoDA7oOUYwZfFvMt/2XE=";
|
||||||
ublacklist = fetchAddon "ublacklist" "@ublacklist" "sha256-NZ2FmgJiYnH7j2Lkn0wOembxaEphmUuUk0Ytmb0rNWo=";
|
ublacklist = fetchAddon "ublacklist" "@ublacklist" "sha256-NZ2FmgJiYnH7j2Lkn0wOembxaEphmUuUk0Ytmb0rNWo=";
|
||||||
ublock-origin = fetchAddon "ublock-origin" "uBlock0@raymondhill.net" "sha256-EGGAA+cLUow/F5luNzFG055rFfd3rEyh8hTaL/23pbM=";
|
ublock-origin = fetchAddon "ublock-origin" "uBlock0@raymondhill.net" "sha256-i3NGi8IzoR3SiVIZRmOBeD0ZEjhX3Qtv0WoBgg/KSDQ=";
|
||||||
|
|
||||||
# TODO: build bypass-paywalls from source? it's mysteriously disappeared from the Mozilla store.
|
# TODO: build bypass-paywalls from source? it's mysteriously disappeared from the Mozilla store.
|
||||||
# bypass-paywalls-clean = fetchAddon "bypass-paywalls-clean" "{d133e097-46d9-4ecc-9903-fa6a722a6e0e}" "sha256-oUwdqdAwV3DezaTtOMx7A/s4lzIws+t2f08mwk+324k=";
|
# bypass-paywalls-clean = fetchAddon "bypass-paywalls-clean" "{d133e097-46d9-4ecc-9903-fa6a722a6e0e}" "sha256-oUwdqdAwV3DezaTtOMx7A/s4lzIws+t2f08mwk+324k=";
|
||||||
@@ -113,7 +113,8 @@ in lib.makeScope newScope (self: with self; {
|
|||||||
# XXX: i tried to build sponsorblock from source and patch this *before* it gets webpack'd,
|
# XXX: i tried to build sponsorblock from source and patch this *before* it gets webpack'd,
|
||||||
# but web shit is absolutely cursed and building from source requires a fucking PhD
|
# but web shit is absolutely cursed and building from source requires a fucking PhD
|
||||||
# (if you have one, feel free to share your nix package)
|
# (if you have one, feel free to share your nix package)
|
||||||
${gnused}/bin/sed -i 's/default\.config\.userID)/default.config.userID && false)/' js/background.js
|
substituteInPlace js/background.js \
|
||||||
|
--replace 'default.config.userId)' 'default.config.userID && false)'
|
||||||
'';
|
'';
|
||||||
|
|
||||||
ublacklist = wrapAddon unwrapped.ublacklist {};
|
ublacklist = wrapAddon unwrapped.ublacklist {};
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
, fetchFromGitHub
|
, fetchFromGitHub
|
||||||
, libhandy
|
, libhandy
|
||||||
}:
|
}:
|
||||||
gpodder.overrideAttrs (upstream: rec {
|
gpodder.overridePythonAttrs (upstream: rec {
|
||||||
pname = "gpodder-adaptive";
|
pname = "gpodder-adaptive";
|
||||||
version = "3.11.1+1";
|
version = "3.11.1+1";
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
@@ -12,6 +12,21 @@ gpodder.overrideAttrs (upstream: rec {
|
|||||||
hash = "sha256-pn5sh8CLV2Civ26PL3rrkkUdoobu7SIHXmWKCZucBhw=";
|
hash = "sha256-pn5sh8CLV2Civ26PL3rrkkUdoobu7SIHXmWKCZucBhw=";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# nixpkgs `gpodder` uses the `format = "other"` Makefile build flow.
|
||||||
|
# upstream specifies a Makefile, and it's just `setup.py` calls plus a few other deps.
|
||||||
|
# however, it calls the build Python, which breaks for cross compilation.
|
||||||
|
# nixpkgs knows how to cross-compile setuptools formats, so use that and only mimic the
|
||||||
|
# parts of the Makefile that aren't part of that.
|
||||||
|
# TODO: upstream this into main nixpkgs `gpodder` package.
|
||||||
|
format = "setuptools";
|
||||||
|
preBuild = ''
|
||||||
|
make \
|
||||||
|
"PREFIX=$(out)" \
|
||||||
|
"share/applications/gpodder-url-handler.desktop" \
|
||||||
|
"share/applications/gpodder.desktop" \
|
||||||
|
"share/dbus-1/services/org.gpodder.service"
|
||||||
|
'';
|
||||||
|
|
||||||
buildInputs = upstream.buildInputs ++ [
|
buildInputs = upstream.buildInputs ++ [
|
||||||
libhandy
|
libhandy
|
||||||
];
|
];
|
||||||
|
569
pkgs/additional/lemoa/Cargo.lock
generated
569
pkgs/additional/lemoa/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -13,13 +13,13 @@
|
|||||||
|
|
||||||
rustPlatform.buildRustPackage rec {
|
rustPlatform.buildRustPackage rec {
|
||||||
pname = "lemoa";
|
pname = "lemoa";
|
||||||
version = "0.3.0";
|
version = "0.4.0";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "lemmy-gtk";
|
owner = "lemmy-gtk";
|
||||||
repo = pname;
|
repo = pname;
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
hash = "sha256-LT+UkjDkKbi327SE4VT+BdrpE6hQywajIZ7xpJPvvCc=";
|
hash = "sha256-0xMdshQ12mV93r5UwxRLgYsIj97GgxmDDMEisam29HI=";
|
||||||
};
|
};
|
||||||
|
|
||||||
cargoLock = {
|
cargoLock = {
|
||||||
|
37
pkgs/additional/linux-manjaro/default.nix
Normal file
37
pkgs/additional/linux-manjaro/default.nix
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
{ linux_6_4
|
||||||
|
, fetchpatch
|
||||||
|
, pkgs
|
||||||
|
# something inside nixpkgs calls `override` on the kernel and passes in extra arguments; we'll forward them
|
||||||
|
, ...
|
||||||
|
}@args:
|
||||||
|
let
|
||||||
|
# use the latest commit: for linux 6.4.7
|
||||||
|
# manjaro's changes between kernel patch versions tend to be minimal if any.
|
||||||
|
manjaroBase = "https://gitlab.manjaro.org/manjaro-arm/packages/core/linux/-/raw/6c64aa18076a7dc75bfd854b27906467f5d95336";
|
||||||
|
manjaroPatch = args: {
|
||||||
|
inherit (args) name;
|
||||||
|
patch = fetchpatch ({
|
||||||
|
url = "${manjaroBase}/${args.name}?inline=false";
|
||||||
|
} // args);
|
||||||
|
};
|
||||||
|
|
||||||
|
# the idea for patching off Manjaro's kernel comes from jakewaksbaum:
|
||||||
|
# - https://git.sr.ht/~jakewaksbaum/pi/tree/af20aae5653545d6e67a459b59ee3e1ca8a680b0/item/kernel/default.nix
|
||||||
|
# - he later abandoned this, i think because he's using the Pinephone Pro which received mainline support.
|
||||||
|
manjaroPatches = [
|
||||||
|
(manjaroPatch {
|
||||||
|
# this patch is critical to enable wifi (RTL8723CS)
|
||||||
|
# - the alternative is a wholly forked kernel by megi/megous:
|
||||||
|
# - https://xnux.eu/howtos/build-pinephone-kernel.html#toc-how-to-build-megi-s-pinehpone-kernel
|
||||||
|
# - i don't know if this patch is based on megi's or original.
|
||||||
|
# - it might be possible to build this rtl8723cs out of tree?
|
||||||
|
name = "2001-staging-add-rtl8723cs-driver.patch";
|
||||||
|
hash = "sha256-M4MR9Oi90BmaB68kWjezHon/NzXDxu13Hc+TWm3tcjg=";
|
||||||
|
})
|
||||||
|
];
|
||||||
|
in linux_6_4.override (args // {
|
||||||
|
kernelPatches = (args.kernelPatches or []) ++ [
|
||||||
|
pkgs.kernelPatches.bridge_stp_helper
|
||||||
|
pkgs.kernelPatches.request_key_helper
|
||||||
|
] ++ manjaroPatches;
|
||||||
|
})
|
@@ -1,13 +1,13 @@
|
|||||||
{ lib
|
{ lib
|
||||||
, buildLinux
|
, buildLinux
|
||||||
, buildPackages
|
, fetchpatch
|
||||||
, fetchFromGitHub
|
, fetchFromGitHub
|
||||||
, modDirVersionArg ? null
|
|
||||||
, nixosTests
|
|
||||||
, perl
|
|
||||||
, pkgs
|
, pkgs
|
||||||
|
# modem_power is incompatible with eg25-manager: <https://gitlab.com/mobian1/eg25-manager/-/issues/38>
|
||||||
|
, withModemPower ? true
|
||||||
|
# something inside nixpkgs calls `override` on the kernel and passes in extra arguments
|
||||||
, ...
|
, ...
|
||||||
} @ args:
|
}@args:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
@@ -20,11 +20,11 @@ let
|
|||||||
# - orange-pi is listed as the "main integration branch".
|
# - orange-pi is listed as the "main integration branch".
|
||||||
# - this suggests it's NOT a stable branch, only `orange-pi-X.YY-YYYYMMDD-NNNN` tags are "formal" releases
|
# - this suggests it's NOT a stable branch, only `orange-pi-X.YY-YYYYMMDD-NNNN` tags are "formal" releases
|
||||||
# - specific branches like `pp` (pinephone) are dev branches, and probably less stable.
|
# - specific branches like `pp` (pinephone) are dev branches, and probably less stable.
|
||||||
rev = "orange-pi-6.4-20230619-0323";
|
rev = "orange-pi-6.4-20230731-1920";
|
||||||
hash = "sha256-il32UQM/8Fc7VHft3+M4TLMxk5+h28C9Suu1kRdZj2M=";
|
hash = "sha256-XHYxFvosa1FMOFuyb3OwRc/orcD98fSi9NKf1f+riCA=";
|
||||||
base = "6.4.0";
|
base = "6.4.7";
|
||||||
# set to empty if not a release candidate, else `-rc<N>`
|
# set to empty if not a release candidate, else `-rc<N>`
|
||||||
rc = "-rc7";
|
rc = "";
|
||||||
|
|
||||||
# pinephone uses the linux dtb at arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
# pinephone uses the linux dtb at arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||||
# - this includes sun50i-a64.dtsi
|
# - this includes sun50i-a64.dtsi
|
||||||
@@ -34,6 +34,18 @@ let
|
|||||||
kernelConfig = with lib.kernel; {
|
kernelConfig = with lib.kernel; {
|
||||||
# NB: nix adds the CONFIG_ prefix to each of these.
|
# NB: nix adds the CONFIG_ prefix to each of these.
|
||||||
# if you add the prefix yourself nix will IGNORE YOUR CONFIG.
|
# if you add the prefix yourself nix will IGNORE YOUR CONFIG.
|
||||||
|
|
||||||
|
# optimize for faster builds.
|
||||||
|
# see <repo:kernel.org/linux:Documentation/admin-guide/quickly-build-trimmed-linux.rst>
|
||||||
|
DEBUG_KERNEL = lib.mkForce no; # option group which seems to just gate the other DEBUG_ opts?
|
||||||
|
DEBUG_INFO = lib.mkForce no; # for gdb debugging
|
||||||
|
DEBUG_INFO_BTF = lib.mkForce no; # BPF debug symbols. rec by <https://nixos.wiki/wiki/Linux_kernel#Too_high_ram_usage>
|
||||||
|
SCHED_DEBUG = lib.mkForce no; # determines /sys/kernel/debug/sched
|
||||||
|
# SUNRPC_DEBUG = lib.mkForce no; # i use NFS though
|
||||||
|
|
||||||
|
MODEM_POWER = lib.mkIf (!withModemPower) no;
|
||||||
|
|
||||||
|
# taken from mobile-nixos config?? or upstream megous config??
|
||||||
RTL8723CS = module;
|
RTL8723CS = module;
|
||||||
BT_HCIUART_3WIRE = yes;
|
BT_HCIUART_3WIRE = yes;
|
||||||
BT_HCIUART_RTL = yes;
|
BT_HCIUART_RTL = yes;
|
||||||
@@ -99,35 +111,46 @@ let
|
|||||||
extraKernelPatches = [
|
extraKernelPatches = [
|
||||||
pkgs.kernelPatches.bridge_stp_helper
|
pkgs.kernelPatches.bridge_stp_helper
|
||||||
pkgs.kernelPatches.request_key_helper
|
pkgs.kernelPatches.request_key_helper
|
||||||
(patchDefconfig kernelConfig)
|
# (patchDefconfig kernelConfig)
|
||||||
|
] ++ lib.optionals (!withModemPower) [
|
||||||
|
{
|
||||||
|
# Drop modem-power from DT to allow eg25-manager to have full control.
|
||||||
|
# source: <https://github.com/NixOS/mobile-nixos/pull/573>
|
||||||
|
name = "remove-modem-power-from-devicetree";
|
||||||
|
patch = fetchpatch {
|
||||||
|
url = "https://gitlab.com/postmarketOS/pmaports/-/raw/164e9f010dcf56642d8e6f422a994b927ae23f38/device/main/linux-postmarketos-allwinner/0007-dts-pinephone-drop-modem-power-node.patch";
|
||||||
|
sha256 = "nYCoaYj8CuxbgXfy5q43Xb/ebe5DlJ1Px571y1/+lfQ=";
|
||||||
|
};
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
# create a kernelPatch which overrides nixos' defconfig with extra options
|
# create a kernelPatch which overrides nixos' defconfig with extra options
|
||||||
patchDefconfig = config: {
|
# patchDefconfig = config: {
|
||||||
# defconfig options. this method comes from here:
|
# # defconfig options. this method comes from here:
|
||||||
# - https://discourse.nixos.org/t/the-correct-way-to-override-the-latest-kernel-config/533/9
|
# # - https://discourse.nixos.org/t/the-correct-way-to-override-the-latest-kernel-config/533/9
|
||||||
name = "linux-megous-defconfig";
|
# name = "linux-megous-defconfig";
|
||||||
patch = null;
|
# patch = null;
|
||||||
extraStructuredConfig = config;
|
# extraStructuredConfig = config;
|
||||||
|
# };
|
||||||
|
|
||||||
|
in buildLinux (args // {
|
||||||
|
version = base + rc;
|
||||||
|
|
||||||
|
# modDirVersion needs to be x.y.z, where `z` could be `Z-rcN`
|
||||||
|
# nix kernel build will sanity check us if we get the modDirVersion wrong
|
||||||
|
modDirVersion = base + rc;
|
||||||
|
|
||||||
|
# branchVersion needs to be x.y
|
||||||
|
extraMeta.branch = versions.majorMinor base;
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "megous";
|
||||||
|
repo = "linux";
|
||||||
|
inherit rev hash;
|
||||||
};
|
};
|
||||||
|
|
||||||
overridenArgs = args // rec {
|
kernelPatches = (args.kernelPatches or []) ++ extraKernelPatches;
|
||||||
version = base + rc;
|
|
||||||
|
|
||||||
# modDirVersion needs to be x.y.z, will automatically add .0 if needed
|
structuredExtraConfig = (args.structuredExtraConfig or {}) // kernelConfig;
|
||||||
modDirVersion = if (modDirVersionArg == null) then concatStringsSep "." (take 3 (splitVersion "${version}.0")) + rc else modDirVersionArg;
|
})
|
||||||
|
|
||||||
# branchVersion needs to be x.y
|
|
||||||
extraMeta.branch = versions.majorMinor version;
|
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
|
||||||
owner = "megous";
|
|
||||||
repo = "linux";
|
|
||||||
inherit rev hash;
|
|
||||||
};
|
|
||||||
} // (args.argsOverride or { });
|
|
||||||
finalArgs = overridenArgs // {
|
|
||||||
kernelPatches = overridenArgs.kernelPatches or [] ++ extraKernelPatches;
|
|
||||||
};
|
|
||||||
in buildLinux finalArgs
|
|
||||||
|
55
pkgs/additional/mcg/default.nix
Normal file
55
pkgs/additional/mcg/default.nix
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
{ stdenv
|
||||||
|
, lib
|
||||||
|
, desktop-file-utils
|
||||||
|
, fetchFromGitLab
|
||||||
|
, gettext
|
||||||
|
, glib
|
||||||
|
, gobject-introspection
|
||||||
|
, gtk3
|
||||||
|
, meson
|
||||||
|
, ninja
|
||||||
|
, python3
|
||||||
|
, wrapGAppsHook
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
# optional deps: avahi, python-keyring
|
||||||
|
pythonEnv = python3.withPackages (ps: with ps; [ dateutil pygobject3 ]);
|
||||||
|
in
|
||||||
|
stdenv.mkDerivation rec {
|
||||||
|
pname = "mcg";
|
||||||
|
version = "3.2.1";
|
||||||
|
src = fetchFromGitLab {
|
||||||
|
owner = "coderkun";
|
||||||
|
repo = "mcg";
|
||||||
|
rev = "v${version}";
|
||||||
|
hash = "sha256-awPMXGruCB/2nwfDqYlc0Uu9E6VV1AleEZAw9Xdsbt8=";
|
||||||
|
};
|
||||||
|
|
||||||
|
postPatch = ''
|
||||||
|
substituteInPlace src/meson.build \
|
||||||
|
--replace "python.find_installation('python3').full_path()" "'${pythonEnv}/bin/python3'"
|
||||||
|
'';
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
gtk3 # for gtk-update-icon-cache
|
||||||
|
desktop-file-utils # for update-desktop-database
|
||||||
|
gettext # for msgfmt
|
||||||
|
glib # for glib-compile-resources
|
||||||
|
gobject-introspection # needed so wrapGAppsHook includes GI_TYPEPATHS for gtk3
|
||||||
|
meson
|
||||||
|
ninja
|
||||||
|
wrapGAppsHook
|
||||||
|
];
|
||||||
|
|
||||||
|
buildInputs = [
|
||||||
|
gtk3
|
||||||
|
];
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
description = "CoverGrid (mcg) is a client for the Music Player Daemon (MPD), focusing on albums instead of single tracks.";
|
||||||
|
homepage = "https://www.suruatoel.xyz/codes/mcg";
|
||||||
|
platforms = platforms.linux;
|
||||||
|
# license = TODO
|
||||||
|
maintainers = with maintainers; [ colinsane ];
|
||||||
|
};
|
||||||
|
}
|
@@ -4,7 +4,7 @@
|
|||||||
, mpvScripts
|
, mpvScripts
|
||||||
}:
|
}:
|
||||||
mpvScripts.uosc.overrideAttrs (upstream: {
|
mpvScripts.uosc.overrideAttrs (upstream: {
|
||||||
version = "unstable-2023-07-26";
|
version = "unstable-2023-08-29";
|
||||||
# src = fetchFromGitHub {
|
# src = fetchFromGitHub {
|
||||||
# owner = "tomasklaen";
|
# owner = "tomasklaen";
|
||||||
# repo = "uosc";
|
# repo = "uosc";
|
||||||
@@ -15,8 +15,8 @@ mpvScripts.uosc.overrideAttrs (upstream: {
|
|||||||
domain = "git.uninsane.org";
|
domain = "git.uninsane.org";
|
||||||
owner = "colin";
|
owner = "colin";
|
||||||
repo = "uosc";
|
repo = "uosc";
|
||||||
rev = "dev/sane";
|
rev = "sane-0.2";
|
||||||
hash = "sha256-XOhryppod3zozYrPQlGBw298u+0/eS1MaDepV4p88cM=";
|
hash = "sha256-j5hX+lAf7mHx4vqI0shOekmOh4aZsOiRb3rPs8vQ4qo=";
|
||||||
# for version > 4.7.0, we can use nixpkgs src and set `patches` to a fetch of my one custom commit
|
# for version > 4.7.0, we can use nixpkgs src and set `patches` to a fetch of my one custom commit
|
||||||
};
|
};
|
||||||
passthru = upstream.passthru // {
|
passthru = upstream.passthru // {
|
||||||
|
102
pkgs/additional/phog/default.nix
Normal file
102
pkgs/additional/phog/default.nix
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
{ lib
|
||||||
|
, stdenv
|
||||||
|
, fetchFromGitLab
|
||||||
|
, meson
|
||||||
|
, ninja
|
||||||
|
, pkg-config
|
||||||
|
, gcr
|
||||||
|
, glib
|
||||||
|
, gnome-desktop
|
||||||
|
, gtk3
|
||||||
|
, libgudev
|
||||||
|
, libjson
|
||||||
|
, json-glib
|
||||||
|
, libhandy
|
||||||
|
, networkmanager
|
||||||
|
, linux-pam
|
||||||
|
, systemd
|
||||||
|
, upower
|
||||||
|
, wayland
|
||||||
|
, libxkbcommon
|
||||||
|
, python3
|
||||||
|
, phoc
|
||||||
|
, bash
|
||||||
|
, gnome
|
||||||
|
, squeekboard ? null
|
||||||
|
, wayland-scanner
|
||||||
|
, wrapGAppsHook
|
||||||
|
}:
|
||||||
|
|
||||||
|
stdenv.mkDerivation rec {
|
||||||
|
pname = "phog";
|
||||||
|
version = "0.1.3";
|
||||||
|
|
||||||
|
src = fetchFromGitLab {
|
||||||
|
owner = "mobian1";
|
||||||
|
repo = "phog";
|
||||||
|
rev = version;
|
||||||
|
hash = "sha256-zny1FUYKwVXVSBGTh8AFVtMBS7dWZHTKO2gkPNPSL2M=";
|
||||||
|
};
|
||||||
|
|
||||||
|
patches = [
|
||||||
|
./sway-compat.patch
|
||||||
|
];
|
||||||
|
|
||||||
|
postPatch = ''
|
||||||
|
patchShebangs build-aux/post_install.py
|
||||||
|
sed -i /phog_plugins_dir/d build-aux/post_install.py
|
||||||
|
substituteInPlace src/greetd.c \
|
||||||
|
--replace '/usr/share/wayland-sessions' '/run/current-system/sw/share/wayland-sessions/' \
|
||||||
|
--replace '/usr/share/xsessions' '/run/current-system/sw/share/xsessions'
|
||||||
|
'' + lib.optionalString (squeekboard == null) ''
|
||||||
|
substituteInPlace data/phog.in \
|
||||||
|
--replace " & squeekboard" ""
|
||||||
|
'';
|
||||||
|
preFixup = ''
|
||||||
|
gappsWrapperArgs+=(
|
||||||
|
--prefix PATH : ${lib.makeBinPath [ bash squeekboard ]}
|
||||||
|
--prefix XDG_DATA_DIRS : "${gnome.gnome-shell}/share/gsettings-schemas/${gnome.gnome-shell.name}"
|
||||||
|
)
|
||||||
|
'';
|
||||||
|
|
||||||
|
|
||||||
|
mesonFlags = [ "-Dcompositor=${phoc}/bin/phoc" ];
|
||||||
|
|
||||||
|
depsBuildBuild = [
|
||||||
|
pkg-config
|
||||||
|
];
|
||||||
|
|
||||||
|
buildInputs = [
|
||||||
|
gcr
|
||||||
|
glib
|
||||||
|
gnome-desktop
|
||||||
|
gtk3
|
||||||
|
libgudev
|
||||||
|
libjson
|
||||||
|
json-glib
|
||||||
|
libhandy
|
||||||
|
networkmanager
|
||||||
|
linux-pam
|
||||||
|
systemd
|
||||||
|
upower
|
||||||
|
wayland
|
||||||
|
libxkbcommon
|
||||||
|
];
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
meson
|
||||||
|
ninja
|
||||||
|
pkg-config
|
||||||
|
python3
|
||||||
|
glib
|
||||||
|
wayland-scanner
|
||||||
|
wrapGAppsHook
|
||||||
|
];
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
description = "Greetd-compatible greeter for mobile phones";
|
||||||
|
homepage = "https://gitlab.com/mobian1/phog/";
|
||||||
|
license = licenses.gpl3Only;
|
||||||
|
maintainers = with maintainers; [ matthewcroughan ];
|
||||||
|
};
|
||||||
|
}
|
31
pkgs/additional/phog/sway-compat.patch
Normal file
31
pkgs/additional/phog/sway-compat.patch
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
commit 86593b754405a194e749e424e27710aa08533853
|
||||||
|
Author: Colin <colin@uninsane.org>
|
||||||
|
Date: 2023-08-26 12:26:36 +0000
|
||||||
|
|
||||||
|
make phoc-specific wayland interface optional: zphoc_layer_shell_effects_v1
|
||||||
|
|
||||||
|
diff --git a/src/drag-surface.c b/src/drag-surface.c
|
||||||
|
index 0e1a371f..56f7a307 100644
|
||||||
|
--- a/src/drag-surface.c
|
||||||
|
+++ b/src/drag-surface.c
|
||||||
|
@@ -204,6 +204,7 @@ phog_drag_surface_configured (PhogLayerSurface *layer_surface)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Configure drag surface if not done yet */
|
||||||
|
+ g_return_if_fail(priv->layer_shell_effects);
|
||||||
|
priv->drag_surface = zphoc_layer_shell_effects_v1_get_draggable_layer_surface (priv->layer_shell_effects,
|
||||||
|
wl_layer_surface);
|
||||||
|
zphoc_draggable_layer_surface_v1_add_listener (priv->drag_surface, &drag_surface_listener, self);
|
||||||
|
diff --git a/src/phog-wayland.c b/src/phog-wayland.c
|
||||||
|
index 99933116..7c2d76ad 100644
|
||||||
|
--- a/src/phog-wayland.c
|
||||||
|
+++ b/src/phog-wayland.c
|
||||||
|
@@ -274,7 +274,7 @@ phog_wayland_constructed (GObject *object)
|
||||||
|
!self->input_inhibit_manager || !self->xdg_wm_base ||
|
||||||
|
!self->zxdg_output_manager_v1 ||
|
||||||
|
!self->zphoc_layer_shell_effects_v1) {
|
||||||
|
- g_error ("Wayland compositor lacks needed globals\n"
|
||||||
|
+ g_warning ("Wayland compositor lacks needed globals\n"
|
||||||
|
"outputs: %d, layer_shell: %p, idle_manager: %p, "
|
||||||
|
"inhibit: %p, xdg_wm: %p, "
|
||||||
|
"xdg_output: %p, wlr_output_manager: %p, "
|
@@ -191,6 +191,12 @@ let
|
|||||||
src = ./src;
|
src = ./src;
|
||||||
pkgs = [ "rsync" ];
|
pkgs = [ "rsync" ];
|
||||||
};
|
};
|
||||||
|
sync-music = static-nix-shell.mkPython3Bin {
|
||||||
|
pname = "sane-sync-music";
|
||||||
|
src = ./src;
|
||||||
|
pkgs = [ "ffmpeg" "sox" ];
|
||||||
|
pyPkgs = [ "unidecode" ];
|
||||||
|
};
|
||||||
vpn-down = static-nix-shell.mkBash {
|
vpn-down = static-nix-shell.mkBash {
|
||||||
pname = "sane-vpn-down";
|
pname = "sane-vpn-down";
|
||||||
src = ./src;
|
src = ./src;
|
||||||
|
@@ -23,9 +23,13 @@ options:
|
|||||||
# - Torznab: <https://torznab.github.io/spec-1.3-draft/index.html>
|
# - Torznab: <https://torznab.github.io/spec-1.3-draft/index.html>
|
||||||
# - TorrentPotato: <https://github.com/RuudBurger/CouchPotatoServer/wiki/Couchpotato-torrent-provider>
|
# - TorrentPotato: <https://github.com/RuudBurger/CouchPotatoServer/wiki/Couchpotato-torrent-provider>
|
||||||
# - its own JSON-based API
|
# - its own JSON-based API
|
||||||
|
#
|
||||||
|
# about torrent jargon:
|
||||||
|
# - <https://en.wikipedia.org/wiki/Pirated_movie_release_types>
|
||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
import natsort
|
import natsort
|
||||||
@@ -66,9 +70,31 @@ def parse_time(t: str) -> datetime:
|
|||||||
return try_parse_time(t).astimezone() or epoch
|
return try_parse_time(t).astimezone() or epoch
|
||||||
|
|
||||||
|
|
||||||
|
# preference, best to worst
|
||||||
|
TRACKER_RANKS = [
|
||||||
|
'bakabt',
|
||||||
|
'nyaa.si',
|
||||||
|
'yts',
|
||||||
|
'internet archive',
|
||||||
|
'the pirate bay',
|
||||||
|
# haven't sorted these
|
||||||
|
'1337x',
|
||||||
|
'kickasstorrents.to',
|
||||||
|
]
|
||||||
|
def tracker_rank(tracker: str):
|
||||||
|
if tracker.lower() in TRACKER_RANKS:
|
||||||
|
return TRACKER_RANKS.index(tracker.lower())
|
||||||
|
logger.warn(f"unknown tracker: {tracker!r}")
|
||||||
|
return len(TRACKER_RANKS)
|
||||||
|
|
||||||
DROP_CATS = { "dvd", "hd", "misc", "other", "sd", "uhd" }
|
DROP_CATS = { "dvd", "hd", "misc", "other", "sd", "uhd" }
|
||||||
MANGA_CATS = { "books", "comics", "ebook" }
|
MANGA_CATS = { "books", "comics", "ebook" }
|
||||||
KNOWN_CATS = frozenset(list(MANGA_CATS) + ["anime", "audio", "movies", "tv", "xxx"])
|
VIDEO_CATS = { "anime", "movies", "tv" }
|
||||||
|
KNOWN_CATS = frozenset(
|
||||||
|
list(MANGA_CATS) +
|
||||||
|
list(VIDEO_CATS) +
|
||||||
|
["audio", "xxx"]
|
||||||
|
)
|
||||||
def clean_cat(c: str) -> str | None:
|
def clean_cat(c: str) -> str | None:
|
||||||
if c in DROP_CATS: return None
|
if c in DROP_CATS: return None
|
||||||
return c
|
return c
|
||||||
@@ -83,6 +109,38 @@ def is_cat(cats: list[str], wanted_cats: list[str], default: bool = False) -> bo
|
|||||||
else:
|
else:
|
||||||
return any(c in wanted_cats for c in cats)
|
return any(c in wanted_cats for c in cats)
|
||||||
|
|
||||||
|
class Filter:
|
||||||
|
def __init__(self, h265: bool=False, manga: bool=False, video: bool=False):
|
||||||
|
self.h265 = h265
|
||||||
|
self.manga = manga
|
||||||
|
self.video = video
|
||||||
|
|
||||||
|
def filter(self, torrents: list['Torrent']) -> list['Torrent']:
|
||||||
|
return [t for t in torrents if self.is_match(t)]
|
||||||
|
|
||||||
|
def is_match(self, t: 'Torrent', default: bool = False) -> bool:
|
||||||
|
valid = True
|
||||||
|
valid = valid and (not self.h265 or self.is_h265(t))
|
||||||
|
valid = valid and (not self.manga or self.is_manga(t, default))
|
||||||
|
valid = valid and (not self.video or self.is_video(t, default))
|
||||||
|
return valid
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def is_h265(t: 'Torrent') -> bool:
|
||||||
|
meta = t.title.lower()
|
||||||
|
return "h265" in meta \
|
||||||
|
or "x265" in meta \
|
||||||
|
or "HEVC" in meta
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def is_manga(t: 'Torrent', default: bool = False) -> bool:
|
||||||
|
return is_cat(t.categories, MANGA_CATS, default)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def is_video(t: 'Torrent', default: bool = False) -> bool:
|
||||||
|
return is_cat(t.categories, VIDEO_CATS, default)
|
||||||
|
|
||||||
|
|
||||||
@dataclass(eq=True, order=True, unsafe_hash=True)
|
@dataclass(eq=True, order=True, unsafe_hash=True)
|
||||||
class Torrent:
|
class Torrent:
|
||||||
seeders: int
|
seeders: int
|
||||||
@@ -151,15 +209,6 @@ class Torrent:
|
|||||||
magnet=self.magnet,
|
magnet=self.magnet,
|
||||||
)
|
)
|
||||||
|
|
||||||
def is_manga(self, default: bool = False) -> bool:
|
|
||||||
return is_cat(self.categories, MANGA_CATS, default)
|
|
||||||
|
|
||||||
def is_h265(self) -> bool:
|
|
||||||
meta = self.title.lower()
|
|
||||||
return "h265" in meta \
|
|
||||||
or "x265" in meta \
|
|
||||||
or "HEVC" in meta
|
|
||||||
|
|
||||||
class Client:
|
class Client:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.apikey = open("/run/secrets/jackett_apikey").read().strip()
|
self.apikey = open("/run/secrets/jackett_apikey").read().strip()
|
||||||
@@ -182,80 +231,55 @@ class Client:
|
|||||||
|
|
||||||
return sorted(torrents, reverse=True)
|
return sorted(torrents, reverse=True)
|
||||||
|
|
||||||
|
def sort_results(torrents: list[Torrent], by: str) -> list[Torrent]:
|
||||||
|
if by == 'seeders':
|
||||||
|
return sorted(torrents, key=lambda t: (t.seeders, t), reverse=True)
|
||||||
|
elif by == 'tracker':
|
||||||
|
return sorted(torrents, key=lambda t: (-tracker_rank(t.tracker), t), reverse=True)
|
||||||
|
assert False, f"unknown sort method: {by}"
|
||||||
|
|
||||||
def filter_results(results: list[Torrent], full: bool, top: int, manga: bool, h265: bool) -> list[Torrent]:
|
def format_results(all_results: list[Torrent], filtered_results: list[Torrent], json: bool):
|
||||||
"""
|
if json:
|
||||||
take the complete query and filter further based on CLI options
|
dumpable = [t.to_dict() for t in filtered_results]
|
||||||
"""
|
print(json.dumps(dumpable))
|
||||||
if manga:
|
else:
|
||||||
results = [t for t in results if t.is_manga(default=True)]
|
num_total = len(all_results)
|
||||||
if h265:
|
num_filtered = len(filtered_results)
|
||||||
results = [t for t in results if t.is_h265()]
|
print(f"found {num_total} result(s) filtered to {num_filtered}")
|
||||||
if not full:
|
for r in filtered_results:
|
||||||
results = results[:top]
|
print(r)
|
||||||
return results
|
|
||||||
|
|
||||||
def parse_args(args: list[str]) -> dict:
|
|
||||||
options = dict(
|
|
||||||
full=False,
|
|
||||||
help=False,
|
|
||||||
json=False,
|
|
||||||
query="",
|
|
||||||
top="5",
|
|
||||||
verbose=False,
|
|
||||||
manga=False,
|
|
||||||
h265=False,
|
|
||||||
)
|
|
||||||
while args:
|
|
||||||
arg = args[0]
|
|
||||||
del args[0]
|
|
||||||
if arg.startswith('--'):
|
|
||||||
opt = arg[2:]
|
|
||||||
if "=" in opt:
|
|
||||||
name, val = opt.split('=')
|
|
||||||
else:
|
|
||||||
name, val = opt, True
|
|
||||||
options[name] = val
|
|
||||||
else:
|
|
||||||
options["query"] = options["query"] + " " + arg if options["query"] else arg
|
|
||||||
|
|
||||||
return options
|
|
||||||
|
|
||||||
def main(args: list[str]):
|
def main(args: list[str]):
|
||||||
logging.basicConfig()
|
logging.basicConfig()
|
||||||
options = parse_args(args)
|
logging.getLogger().setLevel(logging.WARNING)
|
||||||
full = options.pop("full")
|
|
||||||
help = options.pop("help")
|
|
||||||
json = options.pop("json")
|
|
||||||
query = options.pop("query")
|
|
||||||
assert options.get("top") is not True, "use `--top=N`, not `--top N`"
|
|
||||||
top = int(options.pop("top"))
|
|
||||||
verbose = options.pop("verbose")
|
|
||||||
manga = options.pop("manga")
|
|
||||||
h265 = options.pop("h265")
|
|
||||||
|
|
||||||
if options != {}:
|
parser = argparse.ArgumentParser(description='search torrent trackers')
|
||||||
raise BadCliArgs(f"unexpected options: {options}")
|
parser.add_argument('--full', action='store_true', help='show all results')
|
||||||
if help:
|
parser.add_argument('--top', help='how many results to show (default: 5)')
|
||||||
raise BadCliArgs()
|
parser.add_argument('--sort-by', default='seeders', help='how to rank matches (seeders, tracker)')
|
||||||
|
parser.add_argument('--json', action='store_true', help='output results in json')
|
||||||
|
parser.add_argument('--verbose', action='store_true')
|
||||||
|
parser.add_argument('--h265', action='store_true', help='show only H.265/HEVC results (might cause false negatives)')
|
||||||
|
parser.add_argument('--manga', action='store_true', help='show only manga results')
|
||||||
|
parser.add_argument('--video', action='store_true', help='show only video (tv or film)')
|
||||||
|
parser.add_argument("query", help="text to search for in torrent titles/descriptions")
|
||||||
|
|
||||||
if verbose:
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.verbose:
|
||||||
logging.getLogger().setLevel(logging.DEBUG)
|
logging.getLogger().setLevel(logging.DEBUG)
|
||||||
|
|
||||||
|
|
||||||
client = Client()
|
client = Client()
|
||||||
results = client.query(query)
|
all_results = client.query(args.query)
|
||||||
num_results = len(results)
|
|
||||||
|
|
||||||
results = filter_results(results, full, top, manga, h265)
|
filter = Filter(h265=args.h265, manga=args.manga, video=args.video)
|
||||||
|
filtered_results = filter.filter(all_results)
|
||||||
|
ordered_results = sort_results(filtered_results, args.sort_by)
|
||||||
|
|
||||||
if json:
|
if not args.full:
|
||||||
dumpable = [t.to_dict() for t in results]
|
ordered_results = ordered_results[:int(args.top or "5")]
|
||||||
print(json.dumps(dumpable))
|
|
||||||
else:
|
format_results(all_results, ordered_results, args.json)
|
||||||
print(f"found {num_results} result(s)")
|
|
||||||
for r in results:
|
|
||||||
print(r)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main(sys.argv[1:])
|
main(sys.argv[1:])
|
||||||
|
@@ -1,11 +1,13 @@
|
|||||||
#!/usr/bin/env nix-shell
|
#!/usr/bin/env nix-shell
|
||||||
#!nix-shell -i bash -p systemd
|
#!nix-shell -i bash -p systemd
|
||||||
sudo systemctl stop matrix-appservice-irc mx-puppet-discord
|
sudo systemctl stop matrix-appservice-irc mx-puppet-discord mautrix-signal signald
|
||||||
sudo systemctl stop pleroma gitea matrix-synapse jellyfin transmission jackett
|
sudo systemctl stop ejabberd gitea lemmy-ui matrix-synapse pict-rs pleroma
|
||||||
sudo systemctl stop ejabberd goaccess i2p kiwix-serve navidrome
|
sudo systemctl stop dovecot2 opendkin postfix
|
||||||
|
sudo systemctl stop i2p jackett transmission
|
||||||
|
sudo systemctl stop jellyfin kiwix-serve komga navidrome
|
||||||
|
sudo systemctl stop goaccess
|
||||||
# TODO: stop the freshrss timer
|
# TODO: stop the freshrss timer
|
||||||
sudo systemctl stop phpfpm-freshrss
|
sudo systemctl stop phpfpm-freshrss
|
||||||
sudo systemctl stop dovecot2 opendkin postfix
|
|
||||||
sudo systemctl stop nginx
|
sudo systemctl stop nginx
|
||||||
sudo systemctl stop postgresql
|
sudo systemctl stop postgresql
|
||||||
sudo systemctl stop duplicity.timer
|
sudo systemctl stop duplicity.timer
|
||||||
|
204
pkgs/additional/sane-scripts/src/sane-sync-music
Executable file
204
pkgs/additional/sane-scripts/src/sane-sync-music
Executable file
@@ -0,0 +1,204 @@
|
|||||||
|
#!/usr/bin/env nix-shell
|
||||||
|
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ps.unidecode ])" -p ffmpeg -p sox
|
||||||
|
# vim: set filetype=python :
|
||||||
|
import argparse
|
||||||
|
import concurrent.futures
|
||||||
|
import logging
|
||||||
|
import multiprocessing
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
from unidecode import unidecode
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
MAKE_MP3 = [
|
||||||
|
'.flac',
|
||||||
|
'.oga',
|
||||||
|
'.ogg',
|
||||||
|
'.opus',
|
||||||
|
'.wav',
|
||||||
|
'.wma',
|
||||||
|
]
|
||||||
|
COPY_RAW = [
|
||||||
|
'.aac',
|
||||||
|
'.bmp',
|
||||||
|
'.gif',
|
||||||
|
'.jpeg',
|
||||||
|
'.jpg',
|
||||||
|
'.m4a',
|
||||||
|
'.mp3',
|
||||||
|
'.png',
|
||||||
|
]
|
||||||
|
IGNORE = [
|
||||||
|
'.DS_Store',
|
||||||
|
'.avi',
|
||||||
|
'.cue',
|
||||||
|
'.inf',
|
||||||
|
'.log',
|
||||||
|
'.lyrics',
|
||||||
|
'.m3u',
|
||||||
|
'.mov',
|
||||||
|
'.mp4',
|
||||||
|
'.nsf_',
|
||||||
|
'.pdf',
|
||||||
|
'.toc',
|
||||||
|
'.txt',
|
||||||
|
'.webm',
|
||||||
|
]
|
||||||
|
|
||||||
|
class Encoder:
|
||||||
|
def __init__(self, dry_run: bool = False):
|
||||||
|
self.dry_run = dry_run
|
||||||
|
|
||||||
|
def check_output_no_sideeffect(self, args: list[str]) -> bytes:
|
||||||
|
return subprocess.check_output(args)
|
||||||
|
|
||||||
|
def check_output(self, args: list[str]) -> str:
|
||||||
|
if self.dry_run:
|
||||||
|
logger.debug("not invoking because dry run: " + ' '.join(args))
|
||||||
|
return b""
|
||||||
|
else:
|
||||||
|
return subprocess.check_output(args)
|
||||||
|
|
||||||
|
def cp(self, source: Path, dest: Path) -> None:
|
||||||
|
self.check_output(['cp', str(source), str(dest)])
|
||||||
|
|
||||||
|
def ensure_dir(self, dir: Path) -> None:
|
||||||
|
if self.dry_run:
|
||||||
|
logger.debug(f"not invoking because dry run: os.makedirs({dir!r}, exist_ok=True)")
|
||||||
|
|
||||||
|
else:
|
||||||
|
os.makedirs(str(dir), exist_ok=True)
|
||||||
|
|
||||||
|
def remove(self, path: Path) -> None:
|
||||||
|
if self.dry_run:
|
||||||
|
logger.debug(f"not invoking because dry run: os.remove({path!r})")
|
||||||
|
else:
|
||||||
|
os.remove(path)
|
||||||
|
|
||||||
|
def convert(self, source: Path, dest: Path) -> None:
|
||||||
|
source_samplerate = None
|
||||||
|
try:
|
||||||
|
source_samplerate = int(self.check_output_no_sideeffect(['soxi', '-r', str(source)]).decode("utf-8").strip())
|
||||||
|
except:
|
||||||
|
if str(source).endswith('.wma'):
|
||||||
|
logging.debug(f'unsupported extension for samplerate: {source}')
|
||||||
|
else:
|
||||||
|
logging.warning(f'unable to obtain samplerate for {source}')
|
||||||
|
|
||||||
|
samplerate_map = {
|
||||||
|
192000: 48000,
|
||||||
|
96000: 48000,
|
||||||
|
88200: 44100,
|
||||||
|
# preserve as-is
|
||||||
|
48000: 48000,
|
||||||
|
44100: 44100,
|
||||||
|
}
|
||||||
|
|
||||||
|
target_samplerate = samplerate_map.get(source_samplerate)
|
||||||
|
if source_samplerate and not target_samplerate:
|
||||||
|
logging.warning(f'unable to map source sample rate: {source_samplerate}')
|
||||||
|
samplerate_flags = ['-ar', str(target_samplerate)] if target_samplerate else []
|
||||||
|
|
||||||
|
self.check_output([
|
||||||
|
'ffmpeg',
|
||||||
|
'-i', str(source),
|
||||||
|
'-codec:v', 'copy',
|
||||||
|
'-codec:a', 'libmp3lame',
|
||||||
|
'-qscale:a', '0'
|
||||||
|
] + samplerate_flags + [str(dest)])
|
||||||
|
|
||||||
|
|
||||||
|
def clean_name(path: str) -> Path:
|
||||||
|
'''
|
||||||
|
transform a path into something which most filesystems/protocols can reliably support
|
||||||
|
'''
|
||||||
|
out_path = Path()
|
||||||
|
for part in path.parts:
|
||||||
|
blacklisted = '"\'!@#$%^&*()[]{};:,<>?`~|\\/'
|
||||||
|
part = unidecode(part)
|
||||||
|
part = ''.join(c for c in part if c not in blacklisted)
|
||||||
|
out_path /= part
|
||||||
|
return out_path
|
||||||
|
|
||||||
|
def target_name(source_name: str) -> Path:
|
||||||
|
n = clean_name(source_name)
|
||||||
|
if n.suffix in MAKE_MP3:
|
||||||
|
return Path(str(n) + '.mp3')
|
||||||
|
else:
|
||||||
|
return n
|
||||||
|
|
||||||
|
def calculate_delta(in_dir: str, out_dir: str) -> tuple[set[Path], set[Path]]:
|
||||||
|
'''
|
||||||
|
Returns the set of dest files which need to be deleted, followed by the files to copy
|
||||||
|
'''
|
||||||
|
in_files = { p.relative_to(in_dir) for p in Path(in_dir).rglob("*") if not p.is_dir() }
|
||||||
|
logger.info(f'found {len(in_files)} files in source')
|
||||||
|
existing_out_files = { p.relative_to(out_dir) for p in Path(out_dir).rglob("*") if not p.is_dir() }
|
||||||
|
logger.info(f'found {len(existing_out_files)} files in dest')
|
||||||
|
|
||||||
|
expected_out_files = { target_name(n) for n in in_files }
|
||||||
|
|
||||||
|
to_del = { f for f in existing_out_files if f not in expected_out_files }
|
||||||
|
logger.info(f'found {len(to_del)} files to delete')
|
||||||
|
to_copy = { f for f in in_files if target_name(f) not in existing_out_files and f.suffix not in IGNORE }
|
||||||
|
logger.info(f'found {len(to_copy)} files to copy')
|
||||||
|
|
||||||
|
return to_del, to_copy
|
||||||
|
|
||||||
|
def rm_dest_files(encoder: Encoder, out_dir: str, files: set[Path]) -> None:
|
||||||
|
for f in files:
|
||||||
|
logger.info(f'removing {f} because it does not exist on host')
|
||||||
|
encoder.remove(Path(out_dir) / f)
|
||||||
|
|
||||||
|
def copy_one(encoder: Encoder, source: Path, dest: Path) -> None:
|
||||||
|
encoder.ensure_dir(dest.parent)
|
||||||
|
if source.suffix in MAKE_MP3:
|
||||||
|
logger.debug(f'converting {source} -> {dest}')
|
||||||
|
encoder.convert(source, dest)
|
||||||
|
elif source.suffix in COPY_RAW:
|
||||||
|
logger.debug(f'copying {source} -> {dest}')
|
||||||
|
encoder.cp(source, dest)
|
||||||
|
else:
|
||||||
|
logger.warning(f"skipping {source} because I don't know what to do with that file type")
|
||||||
|
|
||||||
|
def cp_src_files(encoder: Encoder, in_dir: Path, out_dir: Path, src_names: set[Path], jobs: int):
|
||||||
|
logger.info(f'using {jobs} jobs to copy {len(src_names)} files')
|
||||||
|
# Parallel(n_jobs=jobs)(delayed(copy_one)(encoder, in_dir / n, out_dir / target_name(n)) for n in src_names)
|
||||||
|
with concurrent.futures.ThreadPoolExecutor(max_workers=jobs) as executor:
|
||||||
|
for n in src_names:
|
||||||
|
executor.submit(copy_one, encoder, in_dir / n, out_dir / target_name(n))
|
||||||
|
|
||||||
|
|
||||||
|
def sync_all(in_dir: str, out_dir: str, jobs: int = None, dry_run: bool = False) -> None:
|
||||||
|
encoder = Encoder(dry_run=dry_run)
|
||||||
|
to_del, to_copy = calculate_delta(in_dir, out_dir)
|
||||||
|
|
||||||
|
rm_dest_files(encoder, out_dir, to_del)
|
||||||
|
cp_src_files(encoder, in_dir, out_dir, to_copy, jobs = jobs or multiprocessing.cpu_count())
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
logging.basicConfig()
|
||||||
|
logger.setLevel(logging.INFO)
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description="synchronize music from one directory to another, possibly compressing it")
|
||||||
|
parser.add_argument("src", help="source directory")
|
||||||
|
parser.add_argument("dest", help="destination directory")
|
||||||
|
parser.add_argument("--jobs", help="number of cores to compress music with (default: all CPU cores)", default=None, type=int)
|
||||||
|
parser.add_argument("--dry-run", action='store_true', help="don't actually run any commands")
|
||||||
|
parser.add_argument("--verbose", action='store_true', help="more logging")
|
||||||
|
parser.add_argument("--quiet", action='store_true', help="less logging")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.verbose:
|
||||||
|
logger.setLevel(logging.DEBUG)
|
||||||
|
if args.quiet:
|
||||||
|
logger.setLevel(logging.WARN)
|
||||||
|
|
||||||
|
sync_all(args.src, args.dest, args.jobs, args.dry_run)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
36
pkgs/additional/sane-weather/default.nix
Normal file
36
pkgs/additional/sane-weather/default.nix
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
{ stdenv
|
||||||
|
, glib-networking
|
||||||
|
, gobject-introspection
|
||||||
|
, libgweather
|
||||||
|
, python3
|
||||||
|
, wrapGAppsNoGuiHook
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
pyEnv = python3.withPackages (ps: [
|
||||||
|
ps.pygobject3
|
||||||
|
]);
|
||||||
|
in
|
||||||
|
stdenv.mkDerivation {
|
||||||
|
pname = "sane-weather";
|
||||||
|
version = "0.1";
|
||||||
|
src = ./.;
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
gobject-introspection
|
||||||
|
wrapGAppsNoGuiHook
|
||||||
|
];
|
||||||
|
|
||||||
|
buildInputs = [
|
||||||
|
glib-networking
|
||||||
|
libgweather
|
||||||
|
pyEnv
|
||||||
|
];
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
mkdir -p "$out/bin"
|
||||||
|
cp sane-weather "$out/bin"
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
}
|
195
pkgs/additional/sane-weather/sane-weather
Executable file
195
pkgs/additional/sane-weather/sane-weather
Executable file
@@ -0,0 +1,195 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# to get GWeather logging, run with
|
||||||
|
# `G_MESSAGES_DEBUG=GWeather`
|
||||||
|
|
||||||
|
# queries weather from public (gov) sources and renders it to stdout.
|
||||||
|
# primary consumer is conky.
|
||||||
|
# very limited; libgweather is a little iffy and doesn't expose everything the raw APIs do
|
||||||
|
# e.g. no precise precipitation predictions.
|
||||||
|
#
|
||||||
|
# future work:
|
||||||
|
# - consider using python-native pynws: <https://github.com/MatthewFlamm/pynws>
|
||||||
|
# - it's well-factored, exposing a nice interface but letting me dig as deep as i want wherever that's incomplete.
|
||||||
|
# - render a graph with rain + temperature forecast
|
||||||
|
# - conky supports graphs with [execgraph](https://conky.cc/variables#execgraph)
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import code
|
||||||
|
import gi
|
||||||
|
import logging
|
||||||
|
import time
|
||||||
|
|
||||||
|
gi.require_version('GWeather', '4.0')
|
||||||
|
|
||||||
|
from gi.repository import GLib
|
||||||
|
from gi.repository import GWeather
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class WeatherSource:
|
||||||
|
'''
|
||||||
|
this class abstracts operations which would query a remote weather server
|
||||||
|
'''
|
||||||
|
def __init__(self):
|
||||||
|
self.info = GWeather.Info()
|
||||||
|
self.info.set_application_id('org.uninsane.sane-weather')
|
||||||
|
self.info.set_contact_info('contact@uninsane.org')
|
||||||
|
|
||||||
|
self.info.set_enabled_providers(
|
||||||
|
# defaults to METAR | IWIN.
|
||||||
|
# options are:
|
||||||
|
# - IWIN # graphical.weather.gov; provides daily min/max temp, precipitation
|
||||||
|
# - METAR # aviationweather.gov; provides current time, wind, visibility, conditions, clouds, temperature, pressure
|
||||||
|
# - MET_NO
|
||||||
|
# - NWS # api.weather.gov; provides hourly temperature, dewpoint, humidity, sky cover, wind, precipitation, snow; daily min/max temp,
|
||||||
|
# - OWM
|
||||||
|
# METAR, if you only want immediate conditions
|
||||||
|
GWeather.Provider.METAR
|
||||||
|
# METAR + NWS, if you want a forecast
|
||||||
|
# GWeather.Provider.METAR | GWeather.Provider.NWS
|
||||||
|
)
|
||||||
|
self.world = GWeather.Location.get_world()
|
||||||
|
|
||||||
|
def query_loc(self, loc: GWeather.Location) -> None:
|
||||||
|
'''
|
||||||
|
query the weather for some location, asynchronously.
|
||||||
|
after calling, poll the `try_...` methods to check for results.
|
||||||
|
'''
|
||||||
|
logger.debug(f"querying: {loc.get_coords()}")
|
||||||
|
self.info.set_location(loc)
|
||||||
|
self.info.update()
|
||||||
|
|
||||||
|
def try_get_celcius(self) -> float | None:
|
||||||
|
valid, temp = self.info.get_value_temp(GWeather.TemperatureUnit.CENTIGRADE)
|
||||||
|
logger.debug(f"try_get_celcius: valid={valid}, temp={temp}")
|
||||||
|
if not valid: temp = None
|
||||||
|
|
||||||
|
return temp
|
||||||
|
|
||||||
|
# potentially interesting methods on GWeather.Info:
|
||||||
|
# - get_conditions # returns '-'
|
||||||
|
# - get_forecast_list # forecast as a list of GWeather.Info instances (daily if IWIN; hourly if NWS)
|
||||||
|
# - get_sky # like 'Clear sky'
|
||||||
|
# - get_sunrise, get_sunset # like '13∶10', '03∶04' (utc time)
|
||||||
|
# - get_symbolic_icon_name # like 'weather-clear-night-symbolic'
|
||||||
|
# - get_temp_min, get_temp_max # returns '-'
|
||||||
|
# - get_temp_summary() # same as get_temp()
|
||||||
|
# - get_update() # like 'Thu, Aug 24 / 13∶00'
|
||||||
|
# - get_wind() # like 'North / 13.0 km/h'
|
||||||
|
# - get_visibility() # like '16093m'
|
||||||
|
# - get_weather_summary() # like 'Seattle-Tacoma International Airport: Clear sky'
|
||||||
|
|
||||||
|
|
||||||
|
class TopLevel:
|
||||||
|
"""
|
||||||
|
this class acts as the "event loop" which glib apps expect.
|
||||||
|
caller sets up a "work queue" of everything they want to do, then calls `run`.
|
||||||
|
glib calls `poll` in a loop, and each time we try to work through another item in the work_queue.
|
||||||
|
when the work_queue is empty, exit glib's main loop & return to the caller (from `run`).
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
self._loop = GLib.MainLoop()
|
||||||
|
self.source = WeatherSource()
|
||||||
|
self.work_queue = []
|
||||||
|
|
||||||
|
def enqueue(self, op) -> None:
|
||||||
|
self.work_queue.append(op)
|
||||||
|
|
||||||
|
def run(self) -> None:
|
||||||
|
self.enqueue(ExitOp())
|
||||||
|
GLib.idle_add(self.poll)
|
||||||
|
self._loop.run()
|
||||||
|
|
||||||
|
def poll(self) -> bool:
|
||||||
|
work = self.work_queue[0]
|
||||||
|
if isinstance(work, QueryOp):
|
||||||
|
del self.work_queue[0]
|
||||||
|
self.source.query_loc(work.loc)
|
||||||
|
elif isinstance(work, PrintTempOp):
|
||||||
|
temp = self.source.try_get_celcius()
|
||||||
|
if temp is not None:
|
||||||
|
del self.work_queue[0]
|
||||||
|
print(f"{int(temp)}°C")
|
||||||
|
elif isinstance(work, DiagnosticsOp):
|
||||||
|
del self.work_queue[0]
|
||||||
|
# GWeather does transparent caching so that we don't usually hit the web
|
||||||
|
last_update = self.source.info.get_update()
|
||||||
|
logger.debug(f"last update: {last_update}")
|
||||||
|
elif isinstance(work, ExitOp):
|
||||||
|
logger.debug("quitting GLib MainLoop")
|
||||||
|
self.source.info.store_cache()
|
||||||
|
self._loop.quit()
|
||||||
|
elif isinstance(work, IdleOp):
|
||||||
|
del self.work_queue[0]
|
||||||
|
logger.debug("micro sleep")
|
||||||
|
time.sleep(0.1)
|
||||||
|
else:
|
||||||
|
assert False, f"unknown work: {work}"
|
||||||
|
|
||||||
|
# micro sleep so we don't peg CPU
|
||||||
|
# TODO: i'm sure there's a better way than all of this
|
||||||
|
time.sleep(0.05)
|
||||||
|
# re-queue this idle fn
|
||||||
|
return True
|
||||||
|
|
||||||
|
# operations:
|
||||||
|
# think of these as public methods on the `TopLevel` class,
|
||||||
|
# except abstracted as values for the sake of glib's event loop.
|
||||||
|
class QueryOp:
|
||||||
|
def __init__(self, loc: GWeather.Location):
|
||||||
|
self.loc = loc
|
||||||
|
|
||||||
|
class PrintTempOp:
|
||||||
|
pass
|
||||||
|
|
||||||
|
class DiagnosticsOp:
|
||||||
|
pass
|
||||||
|
|
||||||
|
class IdleOp:
|
||||||
|
pass
|
||||||
|
|
||||||
|
class ExitOp:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
logging.basicConfig()
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description="acquire weather information for user display")
|
||||||
|
parser.add_argument(
|
||||||
|
'--station-code',
|
||||||
|
default='KSEA',
|
||||||
|
help='4-letter METAR weather station code for where we want to know weather\n '
|
||||||
|
'to find your station see here: <https://aviationweather.gov/metar>'
|
||||||
|
)
|
||||||
|
parser.add_argument('--break-before', action='store_true', help='drop into a REPL before do anything (for debugging)')
|
||||||
|
parser.add_argument('--break-after', action='store_true', help='drop into a REPL after completing the work (for debugging)')
|
||||||
|
parser.add_argument('--verbose', action='store_true', help='enable verbose logging')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.verbose:
|
||||||
|
logger.setLevel(logging.DEBUG)
|
||||||
|
GLib.log_set_debug_enabled(True)
|
||||||
|
|
||||||
|
toplevel = TopLevel()
|
||||||
|
here = GWeather.Location.find_by_station_code(toplevel.source.world, args.station_code)
|
||||||
|
|
||||||
|
if args.break_before:
|
||||||
|
code.interact(local=dict(**globals(), **locals()))
|
||||||
|
|
||||||
|
toplevel.enqueue(QueryOp(here))
|
||||||
|
toplevel.enqueue(PrintTempOp())
|
||||||
|
toplevel.enqueue(DiagnosticsOp())
|
||||||
|
|
||||||
|
# for _ in range(300): # for debugging...
|
||||||
|
# toplevel.enqueue(IdleOp())
|
||||||
|
|
||||||
|
toplevel.run()
|
||||||
|
|
||||||
|
if args.break_after:
|
||||||
|
code.interact(local=dict(**globals(), **locals()))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
@@ -1,14 +1,19 @@
|
|||||||
{ pkgs
|
{ pkgs
|
||||||
|
, bash
|
||||||
, lib
|
, lib
|
||||||
, makeWrapper
|
, makeWrapper
|
||||||
, python3
|
, python3
|
||||||
, stdenv
|
, stdenv
|
||||||
|
, zsh
|
||||||
}:
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
inherit (builtins) attrNames attrValues concatStringsSep foldl' map typeOf;
|
inherit (builtins) attrNames attrValues concatStringsSep foldl' map typeOf;
|
||||||
inherit (lib) concatMapAttrs;
|
inherit (lib) concatMapAttrs;
|
||||||
|
bash' = bash;
|
||||||
pkgs' = pkgs;
|
pkgs' = pkgs;
|
||||||
|
python3' = python3;
|
||||||
|
zsh' = zsh;
|
||||||
# create an attrset of
|
# create an attrset of
|
||||||
# <name> = expected string in the nix-shell invocation
|
# <name> = expected string in the nix-shell invocation
|
||||||
# <value> = package to provide
|
# <value> = package to provide
|
||||||
@@ -74,33 +79,33 @@ in rec {
|
|||||||
);
|
);
|
||||||
|
|
||||||
# `mkShell` specialization for `nix-shell -i bash` scripts.
|
# `mkShell` specialization for `nix-shell -i bash` scripts.
|
||||||
mkBash = { pname, pkgs ? {}, srcPath ? pname, ...}@attrs:
|
mkBash = { pname, pkgs ? {}, srcPath ? pname, bash ? bash', ...}@attrs:
|
||||||
let
|
let
|
||||||
pkgsAsAttrs = pkgsToAttrs "" pkgs' pkgs;
|
pkgsAsAttrs = pkgsToAttrs "" pkgs' pkgs;
|
||||||
pkgsEnv = attrValues pkgsAsAttrs;
|
pkgsEnv = attrValues pkgsAsAttrs;
|
||||||
pkgExprs = attrNames pkgsAsAttrs;
|
pkgExprs = attrNames pkgsAsAttrs;
|
||||||
in mkShell ({
|
in mkShell ({
|
||||||
inherit pkgsEnv pkgExprs;
|
inherit pkgsEnv pkgExprs;
|
||||||
interpreter = "${pkgs'.bash}/bin/bash";
|
interpreter = "${bash}/bin/bash";
|
||||||
} // (removeAttrs attrs [ "pkgs" ])
|
} // (removeAttrs attrs [ "bash" "pkgs" ])
|
||||||
);
|
);
|
||||||
|
|
||||||
# `mkShell` specialization for `nix-shell -i zsh` scripts.
|
# `mkShell` specialization for `nix-shell -i zsh` scripts.
|
||||||
mkZsh = { pname, pkgs ? {}, srcPath ? pname, ...}@attrs:
|
mkZsh = { pname, pkgs ? {}, srcPath ? pname, zsh ? zsh', ...}@attrs:
|
||||||
let
|
let
|
||||||
pkgsAsAttrs = pkgsToAttrs "" pkgs' pkgs;
|
pkgsAsAttrs = pkgsToAttrs "" pkgs' pkgs;
|
||||||
pkgsEnv = attrValues pkgsAsAttrs;
|
pkgsEnv = attrValues pkgsAsAttrs;
|
||||||
pkgExprs = attrNames pkgsAsAttrs;
|
pkgExprs = attrNames pkgsAsAttrs;
|
||||||
in mkShell ({
|
in mkShell ({
|
||||||
inherit pkgsEnv pkgExprs;
|
inherit pkgsEnv pkgExprs;
|
||||||
interpreter = "${pkgs'.zsh}/bin/zsh";
|
interpreter = "${zsh}/bin/zsh";
|
||||||
} // (removeAttrs attrs [ "pkgs" ])
|
} // (removeAttrs attrs [ "pkgs" "zsh" ])
|
||||||
);
|
);
|
||||||
|
|
||||||
# `mkShell` specialization for invocations of `nix-shell -p "python3.withPackages (...)"`
|
# `mkShell` specialization for invocations of `nix-shell -p "python3.withPackages (...)"`
|
||||||
# pyPkgs argument is parsed the same as pkgs, except that names are assumed to be relative to `"ps"` if specified in list form.
|
# pyPkgs argument is parsed the same as pkgs, except that names are assumed to be relative to `"ps"` if specified in list form.
|
||||||
# TODO: rename to `mkPython3` for consistency with e.g. `mkBash`
|
# TODO: rename to `mkPython3` for consistency with e.g. `mkBash`
|
||||||
mkPython3Bin = { pname, pkgs ? {}, pyPkgs ? {}, srcPath ? pname, ... }@attrs:
|
mkPython3Bin = { pname, pkgs ? {}, pyPkgs ? {}, srcPath ? pname, python3 ? python3', ... }@attrs:
|
||||||
let
|
let
|
||||||
pyEnv = python3.withPackages (ps: attrValues (
|
pyEnv = python3.withPackages (ps: attrValues (
|
||||||
pkgsToAttrs "ps." ps pyPkgs
|
pkgsToAttrs "ps." ps pyPkgs
|
||||||
@@ -118,6 +123,6 @@ in rec {
|
|||||||
inherit pkgsEnv pkgExprs;
|
inherit pkgsEnv pkgExprs;
|
||||||
interpreter = pyEnv.interpreter;
|
interpreter = pyEnv.interpreter;
|
||||||
interpreterName = "python3";
|
interpreterName = "python3";
|
||||||
} // (removeAttrs attrs [ "pkgs" "pyPkgs" ])
|
} // (removeAttrs attrs [ "pkgs" "pyPkgs" "python3" ])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -1,24 +0,0 @@
|
|||||||
diff --git a/setup_config_version.sh b/setup_config_version.sh
|
|
||||||
index fde40c1..6386014 100755
|
|
||||||
--- a/setup_config_version.sh
|
|
||||||
+++ b/setup_config_version.sh
|
|
||||||
@@ -8,7 +8,7 @@ case "$1" in
|
|
||||||
exit
|
|
||||||
esac
|
|
||||||
|
|
||||||
-case "$(busybox head -n1 "$1")" in
|
|
||||||
+case "$(head -n1 "$1")" in
|
|
||||||
"#"*)
|
|
||||||
comment="#"
|
|
||||||
;;
|
|
||||||
@@ -23,7 +23,7 @@ case "$(busybox head -n1 "$1")" in
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
-busybox md5sum "$1" | \
|
|
||||||
- busybox cut -d" " -f1 | \
|
|
||||||
- busybox xargs -I{} busybox sed -i "2i$comment configversion: {}" \
|
|
||||||
+md5sum "$1" | \
|
|
||||||
+ cut -d" " -f1 | \
|
|
||||||
+ xargs -I{} sed -i "2i$comment configversion: {}" \
|
|
||||||
"$1"
|
|
@@ -1,58 +0,0 @@
|
|||||||
commit bf0057011777b91ef5af005fb4e984b4b9b71c7b
|
|
||||||
Author: Colin <colin@uninsane.org>
|
|
||||||
Date: 2023-07-15 21:35:45 +0000
|
|
||||||
|
|
||||||
sxmo_wmmenu: respect SXMO_WORKSPACE_WRAPPING
|
|
||||||
|
|
||||||
sxmo_wm.sh uses the `SXMO_WORKSPACE_WRAPPING` variable to control
|
|
||||||
relative movements. for example, set this to "5" and then the "Next
|
|
||||||
Workspace" option in the switch menu will cycle WS 1 -> 2 ... -> 5 -> 1.
|
|
||||||
same for one- and two-finger left/right swipe to switch/move workspaces.
|
|
||||||
|
|
||||||
however, absolute movements (via the move menu) only allowed moving to
|
|
||||||
WS 1-4. a user with non-default `SXMO_WORKSPACE_WRAPPING` could move a
|
|
||||||
window from WS 5 to WS 4 with this menu, but not from WS 4 back to WS 5.
|
|
||||||
this patch brings consistency by using `SXMO_WORKSPACE_WRAPPING`
|
|
||||||
anywhere we would otherwise assume the number of possible workspaces.
|
|
||||||
|
|
||||||
diff --git a/scripts/core/sxmo_wmmenu.sh b/scripts/core/sxmo_wmmenu.sh
|
|
||||||
index 3d40b31..d3c1db6 100755
|
|
||||||
--- a/scripts/core/sxmo_wmmenu.sh
|
|
||||||
+++ b/scripts/core/sxmo_wmmenu.sh
|
|
||||||
@@ -12,6 +12,12 @@
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
+_movetowssubmenu() {
|
|
||||||
+ for ws in $(seq "${SXMO_WORKSPACE_WRAPPING:-4}"); do
|
|
||||||
+ printf "%s Move to WS %s\n" "$ws" "$ws"
|
|
||||||
+ done
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
# A menu which allows to move windows or toggle floating.
|
|
||||||
swaymovemenu() {
|
|
||||||
CHOICES="$(cat <<EOF
|
|
||||||
@@ -22,10 +28,7 @@ $icon_arl Move Left
|
|
||||||
$icon_arr Move Right
|
|
||||||
$icon_wn2 Toggle Floating
|
|
||||||
$icon_ac1 Move Scratchpad
|
|
||||||
-1 Move to WS 1
|
|
||||||
-2 Move to WS 2
|
|
||||||
-3 Move to WS 3
|
|
||||||
-4 Move to WS 4
|
|
||||||
+$(_movetowssubmenu)
|
|
||||||
EOF
|
|
||||||
)"
|
|
||||||
|
|
||||||
@@ -125,10 +128,7 @@ dwmwmmenu() {
|
|
||||||
CHOICES="$(
|
|
||||||
cat <<EOF
|
|
||||||
$icon_cls Close Menu
|
|
||||||
-1 Move to WS 1
|
|
||||||
-2 Move to WS 2
|
|
||||||
-3 Move to WS 3
|
|
||||||
-4 Move to WS 4
|
|
||||||
+$(_movetowssubmenu)
|
|
||||||
$icon_rld Shift stack
|
|
||||||
$icon_grd Toggle Layout
|
|
||||||
EOF
|
|
@@ -1,56 +0,0 @@
|
|||||||
diff --git a/configs/default_hooks/sxmo_hook_apps.sh b/configs/default_hooks/sxmo_hook_apps.sh
|
|
||||||
index ba70a31..9f5a129 100755
|
|
||||||
--- a/configs/default_hooks/sxmo_hook_apps.sh
|
|
||||||
+++ b/configs/default_hooks/sxmo_hook_apps.sh
|
|
||||||
@@ -31,6 +31,7 @@ write_line_app audacity "$icon_mic Audacity" "audacity"
|
|
||||||
write_line_app gnome-calculator "$icon_clc Calculator" "gnome-calculator"
|
|
||||||
write_line_app calcurse "$icon_clk Calcurse" "sxmo_terminal.sh calcurse"
|
|
||||||
write_line_app cmus "$icon_mus Cmus" "sxmo_terminal.sh cmus"
|
|
||||||
+write_line_app cozy "$icon_mus Cozy" "com.github.geigi.cozy"
|
|
||||||
write_line_app dino "$icon_msg Dino" "GDK_SCALE=1 dino"
|
|
||||||
write_line_app dolphin "$icon_dir Dolphin" "dolphin"
|
|
||||||
write_line_app emacs "$icon_edt Emacs (Terminal)" "sxmo_terminal.sh emacs -nw"
|
|
||||||
@@ -54,19 +55,25 @@ write_line_app giara "$icon_red Giara" "giara"
|
|
||||||
write_line_app gnome-chess "$icon_chs Gnome Chess" "gnome-chess"
|
|
||||||
write_line_app gomuks "$icon_msg Gomuks" "sxmo_terminal.sh gomuks"
|
|
||||||
write_line_app gpodder "$icon_rss gPodder" "gpodder"
|
|
||||||
+write_line_app gthumb "$icon_img gThumb" "gthumb"
|
|
||||||
write_line_app gucharmap "$icon_inf Gucharmap" "gucharmap"
|
|
||||||
write_line_app hexchat "$icon_msg Hexchat" "hexchat"
|
|
||||||
write_line_app htop "$icon_cfg Htop" "sxmo_terminal.sh htop"
|
|
||||||
write_line_app irssi "$icon_msg Irssi" "sxmo_terminal.sh irssi"
|
|
||||||
write_line_app ii "$icon_msg Ii" "sxmo_terminal.sh ii"
|
|
||||||
write_line_app ipython "$icon_trm IPython" "sxmo_terminal.sh ipython"
|
|
||||||
+write_line_app jellyfinmediaplayer "$icon_mvi Jellyfin" "jellyfinmediaplayer"
|
|
||||||
write_line_app kasts "$icon_rss Kasts" "kasts"
|
|
||||||
write_line_app kmail "$icon_eml KMail" "kmail"
|
|
||||||
+write_line_app komikku "$icon_bok Komikku" "komikku"
|
|
||||||
write_line_app kontact "$icon_msg Kontact" "kontact"
|
|
||||||
write_line_app konversation "$icon_msg Konversation" "konversation"
|
|
||||||
+write_line_app koreader "$icon_bok KOReader" "koreader"
|
|
||||||
write_line_app kwrite "$icon_edt Kwrite" "kwrite"
|
|
||||||
write_line_app lagrange "$icon_glb Lagrange" "lagrange"
|
|
||||||
+write_line_app lemoa "$icon_grp Lemoa" "lemoa"
|
|
||||||
write_line_app lf "$icon_dir Lf" "sxmo_terminal.sh lf"
|
|
||||||
+write_line_app librewolf "$icon_glb Librewolf" "librewolf"
|
|
||||||
write_line_app lollypop "$icon_mus Lollypop" "lollypop"
|
|
||||||
write_line_app luakit "$icon_glb Luakit" "luakit"
|
|
||||||
write_line_app marble "$icon_map Marble" "marble"
|
|
||||||
@@ -97,6 +104,7 @@ write_line_app senpai "$icon_msg Senpai" "sxmo_terminal.sh senpai"
|
|
||||||
write_line_app sic "$icon_msg Sic" "sxmo_terminal.sh sic"
|
|
||||||
([ "$SXMO_WM" = dwm ] && command -v st >/dev/null) && \
|
|
||||||
write_line "$icon_trm St" "st -e $SHELL"
|
|
||||||
+write_line_app sublime-music "$icon_mus Sublime Music" "sublime-music"
|
|
||||||
write_line_app surf "$icon_glb Surf" "surf"
|
|
||||||
write_line_app syncthing "$icon_rld Syncthing" "syncthing"
|
|
||||||
write_line_app telegram-desktop "$icon_tgm Telegram" "telegram-desktop"
|
|
||||||
@@ -104,7 +112,9 @@ write_line_app termite "$icon_trm Termite" "termite -e $SHELL"
|
|
||||||
write_line_app thunar "$icon_dir Thunar" "sxmo_terminal.sh thunar"
|
|
||||||
write_line_app thunderbird "$icon_eml Thunderbird" "thunderbird"
|
|
||||||
write_line_app com.github.bleakgrey.tootle "$icon_msg Tootle" "com.github.bleakgrey.tootle"
|
|
||||||
+write_line_app re.sonny.Tangram "$icon_glb Tangram" "re.sonny.Tangram"
|
|
||||||
write_line_app totem "$icon_mvi Totem" "totem"
|
|
||||||
+write_line_app dev.geopjr.Tuba "$icon_grp Tuba" "dev.geopjr.Tuba"
|
|
||||||
write_line_app tuir "$icon_red Tuir" "sxmo_terminal.sh tuir"
|
|
||||||
write_line_app tut "$icon_msg Tut" "sxmo_terminal.sh tut"
|
|
||||||
write_line_app waydroid "$icon_and Waydroid" "waydroid show-full-ui"
|
|
182
pkgs/additional/sxmo-utils/common.nix
Normal file
182
pkgs/additional/sxmo-utils/common.nix
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
{ stdenv
|
||||||
|
, bash
|
||||||
|
, bc
|
||||||
|
, bemenu
|
||||||
|
, bonsai
|
||||||
|
, brightnessctl
|
||||||
|
, buildPackages
|
||||||
|
, busybox
|
||||||
|
, conky
|
||||||
|
, coreutils
|
||||||
|
, curl
|
||||||
|
, dbus
|
||||||
|
, fetchgit
|
||||||
|
, fetchpatch
|
||||||
|
, gitUpdater
|
||||||
|
, gnugrep
|
||||||
|
, gojq
|
||||||
|
, grim
|
||||||
|
, inotify-tools
|
||||||
|
, j4-dmenu-desktop
|
||||||
|
, jq
|
||||||
|
, lib
|
||||||
|
, libnotify
|
||||||
|
, libxml2
|
||||||
|
, lisgd
|
||||||
|
, makeBinaryWrapper
|
||||||
|
, mako
|
||||||
|
, mepo
|
||||||
|
, modemmanager
|
||||||
|
, nettools
|
||||||
|
, playerctl
|
||||||
|
, procps
|
||||||
|
, pulseaudio
|
||||||
|
, rsync
|
||||||
|
, scdoc
|
||||||
|
, sfeed
|
||||||
|
, slurp
|
||||||
|
, superd
|
||||||
|
, sway
|
||||||
|
, swayidle
|
||||||
|
, wob
|
||||||
|
, wl-clipboard
|
||||||
|
, wtype
|
||||||
|
, wvkbd
|
||||||
|
, xdg-user-dirs
|
||||||
|
, xdotool
|
||||||
|
, xrdb
|
||||||
|
|
||||||
|
, version
|
||||||
|
, rev ? version
|
||||||
|
, hash ? ""
|
||||||
|
, patches ? []
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
# anything which any sxmo script or default hook in this package might invoke
|
||||||
|
runtimeDeps = [
|
||||||
|
bc # also in busybox
|
||||||
|
bemenu
|
||||||
|
bonsai
|
||||||
|
brightnessctl
|
||||||
|
conky
|
||||||
|
curl
|
||||||
|
dbus
|
||||||
|
# dmenu # or dmenu-wayland? only used on x11?
|
||||||
|
gnugrep # also in busybox
|
||||||
|
gojq
|
||||||
|
grim
|
||||||
|
inotify-tools
|
||||||
|
j4-dmenu-desktop
|
||||||
|
jq
|
||||||
|
libnotify
|
||||||
|
libxml2.bin # for xmllint; sxmo_weather.sh, sxmo_surf_linkset.sh
|
||||||
|
lisgd
|
||||||
|
mako
|
||||||
|
mepo # mepo_ui_central_menu.sh
|
||||||
|
modemmanager # mmcli
|
||||||
|
nettools # netstat
|
||||||
|
playerctl
|
||||||
|
procps # pgrep
|
||||||
|
pulseaudio # pactl
|
||||||
|
sfeed
|
||||||
|
slurp # for sxmo_screenshot.sh
|
||||||
|
superd
|
||||||
|
sway
|
||||||
|
swayidle
|
||||||
|
wl-clipboard # for wl-copy; sxmo_screenshot.sh
|
||||||
|
wob
|
||||||
|
wtype # for sxmo_type
|
||||||
|
wvkbd
|
||||||
|
xdg-user-dirs
|
||||||
|
xrdb # for sxmo_xinit AND sxmo_winit
|
||||||
|
|
||||||
|
# X11 only?
|
||||||
|
xdotool
|
||||||
|
];
|
||||||
|
in
|
||||||
|
stdenv.mkDerivation rec {
|
||||||
|
pname = "sxmo-utils";
|
||||||
|
inherit version;
|
||||||
|
|
||||||
|
src = fetchgit {
|
||||||
|
url = "https://git.sr.ht/~mil/sxmo-utils";
|
||||||
|
inherit rev hash;
|
||||||
|
};
|
||||||
|
|
||||||
|
inherit patches;
|
||||||
|
|
||||||
|
postPatch = ''
|
||||||
|
# allow sxmo to source its init file
|
||||||
|
sed -i "s@/etc/profile\.d/sxmo_init.sh@$out/etc/profile.d/sxmo_init.sh@" scripts/core/*.sh
|
||||||
|
# remove absolute paths
|
||||||
|
substituteInPlace scripts/core/sxmo_version.sh \
|
||||||
|
--replace "/usr/bin/" ""
|
||||||
|
|
||||||
|
# let superd find sxmo service binaries at runtime via PATH
|
||||||
|
# TODO: replace with fully-qualified paths
|
||||||
|
sed -i 's:ExecStart=/usr/bin/:ExecStart=/usr/bin/env :' configs/superd/services/*.service
|
||||||
|
|
||||||
|
# install udev rules to where nix expects
|
||||||
|
substituteInPlace Makefile \
|
||||||
|
--replace "/usr/lib/udev/rules.d" "/etc/udev/rules.d"
|
||||||
|
# avoid relative paths in udev rules
|
||||||
|
substituteInPlace configs/udev/90-sxmo.rules \
|
||||||
|
--replace "/bin/chgrp" "${coreutils}/bin/chgrp" \
|
||||||
|
--replace "/bin/chmod" "${coreutils}/bin/chmod"
|
||||||
|
'';
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
makeBinaryWrapper
|
||||||
|
scdoc
|
||||||
|
];
|
||||||
|
|
||||||
|
buildInputs = [ bash ]; # needed here so stdenv's `patchShebangsAuto` hook sets the right interpreter
|
||||||
|
|
||||||
|
makeFlags = [
|
||||||
|
"PREFIX=${placeholder "out"}"
|
||||||
|
"SYSCONFDIR=${placeholder "out"}/etc"
|
||||||
|
"DESTDIR="
|
||||||
|
"OPENRC=0"
|
||||||
|
];
|
||||||
|
preInstall = ''
|
||||||
|
# busybox is used by setup_config_version.sh, but placing it in nativeBuildInputs breaks the nix builder
|
||||||
|
PATH="$PATH:${buildPackages.busybox}/bin"
|
||||||
|
'';
|
||||||
|
|
||||||
|
# we don't wrap sxmo_common.sh or sxmo_init.sh
|
||||||
|
# which is unfortunate, for non-sxmo-utils files that might source those.
|
||||||
|
# if that's a problem, could inject a PATH=... line into them with sed.
|
||||||
|
postInstall = ''
|
||||||
|
for f in \
|
||||||
|
$out/bin/*.sh \
|
||||||
|
$out/share/sxmo/default_hooks/desktop/sxmo_hook_*.sh \
|
||||||
|
$out/share/sxmo/default_hooks/one_button_e_reader/sxmo_hook_*.sh \
|
||||||
|
$out/share/sxmo/default_hooks/three_button_touchscreen/sxmo_hook_*.sh \
|
||||||
|
$out/share/sxmo/default_hooks/sxmo_hook_*.sh \
|
||||||
|
; do
|
||||||
|
case $(basename $f) in
|
||||||
|
(sxmo_common.sh|sxmo_deviceprofile_*.sh|sxmo_hook_icons.sh|sxmo_init.sh)
|
||||||
|
# these are sourced by other scripts: don't wrap them else the `exec` in the wrapper breaks the outer script
|
||||||
|
;;
|
||||||
|
(*)
|
||||||
|
wrapProgram "$f" \
|
||||||
|
--prefix PATH : "${lib.makeBinPath runtimeDeps}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
'';
|
||||||
|
|
||||||
|
passthru = {
|
||||||
|
providedSessions = [ "sxmo" "swmo" ];
|
||||||
|
updateScript = gitUpdater { };
|
||||||
|
};
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
homepage = "https://git.sr.ht/~mil/sxmo-utils";
|
||||||
|
description = "Contains the scripts and small C programs that glues the sxmo enviroment together";
|
||||||
|
license = lib.licenses.mit;
|
||||||
|
maintainers = with lib.maintainers; [ colinsane ];
|
||||||
|
platforms = lib.platforms.linux;
|
||||||
|
};
|
||||||
|
}
|
@@ -1,204 +1,107 @@
|
|||||||
{ stdenv
|
{ callPackage
|
||||||
, bc
|
|
||||||
, bemenu
|
|
||||||
, bonsai
|
|
||||||
, conky
|
|
||||||
, coreutils
|
|
||||||
, dbus
|
|
||||||
, fetchgit
|
|
||||||
, fetchpatch
|
, fetchpatch
|
||||||
, gitUpdater
|
|
||||||
, gnugrep
|
|
||||||
, gojq
|
|
||||||
, grim
|
|
||||||
, inotify-tools
|
|
||||||
, j4-dmenu-desktop
|
|
||||||
, jq
|
|
||||||
, lib
|
|
||||||
, libnotify
|
|
||||||
, lisgd
|
|
||||||
, makeBinaryWrapper
|
|
||||||
, mako
|
|
||||||
, mepo
|
|
||||||
, modemmanager
|
|
||||||
, nettools
|
|
||||||
, playerctl
|
|
||||||
, procps
|
|
||||||
, pulseaudio
|
|
||||||
, rsync
|
|
||||||
, scdoc
|
|
||||||
, sfeed
|
|
||||||
, superd
|
|
||||||
, sway
|
|
||||||
, swayidle
|
|
||||||
, wob
|
|
||||||
, wvkbd
|
|
||||||
, xdg-user-dirs
|
|
||||||
, xdotool
|
|
||||||
}:
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
# anything which any sxmo script or default hook in this package might invoke
|
patches = {
|
||||||
runtimeDeps = [
|
merged = [
|
||||||
bc
|
(fetchpatch {
|
||||||
bemenu
|
# merged post 1.14.2
|
||||||
bonsai
|
# [1/2] sxmo_init: behave well when user's primary group differs from their name
|
||||||
conky
|
# [2/2] sxmo_init: ensure XDG_STATE_HOME exists
|
||||||
dbus
|
url = "https://lists.sr.ht/~mil/sxmo-devel/patches/42309/mbox";
|
||||||
# dmenu # or dmenu-wayland? only used on x11?
|
hash = "sha256-GVWJWTccZeaKsVtsUyZFYl9/qEwJ5U7Bu+DiTDXLjys=";
|
||||||
gnugrep
|
})
|
||||||
gojq
|
(fetchpatch {
|
||||||
grim
|
# merged post 1.14.2
|
||||||
inotify-tools
|
# sxmo_hook_block_suspend: don't assume there's only one MPRIS player
|
||||||
j4-dmenu-desktop
|
url = "https://lists.sr.ht/~mil/sxmo-devel/patches/42441/mbox";
|
||||||
jq
|
hash = "sha256-YmkJ4JLIG/mHosRlVQqvWzujFMBsuDf5nVT3iOi40zU=";
|
||||||
libnotify
|
})
|
||||||
lisgd
|
(fetchpatch {
|
||||||
mako
|
# merged post 1.14.2
|
||||||
mepo # mepo_ui_central_menu.sh
|
# i only care about patch no. 2
|
||||||
modemmanager # mmcli
|
# [1/2] suspend toggle: silence rm failure noise
|
||||||
nettools # netstat
|
# [2/2] config: fix keyboard files location
|
||||||
playerctl
|
name = "multipatch: 42880";
|
||||||
procps # pgrep
|
url = "https://lists.sr.ht/~mil/sxmo-devel/patches/42880/mbox";
|
||||||
pulseaudio # pactl
|
hash = "sha256-tAMPBb6vwzj1dFMTEaqrcCJU6FbQirwZgB0+tqW3rQA=";
|
||||||
sfeed
|
})
|
||||||
superd
|
(fetchpatch {
|
||||||
sway
|
# merged post 1.14.2
|
||||||
swayidle
|
name = "Switch from light to brightnessctl";
|
||||||
wob
|
url = "https://git.sr.ht/~mil/sxmo-utils/commit/d0384a7caed036d25228fa3279c36c0230795e4a.patch";
|
||||||
wvkbd
|
hash = "sha256-/UlcuEI5cJnsqRuZ1zWWzR4dyJw/zYeB1rtJWFeSGEE=";
|
||||||
xdg-user-dirs
|
})
|
||||||
|
(fetchpatch {
|
||||||
|
# merged post 1.14.2
|
||||||
|
name = "sxmo_hook_lock: allow configuration of auto-screenoff timeout v1";
|
||||||
|
url = "https://lists.sr.ht/~mil/sxmo-devel/patches/42443/mbox";
|
||||||
|
hash = "sha256-c4VySbVJgsbh2h+CnCgwWWe5WkAregpYFqL8n3WRXwY=";
|
||||||
|
})
|
||||||
|
(fetchpatch {
|
||||||
|
# merged post 1.14.2
|
||||||
|
name = "sxmo_wmmenu: respect SXMO_WORKSPACE_WRAPPING";
|
||||||
|
url = "https://lists.sr.ht/~mil/sxmo-devel/patches/42698/mbox";
|
||||||
|
hash = "sha256-TrTlrthrpYdIMC8/RCMNaB8PcGQgtya/h2/uLNQDeWs=";
|
||||||
|
})
|
||||||
|
(fetchpatch {
|
||||||
|
# merged ~2023/08/22
|
||||||
|
name = "Make config gesture toggle persistent";
|
||||||
|
url = "https://lists.sr.ht/~mil/sxmo-devel/patches/42876/mbox";
|
||||||
|
hash = "sha256-Oa0MI0Kt9Xgl5L1KarHI6Yn4+vpRxUSujB1iY4hlK9c=";
|
||||||
|
})
|
||||||
|
(fetchpatch {
|
||||||
|
# merged ~2023/08/29
|
||||||
|
# [1/2] Makefile: obey PREFIX when installing udev rules
|
||||||
|
# [2/2] Makefile: use SYSCONFDIR instead of hardcoding /etc
|
||||||
|
name = "44110-multipatch-makefile-nixos";
|
||||||
|
url = "https://lists.sr.ht/~mil/sxmo-devel/patches/44110/mbox";
|
||||||
|
hash = "sha256-jXtwgOVGSjwWj7a36F6P+e63lKvk4OmFIzxTkf9yZMs=";
|
||||||
|
})
|
||||||
|
];
|
||||||
|
unmerged = [
|
||||||
|
# (fetchpatch {
|
||||||
|
# XXX: doesn't apply cleanly to 1.14.2 release
|
||||||
|
# # Don't wait for led or status bar in state change hooks
|
||||||
|
# # - significantly decreases the time between power-button state transitions
|
||||||
|
# url = "https://lists.sr.ht/~mil/sxmo-devel/patches/43109/mbox";
|
||||||
|
# hash = "sha256-4uR2u6pa62y6SaRHYRn15YGDPILAs7py0mPbAjsgwM4=";
|
||||||
|
# })
|
||||||
|
|
||||||
# X11 only?
|
(fetchpatch {
|
||||||
xdotool
|
name = "sxmo_migrate: add option to disable configversion checks";
|
||||||
];
|
url = "https://lists.sr.ht/~mil/sxmo-devel/patches/44155/mbox";
|
||||||
in
|
hash = "sha256-ZcUD2UWPM8PxGM9TBnGe8JCJgMC72OZYzctDf2o7Ub0=";
|
||||||
stdenv.mkDerivation rec {
|
})
|
||||||
pname = "sxmo-utils";
|
|
||||||
version = "1.14.2";
|
|
||||||
|
|
||||||
src = fetchgit {
|
## these might or might not be upstream-worthy
|
||||||
url = "https://git.sr.ht/~mil/sxmo-utils";
|
./0104-full-auto-rotate.patch
|
||||||
rev = version;
|
# ./0106-no-restart-lisgd.patch
|
||||||
|
|
||||||
|
## not upstreamable
|
||||||
|
# let NixOS manage the audio daemons (pulseaudio/pipewire)
|
||||||
|
./0005-system-audio.patch
|
||||||
|
];
|
||||||
|
# these don't apply cleanly to the stable release; only to latest
|
||||||
|
unmerged-tip-only = [
|
||||||
|
# TODO: send these upstream
|
||||||
|
(fetchpatch {
|
||||||
|
name = "sxmo_hook_apps: add a few";
|
||||||
|
url = "https://git.uninsane.org/colin/sxmo-utils/commit/d6c17a89e1b7bc74d0ba34629fd5db393e5f560b.patch";
|
||||||
|
hash = "sha256-b12p7RTnAqTVfHpYLkNTwuo12KDznYCYJUEJAIES/1I=";
|
||||||
|
})
|
||||||
|
];
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
stable = callPackage ./common.nix {
|
||||||
|
version = "1.14.2";
|
||||||
hash = "sha256-1bGCUhf/bt9I8BjG/G7sjYBzLh28iZSC20ml647a3J4=";
|
hash = "sha256-1bGCUhf/bt9I8BjG/G7sjYBzLh28iZSC20ml647a3J4=";
|
||||||
|
patches = patches.merged ++ patches.unmerged;
|
||||||
};
|
};
|
||||||
|
latest = callPackage ./common.nix {
|
||||||
patches = [
|
version = "unstable-2023-08-29";
|
||||||
# needed for basic use:
|
rev = "871caa7394d2deda6aaff89af0fea9f6de773c2e";
|
||||||
(fetchpatch {
|
hash = "sha256-TnRit0W/Racm92AwoEuSIJiOtu2XBUd3IsQoPrtshvk=";
|
||||||
# merged post 1.14.2
|
patches = patches.unmerged ++ patches.unmerged-tip-only;
|
||||||
# [1/2] sxmo_init: behave well when user's primary group differs from their name
|
|
||||||
# [2/2] sxmo_init: ensure XDG_STATE_HOME exists
|
|
||||||
url = "https://lists.sr.ht/~mil/sxmo-devel/patches/42309/mbox";
|
|
||||||
hash = "sha256-GVWJWTccZeaKsVtsUyZFYl9/qEwJ5U7Bu+DiTDXLjys=";
|
|
||||||
})
|
|
||||||
(fetchpatch {
|
|
||||||
# merged post 1.14.2
|
|
||||||
# sxmo_hook_block_suspend: don't assume there's only one MPRIS player
|
|
||||||
url = "https://lists.sr.ht/~mil/sxmo-devel/patches/42441/mbox";
|
|
||||||
hash = "sha256-YmkJ4JLIG/mHosRlVQqvWzujFMBsuDf5nVT3iOi40zU=";
|
|
||||||
})
|
|
||||||
(fetchpatch {
|
|
||||||
# merged post 1.14.2
|
|
||||||
# i only care about patch no. 2
|
|
||||||
# [1/2] suspend toggle: silence rm failure noise
|
|
||||||
# [2/2] config: fix keyboard files location
|
|
||||||
url = "https://lists.sr.ht/~mil/sxmo-devel/patches/42880/mbox";
|
|
||||||
hash = "sha256-tAMPBb6vwzj1dFMTEaqrcCJU6FbQirwZgB0+tqW3rQA=";
|
|
||||||
})
|
|
||||||
./0004-no-busybox.patch
|
|
||||||
# wanted to fix/silence some non-fatal errors
|
|
||||||
./0005-system-audio.patch
|
|
||||||
./0007-workspace-wrapping.patch
|
|
||||||
|
|
||||||
# personal (but upstreamable) preferences:
|
|
||||||
(fetchpatch {
|
|
||||||
# merged post 1.14.2
|
|
||||||
# sxmo_hook_lock: allow configuration of auto-screenoff timeout v1
|
|
||||||
url = "https://lists.sr.ht/~mil/sxmo-devel/patches/42443/mbox";
|
|
||||||
hash = "sha256-c4VySbVJgsbh2h+CnCgwWWe5WkAregpYFqL8n3WRXwY=";
|
|
||||||
})
|
|
||||||
# (fetchpatch {
|
|
||||||
# XXX: doesn't apply cleanly to 1.14.2 release
|
|
||||||
# # Don't wait for led or status bar in state change hooks
|
|
||||||
# # - significantly decreases the time between power-button state transitions
|
|
||||||
# url = "https://lists.sr.ht/~mil/sxmo-devel/patches/43109/mbox";
|
|
||||||
# hash = "sha256-4uR2u6pa62y6SaRHYRn15YGDPILAs7py0mPbAjsgwM4=";
|
|
||||||
# })
|
|
||||||
(fetchpatch {
|
|
||||||
# Make config gesture toggle persistent
|
|
||||||
url = "https://lists.sr.ht/~mil/sxmo-devel/patches/42876/mbox";
|
|
||||||
hash = "sha256-Oa0MI0Kt9Xgl5L1KarHI6Yn4+vpRxUSujB1iY4hlK9c=";
|
|
||||||
})
|
|
||||||
./0104-full-auto-rotate.patch
|
|
||||||
./0105-more-apps.patch
|
|
||||||
# ./0106-no-restart-lisgd.patch
|
|
||||||
];
|
|
||||||
|
|
||||||
postPatch = ''
|
|
||||||
# allow sxmo to source its init file
|
|
||||||
sed -i "s@/etc/profile\.d/sxmo_init.sh@$out/etc/profile.d/sxmo_init.sh@" scripts/core/*.sh
|
|
||||||
# remove absolute paths
|
|
||||||
substituteInPlace scripts/core/sxmo_version.sh \
|
|
||||||
--replace "/usr/bin/" ""
|
|
||||||
|
|
||||||
# let superd find sxmo service binaries at runtime via PATH
|
|
||||||
# TODO: replace with fully-qualified paths
|
|
||||||
sed -i 's:ExecStart=/usr/bin/:ExecStart=/usr/bin/env :' configs/superd/services/*.service
|
|
||||||
|
|
||||||
# install udev rules to where nix expects
|
|
||||||
substituteInPlace Makefile \
|
|
||||||
--replace "/usr/lib/udev/rules.d" "/etc/udev/rules.d"
|
|
||||||
# avoid relative paths in udev rules
|
|
||||||
substituteInPlace configs/udev/90-sxmo.rules \
|
|
||||||
--replace "/bin/chgrp" "${coreutils}/bin/chgrp" \
|
|
||||||
--replace "/bin/chmod" "${coreutils}/bin/chmod"
|
|
||||||
'';
|
|
||||||
|
|
||||||
nativeBuildInputs = [
|
|
||||||
makeBinaryWrapper
|
|
||||||
scdoc
|
|
||||||
];
|
|
||||||
|
|
||||||
installFlags = [
|
|
||||||
"OPENRC=0"
|
|
||||||
"DESTDIR=$(out)"
|
|
||||||
"PREFIX="
|
|
||||||
];
|
|
||||||
|
|
||||||
# we don't wrap sxmo_common.sh or sxmo_init.sh
|
|
||||||
# which is unfortunate, for non-sxmo-utils files that might source though.
|
|
||||||
# if that's a problem, could inject a PATH=... line into them with sed.
|
|
||||||
postInstall = ''
|
|
||||||
for f in \
|
|
||||||
$out/bin/*.sh \
|
|
||||||
$out/share/sxmo/default_hooks/desktop/sxmo_hook_*.sh \
|
|
||||||
$out/share/sxmo/default_hooks/one_button_e_reader/sxmo_hook_*.sh \
|
|
||||||
$out/share/sxmo/default_hooks/three_button_touchscreen/sxmo_hook_*.sh \
|
|
||||||
$out/share/sxmo/default_hooks/sxmo_hook_*.sh \
|
|
||||||
; do
|
|
||||||
case $(basename $f) in
|
|
||||||
(sxmo_common.sh|sxmo_deviceprofile_*.sh|sxmo_hook_icons.sh|sxmo_init.sh)
|
|
||||||
# these are sourced by other scripts: don't wrap them else the `exec` in the wrapper breaks the outer script
|
|
||||||
;;
|
|
||||||
(*)
|
|
||||||
wrapProgram "$f" \
|
|
||||||
--prefix PATH : "${lib.makeBinPath runtimeDeps}"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
'';
|
|
||||||
|
|
||||||
passthru = {
|
|
||||||
providedSessions = [ "sxmo" "swmo" ];
|
|
||||||
updateScript = gitUpdater { };
|
|
||||||
};
|
|
||||||
|
|
||||||
meta = {
|
|
||||||
homepage = "https://git.sr.ht/~mil/sxmo-utils";
|
|
||||||
description = "Contains the scripts and small C programs that glues the sxmo enviroment together";
|
|
||||||
license = lib.licenses.mit;
|
|
||||||
maintainers = with lib.maintainers; [ colinsane ];
|
|
||||||
platforms = lib.platforms.linux;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -21,10 +21,14 @@ let
|
|||||||
|
|
||||||
### ADDITIONAL PACKAGES
|
### ADDITIONAL PACKAGES
|
||||||
alsa-ucm-conf-sane = callPackage ./additional/alsa-ucm-conf-sane { };
|
alsa-ucm-conf-sane = callPackage ./additional/alsa-ucm-conf-sane { };
|
||||||
bonsai = unpatched.bonsai or (callPackage ./additional/bonsai { });
|
# TODO: move target flags to upstream PR and re-enable this bonsai
|
||||||
|
# bonsai = unpatched.bonsai or (callPackage ./additional/bonsai { });
|
||||||
|
bonsai = callPackage ./additional/bonsai { };
|
||||||
bootpart-uefi-x86_64 = callPackage ./additional/bootpart-uefi-x86_64 { };
|
bootpart-uefi-x86_64 = callPackage ./additional/bootpart-uefi-x86_64 { };
|
||||||
cargoDocsetHook = callPackage ./additional/cargo-docset/hook.nix { };
|
cargoDocsetHook = callPackage ./additional/cargo-docset/hook.nix { };
|
||||||
chatty-latest = callPackage ./additional/chatty-latest { };
|
chatty-latest = callPackage ./additional/chatty-latest { };
|
||||||
|
eg25-control = callPackage ./additional/eg25-control { };
|
||||||
|
eg25-manager = callPackage ./additional/eg25-manager { };
|
||||||
feeds = lib.recurseIntoAttrs (callPackage ./additional/feeds { });
|
feeds = lib.recurseIntoAttrs (callPackage ./additional/feeds { });
|
||||||
lemoa = callPackage ./additional/lemoa { };
|
lemoa = callPackage ./additional/lemoa { };
|
||||||
jellyfin-media-player-qt6 = callPackage ./additional/jellyfin-media-player-qt6 { };
|
jellyfin-media-player-qt6 = callPackage ./additional/jellyfin-media-player-qt6 { };
|
||||||
@@ -40,14 +44,20 @@ let
|
|||||||
koreader-from-src = callPackage ./additional/koreader-from-src { };
|
koreader-from-src = callPackage ./additional/koreader-from-src { };
|
||||||
ldd-aarch64 = callPackage ./additional/ldd-aarch64 { };
|
ldd-aarch64 = callPackage ./additional/ldd-aarch64 { };
|
||||||
lightdm-mobile-greeter = callPackage ./additional/lightdm-mobile-greeter { };
|
lightdm-mobile-greeter = callPackage ./additional/lightdm-mobile-greeter { };
|
||||||
|
linux-manjaro = callPackage ./additional/linux-manjaro { };
|
||||||
linux-megous = callPackage ./additional/linux-megous { };
|
linux-megous = callPackage ./additional/linux-megous { };
|
||||||
|
mcg = callPackage ./additional/mcg { };
|
||||||
mpv-uosc-latest = callPackage ./additional/mpv-uosc-latest { };
|
mpv-uosc-latest = callPackage ./additional/mpv-uosc-latest { };
|
||||||
mx-sanebot = callPackage ./additional/mx-sanebot { };
|
mx-sanebot = callPackage ./additional/mx-sanebot { };
|
||||||
|
phog = callPackage ./additional/phog { };
|
||||||
rtl8723cs-firmware = callPackage ./additional/rtl8723cs-firmware { };
|
rtl8723cs-firmware = callPackage ./additional/rtl8723cs-firmware { };
|
||||||
sane-scripts = lib.recurseIntoAttrs (callPackage ./additional/sane-scripts { });
|
sane-scripts = lib.recurseIntoAttrs (callPackage ./additional/sane-scripts { });
|
||||||
|
sane-weather = callPackage ./additional/sane-weather { };
|
||||||
static-nix-shell = callPackage ./additional/static-nix-shell { };
|
static-nix-shell = callPackage ./additional/static-nix-shell { };
|
||||||
sublime-music-mobile = callPackage ./additional/sublime-music-mobile { };
|
sublime-music-mobile = callPackage ./additional/sublime-music-mobile { };
|
||||||
sxmo-utils = callPackage ./additional/sxmo-utils { };
|
sxmo-utils' = lib.recurseIntoAttrs (callPackage ./additional/sxmo-utils { });
|
||||||
|
sxmo-utils = sxmo-utils'.stable;
|
||||||
|
sxmo-utils-latest = sxmo-utils'.latest;
|
||||||
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 { };
|
||||||
unftp = callPackage ./additional/unftp { };
|
unftp = callPackage ./additional/unftp { };
|
||||||
@@ -104,12 +114,13 @@ let
|
|||||||
|
|
||||||
helix = callPackage ./patched/helix { inherit (unpatched) helix; };
|
helix = callPackage ./patched/helix { inherit (unpatched) helix; };
|
||||||
|
|
||||||
|
ibus = callPackage ./patched/ibus { inherit (unpatched) ibus; };
|
||||||
|
|
||||||
# jackett doesn't allow customization of the bind address: this will probably always be here.
|
# jackett doesn't allow customization of the bind address: this will probably always be here.
|
||||||
jackett = callPackage ./patched/jackett { inherit (unpatched) jackett; };
|
jackett = callPackage ./patched/jackett { inherit (unpatched) jackett; };
|
||||||
|
libgweather = callPackage ./patched/libgweather { inherit (unpatched) libgweather; };
|
||||||
|
|
||||||
komikku = callPackage ./patched/komikku { inherit (unpatched) komikku; };
|
# modemmanager = callPackage ./patched/modemmanager { inherit (unpatched) modemmanager; };
|
||||||
|
|
||||||
phoc = callPackage ./patched/phoc { inherit (unpatched) phoc; };
|
|
||||||
|
|
||||||
|
|
||||||
### PYTHON PACKAGES
|
### PYTHON PACKAGES
|
||||||
|
@@ -11,12 +11,15 @@ let
|
|||||||
};
|
};
|
||||||
in
|
in
|
||||||
helix.overrideAttrs (upstream: {
|
helix.overrideAttrs (upstream: {
|
||||||
|
nativeBuildInputs = (upstream.nativeBuildInputs or []) ++ [
|
||||||
|
rsync
|
||||||
|
];
|
||||||
configurePhase = (upstream.configurePhase or "") + ''
|
configurePhase = (upstream.configurePhase or "") + ''
|
||||||
cat ${languages} >> languages.toml
|
cat ${languages} >> languages.toml
|
||||||
substituteAllInPlace languages.toml
|
substituteAllInPlace languages.toml
|
||||||
|
|
||||||
${rsync}/bin/rsync -arv ${tree-sitter-nix-shell.generated}/ runtime/grammars/sources/nix-shell/
|
rsync -arv ${tree-sitter-nix-shell.generated}/ runtime/grammars/sources/nix-shell/
|
||||||
${rsync}/bin/rsync -arv ${tree-sitter-nix-shell}/queries/ runtime/queries/nix-shell/
|
rsync -arv ${tree-sitter-nix-shell}/queries/ runtime/queries/nix-shell/
|
||||||
|
|
||||||
# helix tries to delete the sources during installPhase
|
# helix tries to delete the sources during installPhase
|
||||||
chmod -R +w runtime/grammars/sources/nix-shell
|
chmod -R +w runtime/grammars/sources/nix-shell
|
||||||
|
21
pkgs/patched/ibus/build-without-dbus-launch.patch
Normal file
21
pkgs/patched/ibus/build-without-dbus-launch.patch
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
diff --git a/data/dconf/make-dconf-override-db.sh b/data/dconf/make-dconf-override-db.sh
|
||||||
|
index 32cb1530..4ce36bc1 100755
|
||||||
|
--- a/data/dconf/make-dconf-override-db.sh
|
||||||
|
+++ b/data/dconf/make-dconf-override-db.sh
|
||||||
|
@@ -12,10 +12,6 @@ export XDG_CACHE_HOME="$TMPDIR/cache"
|
||||||
|
export GSETTINGS_SCHEMA_DIR="$TMPDIR/schemas"
|
||||||
|
mkdir -p $XDG_CONFIG_HOME $XDG_CACHE_HOME $GSETTINGS_SCHEMA_DIR
|
||||||
|
|
||||||
|
-eval `dbus-launch --sh-syntax`
|
||||||
|
-
|
||||||
|
-trap cleanup EXIT
|
||||||
|
-
|
||||||
|
cleanup() {
|
||||||
|
test $? -eq 0 && exit
|
||||||
|
rm -rf $TMPDIR; kill $DBUS_SESSION_BUS_PID
|
||||||
|
@@ -57,5 +53,3 @@ if [ -d $TMPDIR/cache/gvfs ] ; then
|
||||||
|
umount $TMPDIR/cache/gvfs
|
||||||
|
fi
|
||||||
|
rm -rf $TMPDIR
|
||||||
|
-
|
||||||
|
-kill $DBUS_SESSION_BUS_PID
|
18
pkgs/patched/ibus/configure-no-ac-check-file.patch
Normal file
18
pkgs/patched/ibus/configure-no-ac-check-file.patch
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
diff --git a/configure.ac b/configure.ac
|
||||||
|
index 392cc581..6d5750dc 100644
|
||||||
|
--- a/configure.ac
|
||||||
|
+++ b/configure.ac
|
||||||
|
@@ -345,11 +345,7 @@ fi
|
||||||
|
AC_SUBST(X11_PREFIX)
|
||||||
|
|
||||||
|
# Check locale dir for Compose files.
|
||||||
|
-AC_CHECK_FILE($X11_PREFIX/share/X11/locale/locale.dir,
|
||||||
|
- X11_LOCALEDATADIR="$X11_PREFIX/share/X11/locale",
|
||||||
|
- [AC_CHECK_FILE($X11_PREFIX/lib/X11/locale/locale.dir,
|
||||||
|
- X11_LOCALEDATADIR="$X11_PREFIX/lib/X11/locale",
|
||||||
|
- X11_LOCALEDATADIR="$(datadir)/X11/locale")])
|
||||||
|
+X11_LOCALEDATADIR="$X11_PREFIX/share/X11/locale"
|
||||||
|
AC_SUBST(X11_LOCALEDATADIR)
|
||||||
|
|
||||||
|
if test x"$enable_wayland" = x"yes"; then
|
||||||
|
|
58
pkgs/patched/ibus/default.nix
Normal file
58
pkgs/patched/ibus/default.nix
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
{ ibus
|
||||||
|
, buildPackages
|
||||||
|
, fetchFromGitHub
|
||||||
|
, gobject-introspection
|
||||||
|
, lib
|
||||||
|
, libdbusmenu-gtk3
|
||||||
|
, pkg-config
|
||||||
|
, pkgs
|
||||||
|
, stdenv
|
||||||
|
, ...
|
||||||
|
}@attrs:
|
||||||
|
let
|
||||||
|
isCross = !(stdenv.buildPlatform.canExecute stdenv.hostPlatform);
|
||||||
|
in
|
||||||
|
(ibus.override
|
||||||
|
(removeAttrs attrs [ "ibus" "libdbusmenu-gtk3" "pkgs" ] )
|
||||||
|
).overrideAttrs (upstream: rec {
|
||||||
|
# compared to 1.5.28, this version supports better cross compilation
|
||||||
|
version = "1.5.29-rc1";
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "ibus";
|
||||||
|
repo = "ibus";
|
||||||
|
rev = version;
|
||||||
|
hash = "sha256-stUWAGtsQRq+g/68OKuYqHgNxZBGzGC6VgJ+IwuAkx8=";
|
||||||
|
};
|
||||||
|
patches = [(builtins.head upstream.patches)] ++ [
|
||||||
|
# this patch is in nixpkgs 1.5.28, but doesn't cleanly apply to this current version
|
||||||
|
./build-without-dbus-launch.patch
|
||||||
|
# AC_CHECK_FILE has an explicit guard against cross compiling, which is silly if you think about it for more than a second.
|
||||||
|
./configure-no-ac-check-file.patch
|
||||||
|
];
|
||||||
|
|
||||||
|
# vapigen (vala) is nativeBuildInputs, so fix the PKG_CONFIG ibus uses to find it.
|
||||||
|
# ibus does an extra sanity check with `PKG_CHECK_EXISTS`, but that doesn't support
|
||||||
|
# PKG_CONFIG_FOR_BUILD, so turn its error into just a warning.
|
||||||
|
postPatch = (upstream.postPatch or "") + lib.optionalString isCross ''
|
||||||
|
substituteInPlace m4/vapigen.m4 \
|
||||||
|
--replace PKG_PROG_PKG_CONFIG PKG_PROG_PKG_CONFIG_FOR_BUILD \
|
||||||
|
--replace 'PKG_CONFIG ' 'PKG_CONFIG_FOR_BUILD ' \
|
||||||
|
--replace 'AC_MSG_ERROR([$vapigen_pkg not found])' 'AC_MSG_WARN([$vapigen_pkg not found])'
|
||||||
|
'';
|
||||||
|
|
||||||
|
configureFlags = upstream.configureFlags ++ [
|
||||||
|
"--enable-vala"
|
||||||
|
];
|
||||||
|
|
||||||
|
# to debug:
|
||||||
|
# makeFlags = upstream.makeFlags ++ [ "V=1" ];
|
||||||
|
|
||||||
|
depsBuildBuild = (upstream.depsBuildBuild or []) ++ [
|
||||||
|
buildPackages.stdenv.cc
|
||||||
|
pkg-config
|
||||||
|
];
|
||||||
|
|
||||||
|
buildInputs = upstream.buildInputs ++ [
|
||||||
|
libdbusmenu-gtk3
|
||||||
|
];
|
||||||
|
})
|
@@ -1,19 +0,0 @@
|
|||||||
{ komikku
|
|
||||||
, fetchFromGitLab
|
|
||||||
, fetchpatch2
|
|
||||||
}:
|
|
||||||
komikku.overrideAttrs (upstream: {
|
|
||||||
# src = fetchFromGitLab {
|
|
||||||
# owner = "valos";
|
|
||||||
# repo = "Komikku";
|
|
||||||
# rev = "7dcf2b3d0ba685396872780b1ce75d01cbe02ebe";
|
|
||||||
# hash = "sha256-LzgHPuIpxy0ropiNycdxZP6onjK2JpMRqkkdmJGA4nE=";
|
|
||||||
# };
|
|
||||||
patches = (upstream.patches or []) ++ [
|
|
||||||
(fetchpatch2 {
|
|
||||||
url = "https://git.uninsane.org/colin/mirror-komikku/commit/318fc0c975ba84ca4dcff405bc1bb8f5895bc5a6.diff";
|
|
||||||
hash = "sha256-mn81hCt5xrypJMOOiCOg8NthLjglXntTDsYpcdCg0E8=";
|
|
||||||
})
|
|
||||||
];
|
|
||||||
passthru.unpatched = komikku;
|
|
||||||
})
|
|
18
pkgs/patched/libgweather/default.nix
Normal file
18
pkgs/patched/libgweather/default.nix
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{ lib
|
||||||
|
, libgweather
|
||||||
|
, fetchpatch
|
||||||
|
, ...
|
||||||
|
}@attrs:
|
||||||
|
(libgweather.override
|
||||||
|
(removeAttrs attrs [ "fetchpatch" "libgweather" ])
|
||||||
|
).overrideAttrs (upstream: {
|
||||||
|
patches = lib.unique (
|
||||||
|
(upstream.patches or []) ++ [
|
||||||
|
(fetchpatch {
|
||||||
|
url = "https://gitlab.gnome.org/GNOME/libgweather/-/merge_requests/282.patch";
|
||||||
|
name = "nws: fix null string comparison when reading visibility";
|
||||||
|
hash = "sha256-yQncWfJJmXOTw8Kvxutjjlenjv1g5QR5JnLU4QhMXSo=";
|
||||||
|
})
|
||||||
|
]
|
||||||
|
);
|
||||||
|
})
|
6
pkgs/patched/modemmanager/default.nix
Normal file
6
pkgs/patched/modemmanager/default.nix
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{ modemmanager }: modemmanager.overrideAttrs (upstream: {
|
||||||
|
patches = (upstream.patches or []) ++ [
|
||||||
|
# don't go into the "fail" state just because we can't figure out if the SIM is unlocked
|
||||||
|
./missing-sim-not-fatal.patch
|
||||||
|
];
|
||||||
|
})
|
41
pkgs/patched/modemmanager/missing-sim-not-fatal.patch
Normal file
41
pkgs/patched/modemmanager/missing-sim-not-fatal.patch
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
commit bf4b81671e9bd073efc95a2fa4d4c05c3174104f
|
||||||
|
Author: Colin <colin@uninsane.org>
|
||||||
|
Date: 2023-08-17 07:50:32 +0000
|
||||||
|
|
||||||
|
don't enter failed state due to missing sim
|
||||||
|
|
||||||
|
diff --git a/src/mm-iface-modem.c b/src/mm-iface-modem.c
|
||||||
|
index 911c139d..c6550ccd 100644
|
||||||
|
--- a/src/mm-iface-modem.c
|
||||||
|
+++ b/src/mm-iface-modem.c
|
||||||
|
@@ -3773,7 +3773,8 @@ internal_load_unlock_required_ready (MMIfaceModem *self,
|
||||||
|
} else {
|
||||||
|
mm_obj_dbg (self, "couldn't check if unlock required: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
- ctx->lock = MM_MODEM_LOCK_UNKNOWN;
|
||||||
|
+ mm_obj_info(self, "faking unlock state (Colin patch)");
|
||||||
|
+ ctx->lock = MM_MODEM_LOCK_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -5177,13 +5178,13 @@ modem_update_lock_info_ready (MMIfaceModem *self,
|
||||||
|
/* NOTE: we already propagated the lock state, no need to do it again */
|
||||||
|
mm_iface_modem_update_lock_info_finish (self, res, &ctx->fatal_error);
|
||||||
|
if (ctx->fatal_error) {
|
||||||
|
- g_prefix_error (&ctx->fatal_error,
|
||||||
|
- "Couldn't check unlock status: ");
|
||||||
|
- /* Jump to the last step */
|
||||||
|
- ctx->step = INITIALIZATION_STEP_LAST;
|
||||||
|
- } else
|
||||||
|
- /* Go on to next step */
|
||||||
|
- ctx->step++;
|
||||||
|
+ mm_obj_info (self, "ignoring 'couldnt check unlock status' error (sane patch)");
|
||||||
|
+ g_error_free (ctx->fatal_error);
|
||||||
|
+ ctx->fatal_error = NULL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Go on to next step */
|
||||||
|
+ ctx->step++;
|
||||||
|
|
||||||
|
interface_initialization_step (task);
|
||||||
|
}
|
@@ -1,11 +0,0 @@
|
|||||||
{ fetchpatch, phoc }:
|
|
||||||
phoc.overrideAttrs (super: {
|
|
||||||
patches = super.patches or [] ++ [
|
|
||||||
(fetchpatch {
|
|
||||||
# this patch fixes some screen-blanking issues.
|
|
||||||
# not 100% necessary, but does give a better experience.
|
|
||||||
url = "https://gitlab.gnome.org/World/Phosh/phoc/-/merge_requests/428.diff";
|
|
||||||
hash = "sha256-XaSpcjtAFbGpqSLOUvjFU84TRmjKhL0NPIDvEK4VUD4=";
|
|
||||||
})
|
|
||||||
];
|
|
||||||
})
|
|
48
secrets/common/mopidy.conf.bin
Normal file
48
secrets/common/mopidy.conf.bin
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"data": "ENC[AES256_GCM,data:DQLyt84vTpMrWhi4PfTUNw5hma1OZxfP7gHhyhCjwAnKKtTjWh2Ew2k7PWDRhpvw57UP4vRktt8hdV6Lx5pcApwdnO73C6rO5gKzzN4lINJj7mnP7RW5yhgJey09qzm0fzmr6rEtuhTnuT6klnUE2Minlv3yV0WjuGADZR1me1AVe6UWrEmd57nx4PEh6zwL87n6ea/AK5DqSRL1De3pGC0deRd7C2hKsemklaAN7NKclgI51Qs+9Z509GlbC1CSZ1c23sBeFBxMfvaWWYBsuIbTnHi/e3WWrO4Xvx0A+Xwl4Kj1EbNWa0CguOJqgD8HNG7bHNDtJd5DuE2m1Ts6UM3Iepo1aSh7uLRCox1Em7S2zWHCGovGw5Dj4W6jhsUOHJKCBxFzZ/nh1Ltt7rc8Gc6S+p3HEXNeuRILwUGVkMl+qR3b/T5hTp1NXTEx2FkpbEWAsmrw1OnF85e5OQbWLeqLbSa2KxWEyTHZlxB20JbfRUvM4UOsy0vi4Otcl4z1O+1CiH/pmesQEWPZr0XQFJ8aG/gHakWEtlg7qPJolQh7KjSooPF6Mj62aeyjuMSe9tOdLeWQ23Qov4PY61+nRoSHb8t6DbmHM1N9kTkZsZcCvIyBE0UZTQLkekmg7FZhgn+TN1Q1LthRBTo9SYr7PfcvvTKnz/nT7yH4G6nR1CVLxPeJVPx3shUEMvDcaelR3Rt9+eXoJTab1ChhUPajtaNMSaDWrn5XcfUL1NQfxcOeiZOUBwDKPg3Por4h949pN47/OQtexUuw+ks91uYL3MdIbPh5f2VYMHX11jMl6EY9y5PIBWlmZeEdcb6EPYm0cHLwBJk+pQTYDMSXkVFCvYMMFfIKuhcw6nEcrBZJUNfH8z75eTMj7mCXX5GNrANfYrUAxNGubYBqbMQhXv4kO2NhGfKp2GDV6Zz1iXM4Vy8WXeBa/frGBkj3Q3ya/1G2EyseOwFzPNxhfqJ1tUfJ2+NDYbsruPWgyXrSvy1/McM5PiRFeQBaVUyhF5GQbmuiVDgFFdnHaPudD4NAu3juWUu0tnCuEpj5cnR7jaFrIrutf7mwHJXi9ipXE1Go2nX7yQT4jhQtQv2Rt3v9kQOV9xfIPgdaP0jd7iPyuOam3nSK4GlsSzG6B8GYw7yUtRDKU//Vi2s/roXzc2ADeXRS3GqJNeHkrPIvhku6JyTZH9vLx7co8IC5ZP+ziMTBcAbpUH0RjlugGuzzDQUz+mv+OJMVr+kXyzxFjBNvF1COweXACJD0A+9KMStUPXZlCZDd5a61nw61yQyVf2UK+SFkPEL80C61ZWbuLDuBc6V0h48vEiw/07/MIcpnhLzLggCpoyXYLlZH,iv:q2agBEI1tvVMPc4TYJJpwkJvrENBVP4LrtAmlKT+wwo=,tag:oj8Bope12LHUvJl4vB6lxg==,type:str]",
|
||||||
|
"sops": {
|
||||||
|
"kms": null,
|
||||||
|
"gcp_kms": null,
|
||||||
|
"azure_kv": null,
|
||||||
|
"hc_vault": null,
|
||||||
|
"age": [
|
||||||
|
{
|
||||||
|
"recipient": "age1tnl4jfgacwkargzeqnhzernw29xx8mkv73xh6ufdyde6q7859slsnzf24x",
|
||||||
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQSGNFU00rSERHQXJJTnpL\nRXNoYm4xazN6Z3dvMDZ1OTA2Q1g3OURrRFdjCkgxaUZaN3k5RHFGM0hTWkRybFBV\ncnVZVkFiV0NWeXJoWGloV0c5Um01cncKLS0tIGZFODFxeXVpNmkyRFN0SE1ZK2J3\nTkd6dzFNT0F5dTJ6VGVVYTJwY2xCL2MKTDHVtRp1uojeHJ2dILTvjQTXtWU0A2ZT\n6KEe5pkoadVoI3lu70RLyGGQuImGgc/ZsEJiV2CHIuKG17J3bexBBw==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recipient": "age1j2pqnl8j0krdzk6npe93s4nnqrzwx978qrc0u570gzlamqpnje9sc8le2g",
|
||||||
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2TWYwdmQxVzRESGR4Q0J1\nN0JXK2V3SXB1SWJxeHJKNjFpOXI3ZkFTbFNJCmNQeHRiM281MXliNDVHNExVMGtX\nR3FZcmtTdWhtaU1NSmlwbjdkcUJtVGcKLS0tIEtJaXBsZXVBSFRnZjRWRGdVcVBQ\nQ0RqQmhMZEJ5cXBkVk1CdWZsMFROSTAKx+uAnbpXblkJi8zSiyJXO3UtHTydGbM4\naSN58lAR3yCuSuNHdUlDXr9TQfF4rTHEBGMBFh0ey/CmX8hzoJXiDQ==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recipient": "age1z8fauff34cdecr6sjkre260luzxcca05kpcwvhx988d306tpcejsp63znu",
|
||||||
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBpZllMSHRDN0tUajdwdzR6\nOTdadjN3L2JFR2RNcVVob0NLWGlycFdMNm5RCk5XbTExc09leGpsMUxUTWFBYjhy\nMnNDazI5WHprMFRNWVc1QkdKTkppZmsKLS0tIEJWRzhBb2lKeDc5bHl6OXdvMDZD\nS0UxSXM5R2xOUU1Ud2s2UmRkVE5uNlkKAHjY/gUahrkgAbb+2Q43asvVrgdaKfWC\nO5JPHo+krBydvNZ2k4261lBF8zwJ++D+qZK396WxChMH/RhiiPUBSQ==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recipient": "age1zsrsvd7j6l62fjxpfd2qnhqlk8wk4p8r0dtxpe4sdgnh2474095qdu7xj9",
|
||||||
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxYVJYL3pmVjRmczJjaTlF\nUW9OOGU5dzdWTHg1bzh2OHR5d0tNTGF0NmdRClQxNVF4b0Z6ZzF0YndvWmZoMlBD\nQXB0dmZhQ3N6S2VjRFh5bko1LzJYR3MKLS0tIEgxS3kzWHJSUStUcDRDRG84bGJ3\nYmRNeEMybDB3b1dFV1QxNmhJeTNCM2MKywwuf2TNR0VuEQcaZB4uYdxSyG6dzNiy\nX2/ke2xG8yApIKW5WIrOO+UgGB9i7ZdiGKUx73YUKgm/4IECfbHxSg==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recipient": "age1vnw7lnfpdpjn62l3u5nyv5xt2c965k96p98kc43mcnyzpetrts9q54mc9v",
|
||||||
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBLdmtEWXJDUUdKdjF6QmNY\nUGd3dW5BNXY0NnB3WE9aSWF3RWxiNi9TMDJnCmhxaDBEVHRWelpLdEgvT2d5Uy9Y\nOUFBK1ZNdHl1Mi9kZ0dZSmpVUVJyQzAKLS0tIFNpeDBFa25wNmhqZk5vT0dOYk1B\nSWhKV2JKMmh4RllQWC9EQ08wVmZ4UmsKQVCwHKBSFOTrG7z3njR7HV1CC/ijQksT\nB4iYhs8Vt91QPLvVte7P9PYk5yNu3cjeV65h4jHn9G/RzfUnnNyfPw==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recipient": "age1w7mectcjku6x3sd8plm8wkn2qfrhv9n6zhzlf329e2r2uycgke8qkf9dyn",
|
||||||
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBBRm9PMWpxMjlsTHpnMVk1\nRmFNclNqdFRPc1N0bU12VEpPcjhDS2JIbXpVCmo1TDdKYTZrNW8vSUdScnRSQnVP\nMENQUGg4Nm1ocEpYS2JGaCtsdloxc28KLS0tIHNjaWE4dFFyU1FBakhoa0VMZFBT\nTG1FODZGYUQwb2w5Z1pvV2tuS0xFajAKAADHxS6UTmdsAxtbR7ioemPLmxVqTEd/\nD1rhXomfMQ7NSkb5SUh8z7axGxY8BziVheQJWGwdIn6+u2KiI8b1ow==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recipient": "age1tzlyex2z6t88tg9h82943e39shxhmqeyr7ywhlwpdjmyqsndv3qq27x0rf",
|
||||||
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBYYUp4VjV5d05xQWFXRjR2\nd1crNVZyRmtuM05aZHAzNE02NC9zVER4SVRFCjN2c0VlZjh6NUJheEFuSFE1cVlW\nTUhTdjhRNXJXanJFTEhlbGhaRUczVWsKLS0tIGlwRTZBWEhQSzFhY1BYQXdyMVVk\nRUFZcHQ5c1MyaVp5ZVJNamxuc1pXOUEKTsSzOuNOReMPZ99ICOW8/TCQBt8jjP6a\nO9DnwjImazq0i3HKjT+dgNYNlwG+MaUqUNdqIixjbE7s7pskSZlgjw==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recipient": "age18vq5ktwgeaysucvw9t67drqmg5zd5c5k3le34yqxckkfj7wqdqgsd4ejmt",
|
||||||
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBMUGlWNkg3aVpwZnppTUpY\nVzdaeXlHWUhFeTZsTDNkY1B2a1RRajQ5YUJvCmI1a0pOTjlnai91MjIrM1I2d3hI\nd0ZkOGk2WWo0U0hOdnRmaW1FQm8zR3cKLS0tIHBYdnFqdHRHbTM2OHpRcXFNN3Bz\nQUZVNnZSQkUxZGhRM2liSXZTRVRHcWsKGMhYTWmtcRy/WjxD9uWe+iQCEMncebzr\nnkOmOPHOdnvJY+WynTAbHs7nYKKRLizchN7WHLxWah39C5KzmTSQyg==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"lastmodified": "2023-08-13T10:17:15Z",
|
||||||
|
"mac": "ENC[AES256_GCM,data:O3X0JKl6Q8JZxeTR+Zxhd8Ys7ujJM3OP/xLen7eG/cq+/MJgUxoLrRVjnKI5JuNemwcQIdsbOl9aWHB9zP1WXSyvK5mmPtt1OUi5dF27qLhRyDm0aqR8JGboI9LRDuAxXVhqNTpj0iBK5WKpHsAJNwfurkWig2tlfcH2Obgqy0Q=,iv:kAl3VLfMLmkHh7vQAA9xkBmbbYwQcUzJYeTJRl9agz0=,tag:M7UWMdL09WWJhJ/9tvDwxw==,type:str]",
|
||||||
|
"pgp": null,
|
||||||
|
"unencrypted_suffix": "_unencrypted",
|
||||||
|
"version": "3.7.3"
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user