Compare commits
1 Commits
wip-emulat
...
wip/overla
Author | SHA1 | Date | |
---|---|---|---|
5801da97f3 |
@@ -8,7 +8,7 @@ keys:
|
|||||||
- &host_servo age1tzlyex2z6t88tg9h82943e39shxhmqeyr7ywhlwpdjmyqsndv3qq27x0rf
|
- &host_servo age1tzlyex2z6t88tg9h82943e39shxhmqeyr7ywhlwpdjmyqsndv3qq27x0rf
|
||||||
- &host_moby age18vq5ktwgeaysucvw9t67drqmg5zd5c5k3le34yqxckkfj7wqdqgsd4ejmt
|
- &host_moby age18vq5ktwgeaysucvw9t67drqmg5zd5c5k3le34yqxckkfj7wqdqgsd4ejmt
|
||||||
creation_rules:
|
creation_rules:
|
||||||
- path_regex: secrets/common*
|
- path_regex: secrets/universal*
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
- *user_desko_colin
|
- *user_desko_colin
|
||||||
@@ -26,19 +26,19 @@ creation_rules:
|
|||||||
- *user_lappy_colin
|
- *user_lappy_colin
|
||||||
- *user_servo_colin
|
- *user_servo_colin
|
||||||
- *host_servo
|
- *host_servo
|
||||||
- path_regex: secrets/desko*
|
- path_regex: secrets/desko.yaml$
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
- *user_desko_colin
|
- *user_desko_colin
|
||||||
- *user_lappy_colin
|
- *user_lappy_colin
|
||||||
- *host_desko
|
- *host_desko
|
||||||
- path_regex: secrets/lappy*
|
- path_regex: secrets/lappy.yaml$
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
- *user_lappy_colin
|
- *user_lappy_colin
|
||||||
- *user_desko_colin
|
- *user_desko_colin
|
||||||
- *host_lappy
|
- *host_lappy
|
||||||
- path_regex: secrets/moby*
|
- path_regex: secrets/moby.yaml$
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
- *user_desko_colin
|
- *user_desko_colin
|
||||||
|
111
README.md
111
README.md
@@ -1,111 +0,0 @@
|
|||||||
## What's Here
|
|
||||||
|
|
||||||
this is the top-level repo from which i configure/deploy all my NixOS machines:
|
|
||||||
- desktop
|
|
||||||
- laptop
|
|
||||||
- server
|
|
||||||
- mobile phone
|
|
||||||
|
|
||||||
i enjoy a monorepo approach. this repo references [nixpkgs][nixpkgs], a couple 3rd party
|
|
||||||
nix modules like [sops][sops], the sources for [uninsane.org][uninsane-org], and that's
|
|
||||||
about it. custom derivations and modules (some of which i try to upstream) live
|
|
||||||
directly here; even the sources for those packages is often kept here too.
|
|
||||||
|
|
||||||
[nixpkgs]: https://github.com/NixOS/nixpkgs
|
|
||||||
[sops]: https://github.com/Mic92/sops-nix
|
|
||||||
[uninsane-org]: https://uninsane.org
|
|
||||||
|
|
||||||
## Layout
|
|
||||||
- `doc/`
|
|
||||||
- instructions for tasks i find myself doing semi-occasionally in this repo.
|
|
||||||
- `hosts/`
|
|
||||||
- the bulk of config which isn't factored with external use in mind.
|
|
||||||
- that is, if you were to add this repo to a flake.nix for your own use,
|
|
||||||
you won't likely be depending on anything in this directory.
|
|
||||||
- `integrations/`
|
|
||||||
- code intended for consumption by external tools (e.g. the Nix User Repos)
|
|
||||||
- `modules/`
|
|
||||||
- config which is gated behind `enable` flags, in similar style to nixpkgs'
|
|
||||||
`nixos/` directory.
|
|
||||||
- if you depend on this repo, it's most likely for something in this directory.
|
|
||||||
- `nixpatches/`
|
|
||||||
- literally, diffs i apply atop upstream nixpkgs before performing further eval.
|
|
||||||
- `overlays/`
|
|
||||||
- exposed via the `overlays` output in `flake.nix`.
|
|
||||||
- predominantly a list of `callPackage` directives.
|
|
||||||
- `pkgs/`
|
|
||||||
- derivations for things not yet packaged in nixpkgs.
|
|
||||||
- derivations for things from nixpkgs which i need to `override` for some reason.
|
|
||||||
- inline code for wholly custom packages (e.g. `pkgs/additional/sane-scripts/` for CLI tools
|
|
||||||
that are highly specific to my setup).
|
|
||||||
- `scripts/`
|
|
||||||
- scripts which aren't reachable on a deployed system, but may aid manual deployments
|
|
||||||
- `secrets/`
|
|
||||||
- encrypted keys, API tokens, anything which one or more of my machines needs
|
|
||||||
read access to but shouldn't be world-readable.
|
|
||||||
- not much to see here
|
|
||||||
- `templates/`
|
|
||||||
- exposed via the `templates` output in `flake.nix`.
|
|
||||||
- used to instantiate short-lived environments.
|
|
||||||
- used to auto-fill the boiler-plate portions of new packages.
|
|
||||||
|
|
||||||
|
|
||||||
## Key Points of Interest
|
|
||||||
|
|
||||||
i.e. you might find value in using these in your own config:
|
|
||||||
|
|
||||||
- `modules/fs/`
|
|
||||||
- use this to statically define leafs and nodes anywhere in the filesystem,
|
|
||||||
not just inside `/nix/store`.
|
|
||||||
- e.g. specify that `/var/www` should be:
|
|
||||||
- owned by a specific user/group
|
|
||||||
- set to a specific mode
|
|
||||||
- symlinked to some other path
|
|
||||||
- populated with some statically-defined data
|
|
||||||
- populated according to some script
|
|
||||||
- created as a dependency of some service (e.g. `nginx`)
|
|
||||||
- values defined here are applied neither at evaluation time _nor_ at activation time.
|
|
||||||
- rather, they become systemd services.
|
|
||||||
- systemd manages dependencies
|
|
||||||
- e.g. link `/var/www -> /mnt/my-drive/www` only _after_ `/mnt/my-drive/www` appears)
|
|
||||||
- this is akin to using [Home Manager's][home-manager] file API -- the part which lets you
|
|
||||||
statically define `~/.config` files -- just with a different philosophy.
|
|
||||||
- `modules/persist/`
|
|
||||||
- my alternative to the Impermanence module.
|
|
||||||
- this builds atop `modules/fs/` to achieve things stock impermanence can't:
|
|
||||||
- persist things to encrypted storage which is unlocked at login time (pam_mount).
|
|
||||||
- "persist" cache directories -- to free up RAM -- but auto-wipe them on mount
|
|
||||||
and encrypt them to ephemeral keys so they're unreadable post shutdown/unmount.
|
|
||||||
- `modules/programs.nix`
|
|
||||||
- like nixpkgs' `programs` options, but allows both system-wide or per-user deployment.
|
|
||||||
- allows `fs` and `persist` config values to be gated behind program deployment:
|
|
||||||
- e.g. `/home/<user>/.mozilla/firefox` is persisted only for users who
|
|
||||||
`sane.programs.firefox.enableFor.user."<user>" = true;`
|
|
||||||
- `modules/users.nix`
|
|
||||||
- convenience layer atop the above modules so that you can just write
|
|
||||||
`fs.".config/git"` instead of `fs."/home/colin/.config/git"`
|
|
||||||
|
|
||||||
some things in here could easily find broader use. if you would find benefit in
|
|
||||||
them being factored out of my config, message me and we could work to make that happen.
|
|
||||||
|
|
||||||
[home-manager]: https://github.com/nix-community/home-manager
|
|
||||||
|
|
||||||
## Using This Repo In Your Own Config
|
|
||||||
|
|
||||||
this should be a pretty "standard" flake. just reference it, and import either
|
|
||||||
- `nixosModules.sane` (for the modules)
|
|
||||||
- `overlays.pkgs` (for the packages)
|
|
||||||
|
|
||||||
## Mirrors
|
|
||||||
|
|
||||||
this repo exists in a few known locations:
|
|
||||||
- primary: <https://git.uninsane.org/colin/nix-files>
|
|
||||||
- mirror: <https://github.com/nix-community/nur-combined/tree/master/repos/colinsane>
|
|
||||||
|
|
||||||
## Contact
|
|
||||||
|
|
||||||
if you want to contact me for questions, or collaborate to split something useful into a shared repo, etc,
|
|
||||||
you can reach me via any method listed [here](https://uninsane.org/about).
|
|
||||||
patches, for this repo or any other i host, will be warmly welcomed in any manner you see fit:
|
|
||||||
`git send-email`, DM'ing the patch over Matrix/Lemmy/ActivityPub/etc, even a literal PR where you
|
|
||||||
link me to your own clone.
|
|
81
TODO.md
81
TODO.md
@@ -1,81 +0,0 @@
|
|||||||
## BUGS
|
|
||||||
- why i need to manually restart `wireguard-wg-ovpns` on servo periodically
|
|
||||||
- else DNS fails
|
|
||||||
- fix epiphany URL bar input on moby
|
|
||||||
|
|
||||||
## REFACTORING:
|
|
||||||
|
|
||||||
### sops/secrets
|
|
||||||
- attach secrets to the thing they're used by (sane.programs)
|
|
||||||
- rework secrets to leverage `sane.fs`
|
|
||||||
- remove sops activation script as it's covered by my systemd sane.fs impl
|
|
||||||
|
|
||||||
### roles
|
|
||||||
- allow any host to take the role of `uninsane.org`
|
|
||||||
- will make it easier to test new services?
|
|
||||||
|
|
||||||
### upstreaming
|
|
||||||
- split out a sxmo module usable by NUR consumers
|
|
||||||
- bump nodejs version in lemmy-ui
|
|
||||||
- add updateScripts to all my packages in nixpkgs
|
|
||||||
- fix lightdm-mobile-greeter for newer libhandy
|
|
||||||
- port zecwallet-lite to a from-source build
|
|
||||||
- REVIEW/integrate jellyfin dataDir config: <https://github.com/NixOS/nixpkgs/pull/233617>
|
|
||||||
- remove `libsForQt5.callPackage` broadly: <https://github.com/NixOS/nixpkgs/issues/180841>
|
|
||||||
|
|
||||||
|
|
||||||
## IMPROVEMENTS:
|
|
||||||
### security/resilience
|
|
||||||
- validate duplicity backups!
|
|
||||||
- encrypt more ~ dirs (~/archives, ~/records, ..?)
|
|
||||||
- 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?
|
|
||||||
- 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.
|
|
||||||
- **systemd-run** takes a command and runs it in a temporary scope (cgroup)
|
|
||||||
- presumably uses the same options as systemd services
|
|
||||||
- see e.g. <https://github.com/NixOS/nixpkgs/issues/113903#issuecomment-857296349>
|
|
||||||
- flatpak does this, somehow
|
|
||||||
- apparmor? SElinux? (desktop) "portals"?
|
|
||||||
- see Spectrum OS; Alyssa Ross; etc
|
|
||||||
- bubblewrap-based sandboxing: <https://github.com/nixpak/nixpak>
|
|
||||||
- canaries for important services
|
|
||||||
- e.g. daily email checks; daily backup checks
|
|
||||||
- integrate `nix check` into Gitea actions?
|
|
||||||
|
|
||||||
### user experience
|
|
||||||
- neovim: set up language server (lsp; rnix-lsp; nvim-lspconfig)
|
|
||||||
- Helix: make copy-to-system clipboard be the default
|
|
||||||
- firefox/librewolf: persist history
|
|
||||||
- just not cookies or tabs
|
|
||||||
- moby: improve gPodder launch time
|
|
||||||
- moby: theme GTK apps (i.e. non-adwaita styles)
|
|
||||||
- especially, make the menubar collapsible
|
|
||||||
- try Gradience tool specifically for theming adwaita? <https://linuxphoneapps.org/apps/com.github.gradienceteam.gradience/>
|
|
||||||
- package Nix/NixOS docs for Zeal
|
|
||||||
- install [doc-browser](https://github.com/qwfy/doc-browser)
|
|
||||||
- this supports both dash (zeal) *and* the datasets from <https://devdocs.io> (which includes nix!)
|
|
||||||
- install [devhelp](https://wiki.gnome.org/Apps/Devhelp) (gnome)
|
|
||||||
- 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
|
|
||||||
- uninsane.org: make URLs relative to allow local use (and as offline homepage)
|
|
||||||
- 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
|
|
||||||
- could change junk filter from "no DKIM success" to explicit "DKIM failed"
|
|
||||||
|
|
||||||
### perf
|
|
||||||
- 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
|
|
||||||
- would be super handy for package prototyping!
|
|
||||||
- why does nixos-rebuild switch take 5 minutes when net is flakey?
|
|
||||||
- trying to auto-mount servo?
|
|
||||||
- something to do with systemd services restarting/stalling
|
|
||||||
- maybe wireguard & its refresh operation, specifically?
|
|
||||||
- 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
|
|
||||||
|
|
||||||
|
|
||||||
## NEW FEATURES:
|
|
||||||
- migrate MAME cabinet to nix
|
|
||||||
- boot it from PXE from servo?
|
|
||||||
- enable IPv6
|
|
@@ -1,13 +0,0 @@
|
|||||||
to ship `pkgs.foo` on some host, either:
|
|
||||||
- add it as an entry in `suggestedPrograms` to the appropriate category in `hosts/common/programs/assorted.nix`, or
|
|
||||||
- `sane.programs.foo.enableFor.user.colin = true` in `hosts/by-name/myhost/default.nix`
|
|
||||||
|
|
||||||
if the program needs customization (persistence, configs, secrets):
|
|
||||||
- add a file for it at `hosts/common/programs/<foo>.nix`
|
|
||||||
- set the options, `sane.programs.foo.{fs,persist}`
|
|
||||||
|
|
||||||
if it's unclear what fs paths a program uses:
|
|
||||||
- run one of these commands, launch the program, run it again, and `diff`:
|
|
||||||
- `du -x --apparent-size ~`
|
|
||||||
- `find ~ -xdev`
|
|
||||||
- or, inspect the whole tmpfs root with `ncdu -x /`
|
|
149
flake.lock
generated
149
flake.lock
generated
@@ -1,15 +1,12 @@
|
|||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"flake-utils": {
|
"flake-utils": {
|
||||||
"inputs": {
|
|
||||||
"systems": "systems"
|
|
||||||
},
|
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1687709756,
|
"lastModified": 1659877975,
|
||||||
"narHash": "sha256-Y5wKlQSkgEK2weWdOu4J3riRd+kV/VCgHsqLNTTWQ/0=",
|
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "dbabf0ca0c0c4bce6ea5eaf65af5cb694d2082c7",
|
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -18,14 +15,35 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"home-manager": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1667907331,
|
||||||
|
"narHash": "sha256-bHkAwkYlBjkupPUFcQjimNS8gxWSWjOTevEuwdnp5m0=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "home-manager",
|
||||||
|
"rev": "6639e3a837fc5deb6f99554072789724997bc8e5",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"ref": "release-22.05",
|
||||||
|
"repo": "home-manager",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"mobile-nixos": {
|
"mobile-nixos": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1690059310,
|
"lastModified": 1670131242,
|
||||||
"narHash": "sha256-4zcoDp8wwZVfGSzXltC5x+eH4kDWC/eJpyQNgr7shAA=",
|
"narHash": "sha256-T/o1/3gffr010fsqgNshs1NJJjsnUYvQnUZgm6hilsY=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "mobile-nixos",
|
"repo": "mobile-nixos",
|
||||||
"rev": "56fc9f9619f305f0865354975a98d22410eed127",
|
"rev": "5ee45cc1f8e43f4af14ee17ccef9156b0db8cd77",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -34,75 +52,75 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nix-serve": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": "nixpkgs"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1687251388,
|
|
||||||
"narHash": "sha256-E9cVlgeCvzPbA/G3mCDCzz8TdRwXyGYzIjmwcvIfghg=",
|
|
||||||
"owner": "edolstra",
|
|
||||||
"repo": "nix-serve",
|
|
||||||
"rev": "d6df5bd8584f37e22cff627db2fc4058a4aab5ee",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "edolstra",
|
|
||||||
"repo": "nix-serve",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs-unpatched"
|
||||||
|
]
|
||||||
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1606086654,
|
"lastModified": 1,
|
||||||
"narHash": "sha256-VFl+3eGIMqNp7cyOMJ6TjM/+UcsLKtodKoYexrlTJMI=",
|
"narHash": "sha256-5eJxyBRYQCoRt92ZFUOdT237Z0VscuNRd0pktDYWJYE=",
|
||||||
"owner": "NixOS",
|
"path": "nixpatches",
|
||||||
"repo": "nixpkgs",
|
"type": "path"
|
||||||
"rev": "19db3e5ea2777daa874563b5986288151f502e27",
|
|
||||||
"type": "github"
|
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"id": "nixpkgs",
|
"path": "nixpatches",
|
||||||
"ref": "nixos-20.09",
|
"type": "path"
|
||||||
"type": "indirect"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs-stable": {
|
"nixpkgs-stable": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1690066826,
|
"lastModified": 1673163619,
|
||||||
"narHash": "sha256-6L2qb+Zc0BFkh72OS9uuX637gniOjzU6qCDBpjB2LGY=",
|
"narHash": "sha256-B33PFBL64ZgTWgMnhFL3jgheAN/DjHPsZ1Ih3z0VE5I=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "ce45b591975d070044ca24e3003c830d26fea1c8",
|
"rev": "8c54d842d9544361aac5f5b212ba04e4089e8efe",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"id": "nixpkgs",
|
||||||
|
"ref": "nixos-22.11",
|
||||||
|
"type": "indirect"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs-stable_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1673100377,
|
||||||
|
"narHash": "sha256-mT76pTd0YFxT6CwtPhDgHJhuIgLY+ZLSMiQpBufwMG4=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "9f11a2df77cb945c115ae2a65f53f38121597d73",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"ref": "release-23.05",
|
"ref": "release-22.11",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs-unpatched": {
|
"nixpkgs-unpatched": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1691006197,
|
"lastModified": 1673226411,
|
||||||
"narHash": "sha256-DbtxVWPt+ZP5W0Usg7jAyTomIM//c3Jtfa59Ht7AV8s=",
|
"narHash": "sha256-b6cGb5Ln7Zy80YO66+cbTyGdjZKtkoqB/iIIhDX9gRA=",
|
||||||
"owner": "nixos",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "66aedfd010204949cb225cf749be08cb13ce1813",
|
"rev": "aa1d74709f5dac623adb4d48fdfb27cc2c92a4d4",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "nixos",
|
"id": "nixpkgs",
|
||||||
"ref": "nixos-unstable",
|
"ref": "nixos-unstable",
|
||||||
"repo": "nixpkgs",
|
"type": "indirect"
|
||||||
"type": "github"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
|
"home-manager": "home-manager",
|
||||||
"mobile-nixos": "mobile-nixos",
|
"mobile-nixos": "mobile-nixos",
|
||||||
"nix-serve": "nix-serve",
|
"nixpkgs": "nixpkgs",
|
||||||
|
"nixpkgs-stable": "nixpkgs-stable",
|
||||||
"nixpkgs-unpatched": "nixpkgs-unpatched",
|
"nixpkgs-unpatched": "nixpkgs-unpatched",
|
||||||
"sops-nix": "sops-nix",
|
"sops-nix": "sops-nix",
|
||||||
"uninsane-dot-org": "uninsane-dot-org"
|
"uninsane-dot-org": "uninsane-dot-org"
|
||||||
@@ -111,16 +129,16 @@
|
|||||||
"sops-nix": {
|
"sops-nix": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nixpkgs-unpatched"
|
"nixpkgs"
|
||||||
],
|
],
|
||||||
"nixpkgs-stable": "nixpkgs-stable"
|
"nixpkgs-stable": "nixpkgs-stable_2"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1690199016,
|
"lastModified": 1673147300,
|
||||||
"narHash": "sha256-yTLL72q6aqGmzHq+C3rDp3rIjno7EJZkFLof6Ika7cE=",
|
"narHash": "sha256-gR9OEfTzWfL6vG0qkbn1TlBAOlg4LuW8xK/u0V41Ihc=",
|
||||||
"owner": "Mic92",
|
"owner": "Mic92",
|
||||||
"repo": "sops-nix",
|
"repo": "sops-nix",
|
||||||
"rev": "c36df4fe4bf4bb87759b1891cab21e7a05219500",
|
"rev": "2253120d2a6147e57bafb5c689e086221df8032f",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -129,34 +147,19 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"systems": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681028828,
|
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"uninsane-dot-org": {
|
"uninsane-dot-org": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-utils": "flake-utils",
|
"flake-utils": "flake-utils",
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nixpkgs-unpatched"
|
"nixpkgs"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1691106178,
|
"lastModified": 1666870107,
|
||||||
"narHash": "sha256-3mZ9gTvMpbZA9ea9ovoQpn2wKuQY0QZ7MDdEjArYdAQ=",
|
"narHash": "sha256-b9eXZxSwhzdJI5uQgfrMhu4SY2POrPkinUg7F5gQVYo=",
|
||||||
"ref": "refs/heads/master",
|
"ref": "refs/heads/master",
|
||||||
"rev": "f4d91aa201b6e49af690f250d4786bd1d8b4dcfd",
|
"rev": "80c6ec95bd430e29d231cf745f19279bb76fb382",
|
||||||
"revCount": 205,
|
"revCount": 164,
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://git.uninsane.org/colin/uninsane"
|
"url": "https://git.uninsane.org/colin/uninsane"
|
||||||
},
|
},
|
||||||
|
310
flake.nix
310
flake.nix
@@ -1,153 +1,81 @@
|
|||||||
# FLAKE FEEDBACK:
|
# docs:
|
||||||
# - if flake inputs are meant to be human-readable, a human should be able to easily track them down given the URL.
|
# - <https://nixos.wiki/wiki/Flakes>
|
||||||
# - this is not the case with registry URLs, like `nixpkgs/nixos-22.11`.
|
|
||||||
# - this is marginally the case with schemes like `github:nixos/nixpkgs`.
|
|
||||||
# - given the *existing* `git+https://` scheme, i propose expressing github URLs similarly:
|
|
||||||
# - `github+https://github.com/nixos/nixpkgs/tree/nixos-22.11`
|
|
||||||
# - need some way to apply local patches to inputs.
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# DEVELOPMENT DOCS:
|
|
||||||
# - Flake docs: <https://nixos.wiki/wiki/Flakes>
|
|
||||||
# - Flake RFC: <https://github.com/tweag/rfcs/blob/flakes/rfcs/0049-flakes.md>
|
|
||||||
# - Discussion: <https://github.com/NixOS/rfcs/pull/49>
|
|
||||||
# - <https://serokell.io/blog/practical-nix-flakes>
|
# - <https://serokell.io/blog/practical-nix-flakes>
|
||||||
#
|
|
||||||
#
|
|
||||||
# COMMON OPERATIONS:
|
|
||||||
# - update a specific flake input:
|
|
||||||
# - `nix flake lock --update-input nixpkgs`
|
|
||||||
|
|
||||||
{
|
{
|
||||||
# XXX: use the `github:` scheme instead of the more readable git+https: because it's *way* more efficient
|
|
||||||
# preferably, i would rewrite the human-readable https URLs to nix-specific github: URLs with a helper,
|
|
||||||
# but `inputs` is required to be a strict attrset: not an expression.
|
|
||||||
inputs = {
|
inputs = {
|
||||||
# branch workflow:
|
nixpkgs-stable.url = "nixpkgs/nixos-22.11";
|
||||||
# - daily:
|
nixpkgs-unpatched.url = "nixpkgs/nixos-unstable";
|
||||||
# - nixos-unstable cut from master after enough packages have been built in caches.
|
nixpkgs = {
|
||||||
# - every 6 hours:
|
url = "path:nixpatches";
|
||||||
# - master auto-merged into staging.
|
inputs.nixpkgs.follows = "nixpkgs-unpatched";
|
||||||
# - staging-next auto-merged into staging.
|
};
|
||||||
# - manually, approximately once per month:
|
|
||||||
# - staging-next is cut from staging.
|
|
||||||
# - staging-next merged into master.
|
|
||||||
#
|
|
||||||
# which branch to source from?
|
|
||||||
# - for everyday development, prefer `nixos-unstable` branch, as it provides good caching.
|
|
||||||
# - if need to test bleeding updates (e.g. if submitting code into staging):
|
|
||||||
# - use `staging-next` if it's been cut (i.e. if there's an active staging-next -> master PR)
|
|
||||||
# - use `staging` if no staging-next branch has been cut.
|
|
||||||
#
|
|
||||||
# <https://github.com/nixos/nixpkgs/tree/nixos-unstable>
|
|
||||||
nixpkgs-unpatched.url = "github:nixos/nixpkgs?ref=nixos-unstable";
|
|
||||||
# nixpkgs-unpatched.url = "github:nixos/nixpkgs?ref=staging-next";
|
|
||||||
# nixpkgs-unpatched.url = "github:nixos/nixpkgs?ref=staging";
|
|
||||||
|
|
||||||
mobile-nixos = {
|
mobile-nixos = {
|
||||||
# <https://github.com/nixos/mobile-nixos>
|
|
||||||
url = "github:nixos/mobile-nixos";
|
url = "github:nixos/mobile-nixos";
|
||||||
flake = false;
|
flake = false;
|
||||||
};
|
};
|
||||||
|
home-manager = {
|
||||||
|
url = "github:nix-community/home-manager/release-22.05";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
sops-nix = {
|
sops-nix = {
|
||||||
# <https://github.com/Mic92/sops-nix>
|
|
||||||
url = "github:Mic92/sops-nix";
|
url = "github:Mic92/sops-nix";
|
||||||
# inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
inputs.nixpkgs.follows = "nixpkgs-unpatched";
|
|
||||||
};
|
};
|
||||||
uninsane-dot-org = {
|
uninsane-dot-org = {
|
||||||
url = "git+https://git.uninsane.org/colin/uninsane";
|
url = "git+https://git.uninsane.org/colin/uninsane";
|
||||||
# inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
inputs.nixpkgs.follows = "nixpkgs-unpatched";
|
|
||||||
};
|
|
||||||
nix-serve = {
|
|
||||||
# <https://github.com/edolstra/nix-serve>
|
|
||||||
url = "github:edolstra/nix-serve";
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = {
|
outputs = {
|
||||||
self,
|
self,
|
||||||
|
nixpkgs,
|
||||||
|
nixpkgs-stable,
|
||||||
nixpkgs-unpatched,
|
nixpkgs-unpatched,
|
||||||
mobile-nixos,
|
mobile-nixos,
|
||||||
|
home-manager,
|
||||||
sops-nix,
|
sops-nix,
|
||||||
uninsane-dot-org,
|
uninsane-dot-org
|
||||||
nix-serve,
|
}:
|
||||||
...
|
|
||||||
}@inputs:
|
|
||||||
let
|
let
|
||||||
inherit (builtins) attrNames elem listToAttrs map mapAttrs;
|
nixpkgsCompiledBy = local: nixpkgs.legacyPackages."${local}";
|
||||||
mapAttrs' = f: set:
|
|
||||||
listToAttrs (map (attr: f attr set.${attr}) (attrNames set));
|
|
||||||
# mapAttrs but without the `name` argument
|
|
||||||
mapAttrValues = f: mapAttrs (_: f);
|
|
||||||
# rather than apply our nixpkgs patches as a flake input, do that here instead.
|
|
||||||
# this (temporarily?) resolves the bad UX wherein a subflake residing in the same git
|
|
||||||
# repo as the main flake causes the main flake to have an unstable hash.
|
|
||||||
nixpkgs = (import ./nixpatches/flake.nix).outputs {
|
|
||||||
self = nixpkgs;
|
|
||||||
nixpkgs = nixpkgs-unpatched;
|
|
||||||
};
|
|
||||||
|
|
||||||
nixpkgsCompiledBy = system: nixpkgs.legacyPackages."${system}";
|
evalHost = { name, local, target }:
|
||||||
|
let
|
||||||
evalHost = { name, local, target }: nixpkgs.lib.nixosSystem {
|
# XXX: we'd prefer to use `nixosSystem = (nixpkgsCompiledBy local).nixos`
|
||||||
|
# but it doesn't propagate config to the underlying pkgs, meaning it doesn't let you use
|
||||||
|
# non-free packages even after setting nixpkgs.allowUnfree.
|
||||||
|
nixosSystem = import ((nixpkgsCompiledBy local).path + "/nixos/lib/eval-config.nix");
|
||||||
|
in
|
||||||
|
(nixosSystem {
|
||||||
|
# we use pkgs built for and *by* the target, i.e. emulation, by default.
|
||||||
|
# cross compilation only happens on explicit access to `pkgs.cross`
|
||||||
system = target;
|
system = target;
|
||||||
modules = [
|
modules = [
|
||||||
{
|
(import ./hosts/instantiate.nix { localSystem = local; hostName = name; })
|
||||||
nixpkgs = (if (local != null) then {
|
|
||||||
buildPlatform = local;
|
|
||||||
} else {}) // {
|
|
||||||
# TODO: does the earlier `system` arg to nixosSystem make its way here?
|
|
||||||
hostPlatform.system = target;
|
|
||||||
};
|
|
||||||
# nixpkgs.buildPlatform = local; # set by instantiate.nix instead
|
|
||||||
# nixpkgs.config.replaceStdenv = { pkgs }: pkgs.ccacheStdenv;
|
|
||||||
}
|
|
||||||
(import ./hosts/instantiate.nix { hostName = name; })
|
|
||||||
self.nixosModules.default
|
self.nixosModules.default
|
||||||
self.nixosModules.passthru
|
self.nixosModules.passthru
|
||||||
{
|
{
|
||||||
nixpkgs.overlays = [
|
nixpkgs.overlays = [
|
||||||
|
self.overlays.default
|
||||||
self.overlays.passthru
|
self.overlays.passthru
|
||||||
self.overlays.sane-all
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
};
|
});
|
||||||
in {
|
in {
|
||||||
nixosConfigurations =
|
nixosConfigurations = {
|
||||||
let
|
servo = evalHost { name = "servo"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
||||||
hosts = {
|
desko = evalHost { name = "desko"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
||||||
servo = { name = "servo"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
lappy = evalHost { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
||||||
desko = { name = "desko"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
moby = evalHost { name = "moby"; local = "aarch64-linux"; target = "aarch64-linux"; };
|
||||||
lappy = { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
# special cross-compiled variant, to speed up deploys from an x86 box to the arm target
|
||||||
moby = { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; };
|
# note that these *do* produce different store paths, because the closure for the tools used to cross compile
|
||||||
rescue = { name = "rescue"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
# v.s. emulate differ.
|
||||||
};
|
# so deploying foo-cross and then foo incurs some rebuilding.
|
||||||
# cross-compiled builds: instead of emulating the host, build using a cross-compiler.
|
moby-cross = evalHost { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; };
|
||||||
# - these are faster to *build* than the emulated variants (useful when tweaking packages),
|
rescue = evalHost { name = "rescue"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
||||||
# - but fewer of their packages can be found in upstream caches.
|
|
||||||
cross = mapAttrValues evalHost hosts;
|
|
||||||
emulated = mapAttrValues
|
|
||||||
({name, local, target}: evalHost {
|
|
||||||
inherit name target;
|
|
||||||
local = null;
|
|
||||||
})
|
|
||||||
hosts;
|
|
||||||
prefixAttrs = prefix: attrs: mapAttrs'
|
|
||||||
(name: value: {
|
|
||||||
name = prefix + name;
|
|
||||||
inherit value;
|
|
||||||
})
|
|
||||||
attrs;
|
|
||||||
in
|
|
||||||
(prefixAttrs "cross-" cross) //
|
|
||||||
(prefixAttrs "emulated-" emulated) // {
|
|
||||||
# prefer native builds for these machines:
|
|
||||||
inherit (emulated) servo desko lappy rescue;
|
|
||||||
# prefer cross-compiled builds for these machines:
|
|
||||||
inherit (cross) moby;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
# unofficial output
|
# unofficial output
|
||||||
@@ -164,38 +92,21 @@
|
|||||||
# - if fs wasn't resized automatically, then `sudo btrfs filesystem resize max /`
|
# - if fs wasn't resized automatically, then `sudo btrfs filesystem resize max /`
|
||||||
# - checkout this flake into /etc/nixos AND UPDATE THE FS UUIDS.
|
# - checkout this flake into /etc/nixos AND UPDATE THE FS UUIDS.
|
||||||
# - `nixos-rebuild --flake './#<host>' switch`
|
# - `nixos-rebuild --flake './#<host>' switch`
|
||||||
imgs = mapAttrValues (host: host.config.system.build.img) self.nixosConfigurations;
|
imgs = builtins.mapAttrs (_: host-dfn: host-dfn.config.system.build.img) self.nixosConfigurations;
|
||||||
|
|
||||||
# unofficial output
|
overlays = rec {
|
||||||
host-pkgs = mapAttrValues (host: host.config.system.build.pkgs) self.nixosConfigurations;
|
default = pkgs;
|
||||||
host-programs = mapAttrValues (host: mapAttrValues (p: p.package) host.config.sane.programs) self.nixosConfigurations;
|
pkgs = import ./pkgs/overlay.nix;
|
||||||
|
passthru =
|
||||||
overlays = {
|
|
||||||
# N.B.: `nix flake check` requires every overlay to take `final: prev:` at defn site,
|
|
||||||
# hence the weird redundancy.
|
|
||||||
default = final: prev: self.overlays.pkgs final prev;
|
|
||||||
sane-all = final: prev: import ./overlays/all.nix final prev;
|
|
||||||
disable-flakey-tests = final: prev: import ./overlays/disable-flakey-tests.nix final prev;
|
|
||||||
pkgs = final: prev: import ./overlays/pkgs.nix final prev;
|
|
||||||
pins = final: prev: import ./overlays/pins.nix final prev;
|
|
||||||
preferences = final: prev: import ./overlays/preferences.nix final prev;
|
|
||||||
optimizations = final: prev: import ./overlays/optimizations.nix final prev;
|
|
||||||
passthru = final: prev:
|
|
||||||
let
|
let
|
||||||
|
stable = next: prev: {
|
||||||
|
stable = nixpkgs-stable.legacyPackages."${prev.stdenv.hostPlatform}";
|
||||||
|
};
|
||||||
mobile = (import "${mobile-nixos}/overlay/overlay.nix");
|
mobile = (import "${mobile-nixos}/overlay/overlay.nix");
|
||||||
uninsane = uninsane-dot-org.overlay;
|
uninsane = uninsane-dot-org.overlay;
|
||||||
# nix-serve' = nix-serve.overlay;
|
|
||||||
nix-serve' = next: prev: {
|
|
||||||
# XXX(2023/03/02): upstream isn't compatible with modern `nix`. probably the perl bindings.
|
|
||||||
# - we use the package built against `nixpkgs` specified in its flake rather than use its overlay,
|
|
||||||
# to get around this.
|
|
||||||
inherit (nix-serve.packages."${next.system}") nix-serve;
|
|
||||||
};
|
|
||||||
in
|
in
|
||||||
(mobile final prev)
|
next: prev:
|
||||||
// (uninsane final prev)
|
(stable next prev) // (mobile next prev) // (uninsane next prev);
|
||||||
// (nix-serve' final prev)
|
|
||||||
;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
nixosModules = rec {
|
nixosModules = rec {
|
||||||
@@ -203,6 +114,7 @@
|
|||||||
sane = import ./modules;
|
sane = import ./modules;
|
||||||
passthru = { ... }: {
|
passthru = { ... }: {
|
||||||
imports = [
|
imports = [
|
||||||
|
home-manager.nixosModule
|
||||||
sops-nix.nixosModules.sops
|
sops-nix.nixosModules.sops
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
@@ -219,129 +131,35 @@
|
|||||||
aarch64-linux = allPkgsFor "aarch64-linux";
|
aarch64-linux = allPkgsFor "aarch64-linux";
|
||||||
};
|
};
|
||||||
|
|
||||||
# extract only our own packages from the full set.
|
# extract only our own packages from the full set
|
||||||
# because of `nix flake check`, we flatten the package set and only surface x86_64-linux packages.
|
packages = builtins.mapAttrs
|
||||||
packages = mapAttrs
|
(_: full: full.sane // { inherit (full) sane uninsane-dot-org; })
|
||||||
(system: allPkgs:
|
self.legacyPackages;
|
||||||
allPkgs.lib.filterAttrs (name: pkg:
|
|
||||||
# keep only packages which will pass `nix flake check`, i.e. keep only:
|
|
||||||
# - derivations (not package sets)
|
|
||||||
# - packages that build for the given platform
|
|
||||||
(! elem name [ "feeds" "pythonPackagesExtensions" ])
|
|
||||||
&& (allPkgs.lib.meta.availableOn allPkgs.stdenv.hostPlatform pkg)
|
|
||||||
)
|
|
||||||
(
|
|
||||||
# expose sane packages and chosen inputs (uninsane.org)
|
|
||||||
(import ./pkgs { pkgs = allPkgs; }) // {
|
|
||||||
inherit (allPkgs) uninsane-dot-org;
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
# self.legacyPackages;
|
|
||||||
{ inherit (self.legacyPackages) x86_64-linux; }
|
|
||||||
;
|
|
||||||
|
|
||||||
apps."x86_64-linux" =
|
apps."x86_64-linux" =
|
||||||
let
|
let
|
||||||
pkgs = self.legacyPackages."x86_64-linux";
|
pkgs = self.legacyPackages."x86_64-linux";
|
||||||
deployScript = host: addr: action: pkgs.writeShellScript "deploy-${host}" ''
|
|
||||||
nix build '.#nixosConfigurations.${host}.config.system.build.toplevel' --out-link ./result-${host} $@
|
|
||||||
sudo nix sign-paths -r -k /run/secrets/nix_serve_privkey $(readlink ./result-${host})
|
|
||||||
|
|
||||||
# XXX: this triggers another config eval & (potentially) build.
|
|
||||||
# if the config changed between these invocations, the above signatures might not apply to the deployed config.
|
|
||||||
# let the user handle that edge case by re-running this whole command
|
|
||||||
nixos-rebuild --flake '.#${host}' ${action} --target-host colin@${addr} --use-remote-sudo $@
|
|
||||||
'';
|
|
||||||
in {
|
in {
|
||||||
help = {
|
|
||||||
type = "app";
|
|
||||||
program = let
|
|
||||||
helpMsg = builtins.toFile "nixos-config-help-message" ''
|
|
||||||
commands:
|
|
||||||
- `nix run '.#help'`
|
|
||||||
- show this message
|
|
||||||
- `nix run '.#update-feeds'`
|
|
||||||
- updates metadata for all feeds
|
|
||||||
- `nix run '.#init-feed' <url>`
|
|
||||||
- `nix run '.#deploy-{lappy,moby,moby-test,servo}' [nixos-rebuild args ...]`
|
|
||||||
- `nix run '.#check-nur'`
|
|
||||||
'';
|
|
||||||
in builtins.toString (pkgs.writeShellScript "nixos-config-help" ''
|
|
||||||
cat ${helpMsg}
|
|
||||||
'');
|
|
||||||
};
|
|
||||||
update-feeds = {
|
update-feeds = {
|
||||||
type = "app";
|
type = "app";
|
||||||
program = "${pkgs.feeds.updateScript}";
|
program = "${pkgs.feeds.passthru.updateScript}";
|
||||||
};
|
};
|
||||||
|
|
||||||
init-feed = {
|
init-feed = {
|
||||||
type = "app";
|
type = "app";
|
||||||
program = "${pkgs.feeds.initFeedScript}";
|
program = "${pkgs.feeds.passthru.initFeedScript}";
|
||||||
};
|
|
||||||
|
|
||||||
deploy-lappy = {
|
|
||||||
type = "app";
|
|
||||||
program = ''${deployScript "lappy" "lappy" "switch"}'';
|
|
||||||
};
|
|
||||||
deploy-moby-test = {
|
|
||||||
type = "app";
|
|
||||||
program = ''${deployScript "moby" "moby-hn" "test"}'';
|
|
||||||
};
|
|
||||||
deploy-moby = {
|
|
||||||
type = "app";
|
|
||||||
program = ''${deployScript "moby" "moby-hn" "switch"}'';
|
|
||||||
};
|
|
||||||
deploy-servo = {
|
|
||||||
type = "app";
|
|
||||||
program = ''${deployScript "servo" "servo" "switch"}'';
|
|
||||||
};
|
|
||||||
|
|
||||||
check-nur = {
|
|
||||||
# `nix run '.#check-nur'`
|
|
||||||
# validates that my repo can be included in the Nix User Repository
|
|
||||||
type = "app";
|
|
||||||
program = builtins.toString (pkgs.writeShellScript "check-nur" ''
|
|
||||||
cd ${./.}/integrations/nur
|
|
||||||
NIX_PATH= NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM=1 nix-env -f . -qa \* --meta --xml \
|
|
||||||
--allowed-uris https://static.rust-lang.org \
|
|
||||||
--option restrict-eval true \
|
|
||||||
--option allow-import-from-derivation true \
|
|
||||||
--drv-path --show-trace \
|
|
||||||
-I nixpkgs=$(nix-instantiate --find-file nixpkgs) \
|
|
||||||
-I ../../
|
|
||||||
'');
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
templates = {
|
templates = {
|
||||||
env.python-data = {
|
python-data = {
|
||||||
# initialize with:
|
# initialize with:
|
||||||
# - `nix flake init -t '/home/colin/dev/nixos/#env.python-data'`
|
# - `nix flake init -t '/home/colin/dev/nixos/#python-data'`
|
||||||
# then enter with:
|
# then enter with:
|
||||||
# - `nix develop`
|
# - `nix develop`
|
||||||
path = ./templates/env/python-data;
|
path = ./templates/python-data;
|
||||||
description = "python environment for data processing";
|
description = "python environment for data processing";
|
||||||
};
|
};
|
||||||
pkgs.rust-inline = {
|
|
||||||
# initialize with:
|
|
||||||
# - `nix flake init -t '/home/colin/dev/nixos/#pkgs.rust-inline'`
|
|
||||||
path = ./templates/pkgs/rust-inline;
|
|
||||||
description = "rust package and development environment (inline rust sources)";
|
|
||||||
};
|
|
||||||
pkgs.rust = {
|
|
||||||
# initialize with:
|
|
||||||
# - `nix flake init -t '/home/colin/dev/nixos/#pkgs.rust'`
|
|
||||||
path = ./templates/pkgs/rust;
|
|
||||||
description = "rust package fit to ship in nixpkgs";
|
|
||||||
};
|
|
||||||
pkgs.make = {
|
|
||||||
# initialize with:
|
|
||||||
# - `nix flake init -t '/home/colin/dev/nixos/#pkgs.make'`
|
|
||||||
path = ./templates/pkgs/make;
|
|
||||||
description = "default Makefile-based derivation";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +0,0 @@
|
|||||||
## directory structure
|
|
||||||
- by-name/<hostname>: configuration which is evaluated _only_ for the given hostname
|
|
||||||
- common/: configuration which applies to all hosts
|
|
||||||
- modules/: nixpkgs-style modules which may be used by multiple hosts, but configured separately per host.
|
|
||||||
- ideally no module here has effect unless `enable`d
|
|
||||||
- however, `enable` may default to true
|
|
||||||
- and in practice some of these modules surely aren't fully "disableable"
|
|
@@ -1,38 +0,0 @@
|
|||||||
# doesn't actually *enable* anything,
|
|
||||||
# but sets up any modules such that if they *were* enabled, they'll act as expected.
|
|
||||||
{ pkgs, ... }:
|
|
||||||
{
|
|
||||||
sane.gui.sxmo = {
|
|
||||||
greeter = "sway";
|
|
||||||
settings = {
|
|
||||||
# XXX: make sure the user is part of the `input` group!
|
|
||||||
SXMO_LISGD_INPUT_DEVICE = "/dev/input/by-id/usb-Wacom_Co._Ltd._Pen_and_multitouch_sensor-event-if00";
|
|
||||||
# these identifiers are from `swaymsg -t get_inputs`
|
|
||||||
SXMO_VOLUME_BUTTON = "1:1:AT_Translated_Set_2_keyboard";
|
|
||||||
# SXMO_VOLUME_BUTTON = "none";
|
|
||||||
SXMO_POWER_BUTTON = "0:1:Power_Button";
|
|
||||||
# SXMO_POWER_BUTTON = "none";
|
|
||||||
SXMO_DISABLE_LEDS = "1";
|
|
||||||
SXMO_UNLOCK_IDLE_TIME = "120"; # default
|
|
||||||
# sxmo tries to determine device type from /proc/device-tree/compatible,
|
|
||||||
# but that doesn't seem to exist on NixOS? (or maybe it just doesn't exist
|
|
||||||
# on non-aarch64 builds).
|
|
||||||
# the device type informs (at least):
|
|
||||||
# - SXMO_WIFI_MODULE
|
|
||||||
# - SXMO_RTW_SCAN_INTERVAL
|
|
||||||
# - SXMO_SYS_FILES
|
|
||||||
# - SXMO_TOUCHSCREEN_ID
|
|
||||||
# - SXMO_MONITOR
|
|
||||||
# - SXMO_ALSA_CONTROL_NAME
|
|
||||||
# - SXMO_SWAY_SCALE
|
|
||||||
# see <repo:mil/sxmo-utils:scripts/deviceprofiles>
|
|
||||||
# SXMO_DEVICE_NAME = "pine64,pinephone-1.2";
|
|
||||||
};
|
|
||||||
package = pkgs.sxmo-utils.overrideAttrs (base: {
|
|
||||||
postPatch = (base.postPatch or "") + ''
|
|
||||||
# after volume-button navigation mode, restore full keyboard functionality
|
|
||||||
cp ${./xkb_mobile_normal_buttons} ./configs/xkb/xkb_mobile_normal_buttons
|
|
||||||
'';
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,7 +0,0 @@
|
|||||||
xkb_keymap {
|
|
||||||
xkb_keycodes { include "evdev+aliases(qwerty)" };
|
|
||||||
xkb_types { include "complete" };
|
|
||||||
xkb_compat { include "complete" };
|
|
||||||
xkb_symbols { include "pc+us+inet(evdev)" };
|
|
||||||
xkb_geometry { include "pc(pc105)" };
|
|
||||||
};
|
|
@@ -1,163 +0,0 @@
|
|||||||
# Pinephone
|
|
||||||
# other setups to reference:
|
|
||||||
# - <https://hamblingreen.gitlab.io/2022/03/02/my-pinephone-setup.html>
|
|
||||||
# - sxmo Arch user. lots of app recommendations
|
|
||||||
#
|
|
||||||
# wikis, resources, ...:
|
|
||||||
# - Linux Phone Apps: <https://linuxphoneapps.org/>
|
|
||||||
# - massive mobile-friendly app database
|
|
||||||
# - Mobian wiki: <https://wiki.mobian-project.org/doku.php?id=start>
|
|
||||||
# - recommended apps, chatrooms
|
|
||||||
|
|
||||||
{ config, pkgs, lib, ... }:
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
./bootloader.nix
|
|
||||||
./fs.nix
|
|
||||||
./gps.nix
|
|
||||||
./kernel.nix
|
|
||||||
./polyfill.nix
|
|
||||||
];
|
|
||||||
|
|
||||||
sane.roles.client = true;
|
|
||||||
sane.zsh.showDeadlines = false; # unlikely to act on them when in shell
|
|
||||||
sane.services.wg-home.enable = true;
|
|
||||||
sane.services.wg-home.ip = config.sane.hosts.by-name."moby".wg-home.ip;
|
|
||||||
|
|
||||||
# XXX colin: phosh doesn't work well with passwordless login,
|
|
||||||
# so set this more reliable default password should anything go wrong
|
|
||||||
users.users.colin.initialPassword = "147147";
|
|
||||||
services.getty.autologinUser = "root"; # allows for emergency maintenance?
|
|
||||||
|
|
||||||
sops.secrets.colin-passwd.neededForUsers = true;
|
|
||||||
|
|
||||||
sane.user.persist.plaintext = [
|
|
||||||
# TODO: make this just generally conditional upon pulse being enabled?
|
|
||||||
".config/pulse" # persist pulseaudio volume
|
|
||||||
];
|
|
||||||
|
|
||||||
sane.gui.sxmo.enable = true;
|
|
||||||
sane.programs.guiApps.suggestedPrograms = [ "handheldGuiApps" ];
|
|
||||||
# sane.programs.consoleUtils.enableFor.user.colin = false;
|
|
||||||
# sane.programs.guiApps.enableFor.user.colin = false;
|
|
||||||
sane.programs.sequoia.enableFor.user.colin = false;
|
|
||||||
sane.programs.tuiApps.enableFor.user.colin = false; # visidata, others, don't compile well
|
|
||||||
# disabled for faster deploys
|
|
||||||
sane.programs.soundconverter.enableFor.user.colin = false;
|
|
||||||
|
|
||||||
# sane.programs.firefox.mime.priority = 300; # prefer other browsers when possible
|
|
||||||
# HACK/TODO: make `programs.P.env.VAR` behave according to `mime.priority`
|
|
||||||
# sane.programs.firefox.env = lib.mkForce {};
|
|
||||||
# sane.programs.epiphany.env.BROWSER = "epiphany";
|
|
||||||
# sane.programs.firefox.enableFor.user.colin = false; # use epiphany instead
|
|
||||||
|
|
||||||
# sane.programs.mpv.enableFor.user.colin = true;
|
|
||||||
|
|
||||||
boot.loader.efi.canTouchEfiVariables = false;
|
|
||||||
# /boot space is at a premium. default was 20.
|
|
||||||
# even 10 can be too much
|
|
||||||
boot.loader.generic-extlinux-compatible.configurationLimit = 8;
|
|
||||||
# mobile.bootloader.enable = false;
|
|
||||||
# mobile.boot.stage-1.enable = false;
|
|
||||||
# boot.initrd.systemd.enable = false;
|
|
||||||
# boot.initrd.services.swraid.enable = false; # attempt to fix dm_mod stuff
|
|
||||||
# disable proximity sensor.
|
|
||||||
# the filtering/calibration is bad that it causes the screen to go fully dark at times.
|
|
||||||
boot.blacklistedKernelModules = [ "stk3310" ];
|
|
||||||
|
|
||||||
# without this some GUI apps fail: `DRM_IOCTL_MODE_CREATE_DUMB failed: Cannot allocate memory`
|
|
||||||
# this is because they can't allocate enough video ram.
|
|
||||||
# the default CMA seems to be 32M.
|
|
||||||
# i was running fine with 256MB from 2022/07-ish through 2022/12-ish, but then the phone quit reliably coming back from sleep: maybe a memory leak?
|
|
||||||
# `cat /proc/meminfo` to see CmaTotal/CmaFree if interested in tuning this.
|
|
||||||
boot.kernelParams = [ "cma=512M" ];
|
|
||||||
|
|
||||||
# mobile-nixos' /lib/firmware includes:
|
|
||||||
# rtl_bt (bluetooth)
|
|
||||||
# anx7688-fw.bin (USB-C -> HDMI bridge)
|
|
||||||
# ov5640_af.bin (camera module)
|
|
||||||
# hardware.firmware = [ config.mobile.device.firmware ];
|
|
||||||
hardware.firmware = [ pkgs.rtl8723cs-firmware ];
|
|
||||||
|
|
||||||
system.stateVersion = "21.11";
|
|
||||||
|
|
||||||
# defined: https://www.freedesktop.org/software/systemd/man/machine-info.html
|
|
||||||
# XXX colin: not sure which, if any, software makes use of this
|
|
||||||
environment.etc."machine-info".text = ''
|
|
||||||
CHASSIS="handset"
|
|
||||||
'';
|
|
||||||
|
|
||||||
# enable rotation sensor
|
|
||||||
hardware.sensor.iio.enable = true;
|
|
||||||
|
|
||||||
# inject specialized alsa configs via the environment.
|
|
||||||
# specifically, this gets the pinephone headphones & internal earpiece working.
|
|
||||||
# see pkgs/patched/alsa-ucm-conf for more info.
|
|
||||||
environment.variables.ALSA_CONFIG_UCM2 = "/run/current-system/sw/share/alsa/ucm2";
|
|
||||||
environment.pathsToLink = [ "/share/alsa/ucm2" ];
|
|
||||||
environment.systemPackages = [ pkgs.alsa-ucm-conf-sane ];
|
|
||||||
systemd =
|
|
||||||
let ucm-env = config.environment.variables.ALSA_CONFIG_UCM2;
|
|
||||||
in {
|
|
||||||
# cribbed from <repo:nixos/mobile-nixos:modules/quirks/audio.nix>
|
|
||||||
|
|
||||||
# pulseaudio
|
|
||||||
user.services.pulseaudio.environment.ALSA_CONFIG_UCM2 = ucm-env;
|
|
||||||
services.pulseaudio.environment.ALSA_CONFIG_UCM2 = ucm-env;
|
|
||||||
|
|
||||||
# pipewire
|
|
||||||
user.services.pipewire.environment.ALSA_CONFIG_UCM2 = ucm-env;
|
|
||||||
user.services.pipewire-pulse.environment.ALSA_CONFIG_UCM2 = ucm-env;
|
|
||||||
user.services.wireplumber.environment.ALSA_CONFIG_UCM2 = ucm-env;
|
|
||||||
services.pipewire.environment.ALSA_CONFIG_UCM2 = ucm-env;
|
|
||||||
services.pipewire-pulse.environment.ALSA_CONFIG_UCM2 = ucm-env;
|
|
||||||
services.wireplumber.environment.ALSA_CONFIG_UCM2 = ucm-env;
|
|
||||||
};
|
|
||||||
|
|
||||||
services.udev.extraRules = let
|
|
||||||
chmod = "${pkgs.coreutils}/bin/chmod";
|
|
||||||
chown = "${pkgs.coreutils}/bin/chown";
|
|
||||||
in ''
|
|
||||||
# make Pinephone flashlight writable by user.
|
|
||||||
# taken from postmarketOS: <repo:postmarketOS/pmaports:device/main/device-pine64-pinephone/60-flashlight.rules>
|
|
||||||
SUBSYSTEM=="leds", DEVPATH=="*/*:flash", RUN+="${chmod} g+w /sys%p/brightness /sys%p/flash_strobe", RUN+="${chown} :video /sys%p/brightness /sys%p/flash_strobe"
|
|
||||||
|
|
||||||
# make Pinephone front LEDs writable by user.
|
|
||||||
SUBSYSTEM=="leds", DEVPATH=="*/*:indicator", RUN+="${chmod} g+w /sys%p/brightness", RUN+="${chown} :video /sys%p/brightness"
|
|
||||||
'';
|
|
||||||
|
|
||||||
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
|
|
||||||
'';
|
|
||||||
}
|
|
@@ -1,24 +0,0 @@
|
|||||||
# pinephone GPS happens in EG25 modem
|
|
||||||
# serial control interface to modem is /dev/ttyUSB2
|
|
||||||
# after enabling GPS, readout is /dev/ttyUSB1
|
|
||||||
#
|
|
||||||
# minimal process to enable modem and GPS:
|
|
||||||
# - `echo 1 > /sys/class/modem-power/modem-power/device/powered`
|
|
||||||
# - `screen /dev/ttyUSB2 115200`
|
|
||||||
# - `AT+QGPSCFG="nmeasrc",1`
|
|
||||||
# - `AT+QGPS=1`
|
|
||||||
#
|
|
||||||
# now, something like `gpsd` can directly read from /dev/ttyUSB1.
|
|
||||||
#
|
|
||||||
# initial GPS fix can take 15+ minutes.
|
|
||||||
# meanwhile, services like eg25-manager can speed this up by uploading assisted GPS data to the modem.
|
|
||||||
#
|
|
||||||
# geoclue somehow fits in here as a geospatial provider that leverages GPS and also other sources like radio towers
|
|
||||||
|
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
services.gpsd.enable = true;
|
|
||||||
services.gpsd.devices = [ "/dev/ttyUSB1" ];
|
|
||||||
|
|
||||||
# TODO: enable eg25-manager, and bring online both the modem and GPS on boot
|
|
||||||
}
|
|
@@ -1,83 +0,0 @@
|
|||||||
{ lib, pkgs, ... }:
|
|
||||||
let
|
|
||||||
# use the last commit on the 5.18 branch (5.18.14)
|
|
||||||
# manjaro's changes between kernel patch versions tend to be minimal if any.
|
|
||||||
manjaroBase = "https://gitlab.manjaro.org/manjaro-arm/packages/core/linux/-/raw/25bd828cd47b1c6e09fcbcf394a649b89d2876dd";
|
|
||||||
manjaroPatch = name: sha256: {
|
|
||||||
inherit name;
|
|
||||||
patch = pkgs.fetchpatch {
|
|
||||||
inherit name;
|
|
||||||
url = "${manjaroBase}/${name}?inline=false";
|
|
||||||
inherit sha256;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# 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
|
|
||||||
"1001-arm64-dts-allwinner-add-hdmi-sound-to-pine-devices.patch"
|
|
||||||
"sha256-DApd791A+AxB28Ven/MVAyuyVphdo8KQDx8O7oxVPnc="
|
|
||||||
)
|
|
||||||
# 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
|
|
||||||
{
|
|
||||||
# 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;
|
|
||||||
|
|
||||||
# alternatively, use nixos' kernel and add the stuff we want:
|
|
||||||
# # 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 ++ [
|
|
||||||
# (patchDefconfig kernelConfig)
|
|
||||||
# ];
|
|
||||||
|
|
||||||
nixpkgs.hostPlatform.linux-kernel = {
|
|
||||||
# defaults:
|
|
||||||
name = "aarch64-multiplatform";
|
|
||||||
baseConfig = "defconfig";
|
|
||||||
DTB = true;
|
|
||||||
autoModules = true;
|
|
||||||
preferBuiltin = true;
|
|
||||||
# extraConfig = ...
|
|
||||||
# ^-- raspberry pi stuff: we don't need it.
|
|
||||||
|
|
||||||
# target = "Image"; # <-- default
|
|
||||||
target = "Image.gz"; # <-- compress the kernel image
|
|
||||||
# target = "zImage"; # <-- confuses other parts of nixos :-(
|
|
||||||
};
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
Before Width: | Height: | Size: 118 KiB |
@@ -1,179 +0,0 @@
|
|||||||
# this file configures preferences per program, without actually enabling any programs.
|
|
||||||
# the goal is to separate the place where we decide *what* to use (i.e. `sane.programs.firefox.enable = true` -- at the toplevel)
|
|
||||||
# from where we specific how that thing should behave *if* it's in use.
|
|
||||||
#
|
|
||||||
# NixOS backgrounds:
|
|
||||||
# - <https://github.com/NixOS/nixos-artwork>
|
|
||||||
# - <https://github.com/NixOS/nixos-artwork/issues/50> (colorful; unmerged)
|
|
||||||
# - <https://github.com/NixOS/nixos-artwork/pull/60/files> (desktop-oriented; clean; unmerged)
|
|
||||||
# - <https://itsfoss.com/content/images/2023/04/nixos-tutorials.png>
|
|
||||||
|
|
||||||
{ lib, pkgs, sane-lib, ... }:
|
|
||||||
let
|
|
||||||
# TODO: generate this from the .svg
|
|
||||||
# bg = ./nixos-bg-02.png;
|
|
||||||
bg = pkgs.runCommand "nixos-bg.png" { nativeBuildInputs = [ pkgs.inkscape ]; } ''
|
|
||||||
inkscape ${./nixos-bg-02.svg} -o $out
|
|
||||||
'';
|
|
||||||
in
|
|
||||||
{
|
|
||||||
sane.programs.firefox.config = {
|
|
||||||
# compromise impermanence for the sake of usability
|
|
||||||
persistCache = "private";
|
|
||||||
persistData = "private";
|
|
||||||
|
|
||||||
# i don't do crypto stuff on moby
|
|
||||||
addons.ether-metamask.enable = false;
|
|
||||||
# sidebery UX doesn't make sense on small screen
|
|
||||||
addons.sidebery.enable = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
sane.gui.sxmo = {
|
|
||||||
nogesture = true;
|
|
||||||
settings = {
|
|
||||||
### hardware: touch screen
|
|
||||||
SXMO_LISGD_INPUT_DEVICE = "/dev/input/by-path/platform-1c2ac00.i2c-event";
|
|
||||||
# vol and power are detected correctly by upstream
|
|
||||||
|
|
||||||
|
|
||||||
### preferences
|
|
||||||
# notable bemenu options:
|
|
||||||
# - see `bemenu --help` for all
|
|
||||||
# -P, --prefix text to show before highlighted item.
|
|
||||||
# --scrollbar display scrollbar. (none (default), always, autohide)
|
|
||||||
# -H, --line-height defines the height to make each menu line (0 = default height). (wx)
|
|
||||||
# -M, --margin defines the empty space on either side of the menu. (wx)
|
|
||||||
# -W, --width-factor defines the relative width factor of the menu (from 0 to 1). (wx)
|
|
||||||
# -B, --border defines the width of the border in pixels around the menu. (wx)
|
|
||||||
# -R --border-radius defines the radius of the border around the menu (0 = no curved borders).
|
|
||||||
# --ch defines the height of the cursor (0 = scales with line height). (wx)
|
|
||||||
# --cw defines the width of the cursor. (wx)
|
|
||||||
# --hp defines the horizontal padding for the entries in single line mode. (wx)
|
|
||||||
# --fn defines the font to be used ('name [size]'). (wx)
|
|
||||||
# --tb defines the title background color. (wx)
|
|
||||||
# --tf defines the title foreground color. (wx)
|
|
||||||
# --fb defines the filter background color. (wx)
|
|
||||||
# --ff defines the filter foreground color. (wx)
|
|
||||||
# --nb defines the normal background color. (wx)
|
|
||||||
# --nf defines the normal foreground color. (wx)
|
|
||||||
# --hb defines the highlighted background color. (wx)
|
|
||||||
# --hf defines the highlighted foreground color. (wx)
|
|
||||||
# --fbb defines the feedback background color. (wx)
|
|
||||||
# --fbf defines the feedback foreground color. (wx)
|
|
||||||
# --sb defines the selected background color. (wx)
|
|
||||||
# --sf defines the selected foreground color. (wx)
|
|
||||||
# --ab defines the alternating background color. (wx)
|
|
||||||
# --af defines the alternating foreground color. (wx)
|
|
||||||
# --scb defines the scrollbar background color. (wx)
|
|
||||||
# --scf defines the scrollbar foreground color. (wx)
|
|
||||||
# --bdr defines the border color. (wx)
|
|
||||||
#
|
|
||||||
# colors are specified as `#RRGGBB`
|
|
||||||
# defaults:
|
|
||||||
# --ab "#222222"
|
|
||||||
# --af "#bbbbbb"
|
|
||||||
# --bdr "#005577"
|
|
||||||
# --border 3
|
|
||||||
# --cb "#222222"
|
|
||||||
# --center
|
|
||||||
# --cf "#bbbbbb"
|
|
||||||
# --fb "#222222"
|
|
||||||
# --fbb "#eeeeee"
|
|
||||||
# --fbf "#222222"
|
|
||||||
# --ff "#bbbbbb"
|
|
||||||
# --fixed-height
|
|
||||||
# --fn 'Sxmo 14'
|
|
||||||
# --hb "#005577"
|
|
||||||
# --hf "#eeeeee"
|
|
||||||
# --line-height 20
|
|
||||||
# --list 16
|
|
||||||
# --margin 40
|
|
||||||
# --nb "#222222"
|
|
||||||
# --nf "#bbbbbb"
|
|
||||||
# --no-overlap
|
|
||||||
# --no-spacing
|
|
||||||
# --sb "#323232"
|
|
||||||
# --scb "#005577"
|
|
||||||
# --scf "#eeeeee"
|
|
||||||
# --scrollbar autohide
|
|
||||||
# --tb "#005577"
|
|
||||||
# --tf "#eeeeee"
|
|
||||||
# --wrap
|
|
||||||
BEMENU_OPTS = let
|
|
||||||
bg = "#1d1721"; # slight purple
|
|
||||||
fg0 = "#d8d8d8"; # inactive text (light grey)
|
|
||||||
fg1 = "#ffffff"; # active text (white)
|
|
||||||
accent0 = "#1f5e54"; # darker but saturated teal
|
|
||||||
accent1 = "#418379"; # teal (matches nixos-bg)
|
|
||||||
accent2 = "#5b938a"; # brighter but muted teal
|
|
||||||
in lib.concatStringsSep " " [
|
|
||||||
"--wrap --scrollbar autohide --fixed-height"
|
|
||||||
"--center --margin 45"
|
|
||||||
"--no-spacing"
|
|
||||||
# XXX: font size doesn't seem to take effect (would prefer larger)
|
|
||||||
"--fn 'Sxmo 14' --line-height 22 --border 3"
|
|
||||||
"--bdr '${accent0}'" # border
|
|
||||||
"--scf '${accent2}' --scb '${accent0}'" # scrollbar
|
|
||||||
"--tb '${accent0}' --tf '${fg0}'" # title
|
|
||||||
"--fb '${accent0}' --ff '${fg1}'" # filter (i.e. text that's been entered)
|
|
||||||
"--hb '${accent1}' --hf '${fg1}'" # selected item
|
|
||||||
"--nb '${bg}' --nf '${fg0}'" # normal lines (even)
|
|
||||||
"--ab '${bg}' --af '${fg0}'" # alternated lines (odd)
|
|
||||||
"--cf '${accent0}' --cb '${accent0}'" # cursor (not very useful)
|
|
||||||
];
|
|
||||||
DEFAULT_COUNTRY = "US";
|
|
||||||
|
|
||||||
# BEMENU lines (wayland DMENU):
|
|
||||||
# - camera is 9th entry
|
|
||||||
# - flashlight is 10th entry
|
|
||||||
# - config is 14th entry. inside that:
|
|
||||||
# - autorotate is 11th entry
|
|
||||||
# - system menu is 19th entry
|
|
||||||
# - close is 20th entry
|
|
||||||
# - power is 15th entry
|
|
||||||
# - close is 16th entry
|
|
||||||
SXMO_BEMENU_LANDSCAPE_LINES = "11"; # default 8
|
|
||||||
SXMO_BEMENU_PORTRAIT_LINES = "16"; # default 16
|
|
||||||
SXMO_BG_IMG = "${bg}";
|
|
||||||
SXMO_LOCK_IDLE_TIME = "15"; # how long between screenoff -> lock -> back to screenoff (default: 8)
|
|
||||||
# gravity: how far to tilt the device before the screen rotates
|
|
||||||
# for a given setting, normal <-> invert requires more movement then left <-> right
|
|
||||||
# i.e. the settingd doesn't feel completely symmetric
|
|
||||||
# SXMO_ROTATION_GRAVITY default is 16374
|
|
||||||
# SXMO_ROTATION_GRAVITY = "12800"; # uncomfortably high
|
|
||||||
# SXMO_ROTATION_GRAVITY = "12500"; # kinda uncomfortable when walking
|
|
||||||
SXMO_ROTATION_GRAVITY = "12000";
|
|
||||||
SXMO_SCREENSHOT_DIR = "/home/colin/Pictures"; # default: "$HOME"
|
|
||||||
# test new scales by running `swaymsg -- output DSI-1 scale x.y`
|
|
||||||
# SXMO_SWAY_SCALE = "1.5"; # hard to press gPodder icons
|
|
||||||
SXMO_SWAY_SCALE = "1.8";
|
|
||||||
# SXMO_SWAY_SCALE = "2";
|
|
||||||
SXMO_WORKSPACE_WRAPPING = "5"; # how many workspaces. default: 4
|
|
||||||
|
|
||||||
# wvkbd layers:
|
|
||||||
# - full
|
|
||||||
# - landscape
|
|
||||||
# - special (e.g. coding symbols like ~)
|
|
||||||
# - emoji
|
|
||||||
# - nav
|
|
||||||
# - simple (like landscape, but no parens/tab/etc; even fewer chars)
|
|
||||||
# - simplegrid (simple, but grid layout)
|
|
||||||
# - dialer (digits)
|
|
||||||
# - cyrillic
|
|
||||||
# - arabic
|
|
||||||
# - persian
|
|
||||||
# - greek
|
|
||||||
# - georgian
|
|
||||||
WVKBD_LANDSCAPE_LAYERS = "landscape,special,emoji";
|
|
||||||
WVKBD_LAYERS = "full,special,emoji";
|
|
||||||
};
|
|
||||||
package = pkgs.sxmo-utils.overrideAttrs (base: {
|
|
||||||
postPatch = (base.postPatch or "") + ''
|
|
||||||
cat <<EOF >> ./configs/default_hooks/sxmo_hook_start.sh
|
|
||||||
# rotate UI based on physical display angle by default
|
|
||||||
sxmo_daemons.sh start autorotate sxmo_autorotate.sh
|
|
||||||
EOF
|
|
||||||
'';
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,34 +0,0 @@
|
|||||||
{ config, lib, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
cweb-cfg = config.services.calibre-web;
|
|
||||||
inherit (cweb-cfg) user group;
|
|
||||||
inherit (cweb-cfg.listen) ip port;
|
|
||||||
svc-dir = "/var/lib/${cweb-cfg.dataDir}";
|
|
||||||
in
|
|
||||||
# XXX: disabled because of runtime errors like:
|
|
||||||
# > File "/nix/store/c7jqvx980nlg9xhxi065cba61r2ain9y-calibre-web-0.6.19/lib/python3.10/site-packages/calibreweb/cps/db.py", line 926, in speaking_language
|
|
||||||
# > languages = self.session.query(Languages) \
|
|
||||||
# > AttributeError: 'NoneType' object has no attribute 'query'
|
|
||||||
lib.mkIf false
|
|
||||||
{
|
|
||||||
sane.persist.sys.plaintext = [
|
|
||||||
{ inherit user group; mode = "0700"; path = svc-dir; }
|
|
||||||
];
|
|
||||||
|
|
||||||
services.calibre-web.enable = true;
|
|
||||||
services.calibre-web.listen.ip = "127.0.0.1";
|
|
||||||
# XXX: externally populate `${svc-dir}/metadata.db` (once) from
|
|
||||||
# <https://github.com/janeczku/calibre-web/blob/master/library/metadata.db>
|
|
||||||
# i don't know why you have to do this??
|
|
||||||
# services.calibre-web.options.calibreLibrary = svc-dir;
|
|
||||||
|
|
||||||
services.nginx.virtualHosts."calibre.uninsane.org" = {
|
|
||||||
addSSL = true;
|
|
||||||
enableACME = true;
|
|
||||||
locations."/" = {
|
|
||||||
proxyPass = "http://${ip}:${builtins.toString port}";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
sane.dns.zones."uninsane.org".inet.CNAME."calibre" = "native";
|
|
||||||
}
|
|
@@ -1,37 +0,0 @@
|
|||||||
# nix configs to reference:
|
|
||||||
# - <https://gitlab.com/simple-nixos-mailserver/nixos-mailserver>
|
|
||||||
# - <https://github.com/nix-community/nur-combined/-/tree/master/repos/eh5/machines/srv-m/mail-rspamd.nix>
|
|
||||||
# - postfix / dovecot / rspamd / stalwart-jmap / sogo
|
|
||||||
#
|
|
||||||
# rspamd:
|
|
||||||
# - nixos: <https://nixos.wiki/wiki/Rspamd>
|
|
||||||
# - guide: <https://rspamd.com/doc/quickstart.html>
|
|
||||||
# - non-nixos example: <https://dataswamp.org/~solene/2021-07-13-smtpd-rspamd.html>
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# my rough understanding of the pieces:
|
|
||||||
# - postfix handles SMTP protocol with the rest of the world.
|
|
||||||
# - dovecot implements IMAP protocol.
|
|
||||||
# - client auth (i.e. validate that user@uninsane.org is who they claim)
|
|
||||||
# - "folders" (INBOX, JUNK) are internal to dovecot?
|
|
||||||
# or where do folders live, on-disk?
|
|
||||||
#
|
|
||||||
# - non-local clients (i.e. me) interact with BOTH postfix and dovecot, but primarily dovecot:
|
|
||||||
# - mail reading is done via IMAP (so, dovecot)
|
|
||||||
# - mail sending is done via SMTP/submission port (so, postfix)
|
|
||||||
# - but postfix delegates authorization of that outgoing mail to dovecot, on the server side
|
|
||||||
#
|
|
||||||
# - local clients (i.e. sendmail) interact only with postfix
|
|
||||||
|
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
./dovecot.nix
|
|
||||||
./postfix.nix
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
#### SPAM FILTERING
|
|
||||||
# services.rspamd.enable = true;
|
|
||||||
# services.rspamd.postfix.enable = true;
|
|
||||||
}
|
|
@@ -1,142 +0,0 @@
|
|||||||
# dovecot config options: <https://doc.dovecot.org/configuration_manual/>
|
|
||||||
#
|
|
||||||
# sieve docs:
|
|
||||||
# - sieve language examples: <https://doc.dovecot.org/configuration_manual/sieve/examples/>
|
|
||||||
# - sieve protocol/language: <https://proton.me/support/sieve-advanced-custom-filters>
|
|
||||||
|
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
{
|
|
||||||
sane.ports.ports."143" = {
|
|
||||||
protocol = [ "tcp" ];
|
|
||||||
visibleTo.lan = true;
|
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-imap-imap.uninsane.org";
|
|
||||||
};
|
|
||||||
sane.ports.ports."993" = {
|
|
||||||
protocol = [ "tcp" ];
|
|
||||||
visibleTo.lan = true;
|
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-imaps-imap.uninsane.org";
|
|
||||||
};
|
|
||||||
|
|
||||||
# exists only to manage certs for dovecot
|
|
||||||
services.nginx.virtualHosts."imap.uninsane.org" = {
|
|
||||||
enableACME = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
sane.dns.zones."uninsane.org".inet = {
|
|
||||||
CNAME."imap" = "native";
|
|
||||||
};
|
|
||||||
|
|
||||||
sops.secrets."dovecot_passwd" = {
|
|
||||||
owner = config.users.users.dovecot2.name;
|
|
||||||
# TODO: debug why mail can't be sent without this being world-readable
|
|
||||||
mode = "0444";
|
|
||||||
};
|
|
||||||
|
|
||||||
# inspired by https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/
|
|
||||||
services.dovecot2.enable = true;
|
|
||||||
# services.dovecot2.enableLmtp = true;
|
|
||||||
services.dovecot2.sslServerCert = "/var/lib/acme/imap.uninsane.org/fullchain.pem";
|
|
||||||
services.dovecot2.sslServerKey = "/var/lib/acme/imap.uninsane.org/key.pem";
|
|
||||||
services.dovecot2.enablePAM = false;
|
|
||||||
|
|
||||||
# sieve scripts require me to set a user for... idk why?
|
|
||||||
services.dovecot2.mailUser = "colin";
|
|
||||||
services.dovecot2.mailGroup = "users";
|
|
||||||
users.users.colin.isSystemUser = lib.mkForce false;
|
|
||||||
|
|
||||||
services.dovecot2.extraConfig =
|
|
||||||
let
|
|
||||||
passwdFile = config.sops.secrets.dovecot_passwd.path;
|
|
||||||
in
|
|
||||||
''
|
|
||||||
passdb {
|
|
||||||
driver = passwd-file
|
|
||||||
args = ${passwdFile}
|
|
||||||
}
|
|
||||||
userdb {
|
|
||||||
driver = passwd-file
|
|
||||||
args = ${passwdFile}
|
|
||||||
}
|
|
||||||
|
|
||||||
# allow postfix to query our auth db
|
|
||||||
service auth {
|
|
||||||
unix_listener auth {
|
|
||||||
mode = 0660
|
|
||||||
user = postfix
|
|
||||||
group = postfix
|
|
||||||
}
|
|
||||||
}
|
|
||||||
auth_mechanisms = plain login
|
|
||||||
|
|
||||||
# accept incoming messaging from postfix
|
|
||||||
# service lmtp {
|
|
||||||
# unix_listener dovecot-lmtp {
|
|
||||||
# mode = 0600
|
|
||||||
# user = postfix
|
|
||||||
# group = postfix
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
|
|
||||||
# plugin {
|
|
||||||
# sieve_plugins = sieve_imapsieve
|
|
||||||
# }
|
|
||||||
|
|
||||||
mail_debug = yes
|
|
||||||
auth_debug = yes
|
|
||||||
# verbose_ssl = yes
|
|
||||||
'';
|
|
||||||
|
|
||||||
services.dovecot2.mailboxes = {
|
|
||||||
# special-purpose mailboxes: "All" "Archive" "Drafts" "Flagged" "Junk" "Sent" "Trash"
|
|
||||||
# RFC6154 describes these special mailboxes: https://www.ietf.org/rfc/rfc6154.html
|
|
||||||
# how these boxes are treated is 100% up to the client and server to decide.
|
|
||||||
# client behavior:
|
|
||||||
# iOS
|
|
||||||
# - Drafts: ?
|
|
||||||
# - Sent: works
|
|
||||||
# - Trash: works
|
|
||||||
# - Junk: works ("mark" -> "move to Junk")
|
|
||||||
# aerc
|
|
||||||
# - Drafts: works
|
|
||||||
# - Sent: works
|
|
||||||
# - Trash: no; deleted messages are actually deleted
|
|
||||||
# use `:move trash` instead
|
|
||||||
# - Junk: ?
|
|
||||||
# Sent mailbox: all sent messages are copied to it. unclear if this happens server-side or client-side.
|
|
||||||
Drafts = { specialUse = "Drafts"; auto = "create"; };
|
|
||||||
Sent = { specialUse = "Sent"; auto = "create"; };
|
|
||||||
Trash = { specialUse = "Trash"; auto = "create"; };
|
|
||||||
Junk = { specialUse = "Junk"; auto = "create"; };
|
|
||||||
};
|
|
||||||
|
|
||||||
services.dovecot2.mailPlugins = {
|
|
||||||
perProtocol = {
|
|
||||||
# imap.enable = [
|
|
||||||
# "imap_sieve"
|
|
||||||
# ];
|
|
||||||
lda.enable = [
|
|
||||||
"sieve"
|
|
||||||
];
|
|
||||||
# lmtp.enable = [
|
|
||||||
# "sieve"
|
|
||||||
# ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
services.dovecot2.modules = [
|
|
||||||
pkgs.dovecot_pigeonhole # enables sieve execution (?)
|
|
||||||
];
|
|
||||||
services.dovecot2.sieveScripts = {
|
|
||||||
# if any messages fail to pass (or lack) DKIM, move them to Junk
|
|
||||||
# XXX the key name ("after") is only used to order sieve execution/ordering
|
|
||||||
after = builtins.toFile "ensuredkim.sieve" ''
|
|
||||||
require "fileinto";
|
|
||||||
|
|
||||||
if not header :contains "Authentication-Results" "dkim=pass" {
|
|
||||||
fileinto "Junk";
|
|
||||||
stop;
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
@@ -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
|
|
@@ -1,127 +0,0 @@
|
|||||||
# configuration options (today i don't store my config in nix):
|
|
||||||
#
|
|
||||||
# - jellyfin-web can be statically configured (result/share/jellyfin-web/config.json)
|
|
||||||
# - <https://jellyfin.org/docs/general/clients/web-config>
|
|
||||||
# - configure server list, plugins, "menuLinks", colors
|
|
||||||
#
|
|
||||||
# - jellfyin server is configured in /var/lib/jellfin/
|
|
||||||
# - root/default/<LibraryType>/
|
|
||||||
# - <LibraryName>.mblink: contains the directory name where this library lives
|
|
||||||
# - options.xml: contains preferences which were defined in the web UI during import
|
|
||||||
# - e.g. `EnablePhotos`, `EnableChapterImageExtraction`, etc.
|
|
||||||
# - config/encoding.xml: transcoder settings
|
|
||||||
# - config/system.xml: misc preferences like log file duration, audiobook resume settings, etc.
|
|
||||||
# - data/jellyfin.db: maybe account definitions? internal state?
|
|
||||||
|
|
||||||
{ config, lib, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
# https://jellyfin.org/docs/general/networking/index.html
|
|
||||||
sane.ports.ports."1900" = {
|
|
||||||
protocol = [ "udp" ];
|
|
||||||
visibleTo.lan = true;
|
|
||||||
description = "colin-upnp-for-jellyfin";
|
|
||||||
};
|
|
||||||
sane.ports.ports."7359" = {
|
|
||||||
protocol = [ "udp" ];
|
|
||||||
visibleTo.lan = true;
|
|
||||||
description = "colin-jellyfin-specific-client-discovery";
|
|
||||||
# ^ not sure if this is necessary: copied this port from nixos jellyfin.openFirewall
|
|
||||||
};
|
|
||||||
# not sure if 8096/8920 get used either:
|
|
||||||
sane.ports.ports."8096" = {
|
|
||||||
protocol = [ "tcp" ];
|
|
||||||
visibleTo.lan = true;
|
|
||||||
description = "colin-jellyfin-http-lan";
|
|
||||||
};
|
|
||||||
sane.ports.ports."8920" = {
|
|
||||||
protocol = [ "tcp" ];
|
|
||||||
visibleTo.lan = true;
|
|
||||||
description = "colin-jellyfin-https-lan";
|
|
||||||
};
|
|
||||||
|
|
||||||
sane.persist.sys.plaintext = [
|
|
||||||
{ user = "jellyfin"; group = "jellyfin"; mode = "0700"; path = "/var/lib/jellyfin"; }
|
|
||||||
];
|
|
||||||
sane.fs."/var/lib/jellyfin/config/logging.json" = {
|
|
||||||
# "Emby.Dlna" logging: <https://jellyfin.org/docs/general/networking/dlna>
|
|
||||||
symlink.text = ''
|
|
||||||
{
|
|
||||||
"Serilog": {
|
|
||||||
"MinimumLevel": {
|
|
||||||
"Default": "Information",
|
|
||||||
"Override": {
|
|
||||||
"Microsoft": "Warning",
|
|
||||||
"System": "Warning",
|
|
||||||
"Emby.Dlna": "Debug",
|
|
||||||
"Emby.Dlna.Eventing": "Debug"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"WriteTo": [
|
|
||||||
{
|
|
||||||
"Name": "Console",
|
|
||||||
"Args": {
|
|
||||||
"outputTemplate": "[{Timestamp:HH:mm:ss}] [{Level:u3}] [{ThreadId}] {SourceContext}: {Message:lj}{NewLine}{Exception}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"Enrich": [ "FromLogContext", "WithThreadId" ]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
wantedBeforeBy = [ "jellyfin.service" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
# Jellyfin multimedia server
|
|
||||||
# this is mostly taken from the official jellfin.org docs
|
|
||||||
services.nginx.virtualHosts."jelly.uninsane.org" = {
|
|
||||||
addSSL = true;
|
|
||||||
enableACME = true;
|
|
||||||
# inherit kTLS;
|
|
||||||
|
|
||||||
locations."/" = {
|
|
||||||
proxyPass = "http://127.0.0.1:8096";
|
|
||||||
extraConfig = ''
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header X-Forwarded-Protocol $scheme;
|
|
||||||
proxy_set_header X-Forwarded-Host $http_host;
|
|
||||||
|
|
||||||
# Disable buffering when the nginx proxy gets very resource heavy upon streaming
|
|
||||||
proxy_buffering off;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
# locations."/web/" = {
|
|
||||||
# proxyPass = "http://127.0.0.1:8096/web/index.html";
|
|
||||||
# extraConfig = ''
|
|
||||||
# proxy_set_header Host $host;
|
|
||||||
# proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
# proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
# proxy_set_header X-Forwarded-Protocol $scheme;
|
|
||||||
# proxy_set_header X-Forwarded-Host $http_host;
|
|
||||||
# '';
|
|
||||||
# };
|
|
||||||
locations."/socket" = {
|
|
||||||
proxyPass = "http://127.0.0.1:8096";
|
|
||||||
extraConfig = ''
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection "upgrade";
|
|
||||||
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header X-Forwarded-Protocol $scheme;
|
|
||||||
proxy_set_header X-Forwarded-Host $http_host;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
sane.dns.zones."uninsane.org".inet.CNAME."jelly" = "native";
|
|
||||||
|
|
||||||
services.jellyfin.enable = true;
|
|
||||||
}
|
|
@@ -1,22 +0,0 @@
|
|||||||
{ config, ... }:
|
|
||||||
let
|
|
||||||
svc-cfg = config.services.komga;
|
|
||||||
inherit (svc-cfg) user group port stateDir;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
sane.persist.sys.plaintext = [
|
|
||||||
{ inherit user group; mode = "0700"; path = stateDir; }
|
|
||||||
];
|
|
||||||
|
|
||||||
services.komga.enable = true;
|
|
||||||
services.komga.port = 11319; # chosen at random
|
|
||||||
|
|
||||||
services.nginx.virtualHosts."komga.uninsane.org" = {
|
|
||||||
addSSL = true;
|
|
||||||
enableACME = true;
|
|
||||||
locations."/" = {
|
|
||||||
proxyPass = "http://127.0.0.1:${builtins.toString port}";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
sane.dns.zones."uninsane.org".inet.CNAME."komga" = "native";
|
|
||||||
}
|
|
@@ -1,59 +0,0 @@
|
|||||||
# docs:
|
|
||||||
# - <repo:LemmyNet/lemmy:docker/federation/nginx.conf>
|
|
||||||
# - <repo:LemmyNet/lemmy:docker/nginx.conf>
|
|
||||||
# - <repo:LemmyNet/lemmy-ansible:templates/nginx.conf>
|
|
||||||
|
|
||||||
{ config, lib, ... }:
|
|
||||||
let
|
|
||||||
inherit (builtins) toString;
|
|
||||||
inherit (lib) mkForce;
|
|
||||||
uiPort = 1234; # default ui port is 1234
|
|
||||||
backendPort = 8536; # default backend port is 8536
|
|
||||||
# - i guess the "backend" port is used for federation?
|
|
||||||
in {
|
|
||||||
services.lemmy = {
|
|
||||||
enable = true;
|
|
||||||
settings.hostname = "lemmy.uninsane.org";
|
|
||||||
# federation.debug forces outbound federation queries to be run synchronously
|
|
||||||
# N.B.: this option might not be read for 0.17.0+? <https://github.com/LemmyNet/lemmy/blob/c32585b03429f0f76d1e4ff738786321a0a9df98/RELEASES.md#upgrade-instructions>
|
|
||||||
# settings.federation.debug = true;
|
|
||||||
settings.port = backendPort;
|
|
||||||
ui.port = uiPort;
|
|
||||||
database.createLocally = true;
|
|
||||||
nginx.enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.lemmy.serviceConfig = {
|
|
||||||
# fix to use a normal user so we can configure perms correctly
|
|
||||||
DynamicUser = mkForce false;
|
|
||||||
User = "lemmy";
|
|
||||||
Group = "lemmy";
|
|
||||||
};
|
|
||||||
systemd.services.lemmy.environment = {
|
|
||||||
RUST_BACKTRACE = "full";
|
|
||||||
# RUST_LOG = "debug";
|
|
||||||
# RUST_LOG = "trace";
|
|
||||||
# upstream defaults LEMMY_DATABASE_URL = "postgres:///lemmy?host=/run/postgresql";
|
|
||||||
# - Postgres complains that we didn't specify a user
|
|
||||||
# lemmy formats the url as:
|
|
||||||
# - postgres://{user}:{password}@{host}:{port}/{database}
|
|
||||||
# SO suggests (https://stackoverflow.com/questions/3582552/what-is-the-format-for-the-postgresql-connection-string-url):
|
|
||||||
# - postgresql://[user[:password]@][netloc][:port][/dbname][?param1=value1&...]
|
|
||||||
# LEMMY_DATABASE_URL = "postgres://lemmy@/run/postgresql"; # connection to server on socket "/run/postgresql/.s.PGSQL.5432" failed: FATAL: database "run/postgresql" does not exist
|
|
||||||
# LEMMY_DATABASE_URL = "postgres://lemmy?host=/run/postgresql"; # no PostgreSQL user name specified in startup packet
|
|
||||||
# LEMMY_DATABASE_URL = mkForce "postgres://lemmy@?host=/run/postgresql"; # WORKS
|
|
||||||
LEMMY_DATABASE_URL = mkForce "postgres://lemmy@/lemmy?host=/run/postgresql";
|
|
||||||
};
|
|
||||||
users.groups.lemmy = {};
|
|
||||||
users.users.lemmy = {
|
|
||||||
group = "lemmy";
|
|
||||||
isSystemUser = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
services.nginx.virtualHosts."lemmy.uninsane.org" = {
|
|
||||||
forceSSL = true;
|
|
||||||
enableACME = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
sane.dns.zones."uninsane.org".inet.CNAME."lemmy" = "native";
|
|
||||||
}
|
|
@@ -1,13 +0,0 @@
|
|||||||
diff --git a/src/irc/ConnectionInstance.ts b/src/irc/ConnectionInstance.ts
|
|
||||||
index 688036ca..3373fa27 100644
|
|
||||||
--- a/src/irc/ConnectionInstance.ts
|
|
||||||
+++ b/src/irc/ConnectionInstance.ts
|
|
||||||
@@ -149,7 +149,7 @@ export class ConnectionInstance {
|
|
||||||
if (this.dead) {
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
- ircReason = ircReason || reason;
|
|
||||||
+ ircReason = "bye"; // don't reveal through the IRC quit message that we're a bridge
|
|
||||||
log.info(
|
|
||||||
"disconnect()ing %s@%s - %s", this.nick, this.domain, reason
|
|
||||||
);
|
|
@@ -1,50 +0,0 @@
|
|||||||
diff --git a/config.schema.yml b/config.schema.yml
|
|
||||||
index 2e71c8d6..42ba8ba1 100644
|
|
||||||
--- a/config.schema.yml
|
|
||||||
+++ b/config.schema.yml
|
|
||||||
@@ -433,7 +433,7 @@ properties:
|
|
||||||
type: "boolean"
|
|
||||||
realnameFormat:
|
|
||||||
type: "string"
|
|
||||||
- enum: ["mxid","reverse-mxid"]
|
|
||||||
+ enum: ["mxid","reverse-mxid","localpart"]
|
|
||||||
ipv6:
|
|
||||||
type: "object"
|
|
||||||
properties:
|
|
||||||
diff --git a/src/irc/IdentGenerator.ts b/src/irc/IdentGenerator.ts
|
|
||||||
index 7a2b5cf1..50f7815a 100644
|
|
||||||
--- a/src/irc/IdentGenerator.ts
|
|
||||||
+++ b/src/irc/IdentGenerator.ts
|
|
||||||
@@ -74,6 +74,9 @@ export class IdentGenerator {
|
|
||||||
else if (server.getRealNameFormat() === "reverse-mxid") {
|
|
||||||
realname = IdentGenerator.sanitiseRealname(IdentGenerator.switchAroundMxid(matrixUser));
|
|
||||||
}
|
|
||||||
+ else if (server.getRealNameFormat() == "localpart") {
|
|
||||||
+ realname = IdentGenerator.sanitiseRealname(matrixUser.localpart);
|
|
||||||
+ }
|
|
||||||
else {
|
|
||||||
throw Error('Invalid value for realNameFormat');
|
|
||||||
}
|
|
||||||
diff --git a/src/irc/IrcServer.ts b/src/irc/IrcServer.ts
|
|
||||||
index 2af73ab4..895b9783 100644
|
|
||||||
--- a/src/irc/IrcServer.ts
|
|
||||||
+++ b/src/irc/IrcServer.ts
|
|
||||||
@@ -101,7 +101,7 @@ export interface IrcServerConfig {
|
|
||||||
};
|
|
||||||
lineLimit: number;
|
|
||||||
userModes?: string;
|
|
||||||
- realnameFormat?: "mxid"|"reverse-mxid";
|
|
||||||
+ realnameFormat?: "mxid"|"reverse-mxid"|"localpart";
|
|
||||||
pingTimeoutMs: number;
|
|
||||||
pingRateMs: number;
|
|
||||||
kickOn: {
|
|
||||||
@@ -289,7 +289,7 @@ export class IrcServer {
|
|
||||||
return this.config.ircClients.userModes || "";
|
|
||||||
}
|
|
||||||
|
|
||||||
- public getRealNameFormat(): "mxid"|"reverse-mxid" {
|
|
||||||
+ public getRealNameFormat(): "mxid"|"reverse-mxid"|"localpart" {
|
|
||||||
return this.config.ircClients.realnameFormat || "mxid";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@@ -1,167 +0,0 @@
|
|||||||
# config docs:
|
|
||||||
# - <https://github.com/matrix-org/matrix-appservice-irc/blob/develop/config.sample.yaml>
|
|
||||||
# probably want to remove that.
|
|
||||||
{ config, lib, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
ircServer = { name, additionalAddresses ? [], sasl ? true, port ? 6697 }: let
|
|
||||||
lowerName = lib.toLower name;
|
|
||||||
in {
|
|
||||||
# XXX sasl: appservice doesn't support NickServ identification (only SASL, or PASS if sasl = false)
|
|
||||||
inherit name additionalAddresses sasl port;
|
|
||||||
ssl = true;
|
|
||||||
botConfig = {
|
|
||||||
# bot has no presence in IRC channel; only real Matrix users
|
|
||||||
enabled = false;
|
|
||||||
# this is the IRC username/nickname *of the bot* (not visible in channels): not of the end-user.
|
|
||||||
# the irc username/nick of a mapped Matrix user is determined further down in `ircClients` section.
|
|
||||||
# if `enabled` is false, then this name probably never shows up on the IRC side (?)
|
|
||||||
nick = "uninsane";
|
|
||||||
username = "uninsane";
|
|
||||||
joinChannelsIfNoUsers = false;
|
|
||||||
};
|
|
||||||
dynamicChannels = {
|
|
||||||
enabled = true;
|
|
||||||
aliasTemplate = "#irc_${lowerName}_$CHANNEL";
|
|
||||||
published = false; # false => irc rooms aren't listed in homeserver public rooms list
|
|
||||||
federate = false; # false => Matrix users from other homeservers can't join IRC channels
|
|
||||||
};
|
|
||||||
ircClients = {
|
|
||||||
nickTemplate = "$LOCALPARTsane"; # @colin:uninsane.org (Matrix) -> colinsane (IRC)
|
|
||||||
realnameFormat = "reverse-mxid"; # @colin:uninsane.org (Matrix) -> org.uninsane:colin (IRC)
|
|
||||||
# realnameFormat = "localpart"; # @colin:uninsane.org (Matrix) -> colin (IRC) -- but requires the mxid patch below
|
|
||||||
# by default, Matrix will convert messages greater than (3) lines into a pastebin-like URL to send to IRC.
|
|
||||||
lineLimit = 20;
|
|
||||||
# Rizon in particular allows only 4 connections from one IP before a 30min ban.
|
|
||||||
# that's effectively reduced to 2 during a netsplit, or maybe during a restart.
|
|
||||||
# - https://wiki.rizon.net/index.php?title=Connection/Session_Limit_Exemptions
|
|
||||||
# especially, misconfigurations elsewhere in this config may cause hundreds of connections
|
|
||||||
# so this is a safeguard.
|
|
||||||
maxClients = 2;
|
|
||||||
# don't have the bridge disconnect me from IRC when idle.
|
|
||||||
idleTimeout = 0;
|
|
||||||
concurrentReconnectLimit = 2;
|
|
||||||
reconnectIntervalMs = 60000;
|
|
||||||
kickOn = {
|
|
||||||
# remove Matrix user from room when...
|
|
||||||
channelJoinFailure = false;
|
|
||||||
ircConnectionFailure = false;
|
|
||||||
userQuit = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
matrixClients = {
|
|
||||||
userTemplate = "@irc_${lowerName}_$NICK"; # the :uninsane.org part is appended automatically
|
|
||||||
};
|
|
||||||
|
|
||||||
# this will let this user message the appservice with `!join #<IRCChannel>` and the rest "Just Works"
|
|
||||||
"@colin:uninsane.org" = "admin";
|
|
||||||
|
|
||||||
membershipLists = {
|
|
||||||
enabled = true;
|
|
||||||
global = {
|
|
||||||
ircToMatrix = {
|
|
||||||
initial = true;
|
|
||||||
incremental = true;
|
|
||||||
requireMatrixJoined = false;
|
|
||||||
};
|
|
||||||
matrixToIrc = {
|
|
||||||
initial = true;
|
|
||||||
incremental = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
ignoreIdleUsersOnStartup = {
|
|
||||||
enabled = false; # false => always bridge users, even if idle
|
|
||||||
};
|
|
||||||
};
|
|
||||||
# sync room description?
|
|
||||||
bridgeInfoState = {
|
|
||||||
enabled = true;
|
|
||||||
initial = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
# for per-user IRC password:
|
|
||||||
# - invite @irc_${lowerName}_NickServ:uninsane.org to a DM and type `help` => register
|
|
||||||
# - invite the matrix-appservice-irc user to a DM and type `!help` => add PW to database
|
|
||||||
# to validate that i'm authenticated on the IRC network, DM @irc_${lowerName}_NickServ:uninsane.org:
|
|
||||||
# - send: `STATUS colinsane`
|
|
||||||
# - response should be `3`: "user recognized as owner via password identification"
|
|
||||||
# passwordEncryptionKeyPath = "/path/to/privkey"; # appservice will generate its own if unspecified
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
|
|
||||||
nixpkgs.overlays = [
|
|
||||||
(next: prev: {
|
|
||||||
matrix-appservice-irc = prev.matrix-appservice-irc.overrideAttrs (super: {
|
|
||||||
patches = super.patches or [] ++ [
|
|
||||||
./irc-no-reveal-bridge.patch
|
|
||||||
# ./irc-no-reveal-mxid.patch
|
|
||||||
];
|
|
||||||
});
|
|
||||||
})
|
|
||||||
];
|
|
||||||
|
|
||||||
sane.persist.sys.plaintext = [
|
|
||||||
# TODO: mode?
|
|
||||||
{ user = "matrix-appservice-irc"; group = "matrix-appservice-irc"; path = "/var/lib/matrix-appservice-irc"; }
|
|
||||||
];
|
|
||||||
|
|
||||||
# XXX: matrix-appservice-irc PreStart tries to chgrp the registration.yml to matrix-synapse,
|
|
||||||
# which requires matrix-appservice-irc to be of that group
|
|
||||||
users.users.matrix-appservice-irc.extraGroups = [ "matrix-synapse" ];
|
|
||||||
# weird race conditions around registration.yml mean we want matrix-synapse to be of matrix-appservice-irc group too.
|
|
||||||
users.users.matrix-synapse.extraGroups = [ "matrix-appservice-irc" ];
|
|
||||||
|
|
||||||
services.matrix-synapse.settings.app_service_config_files = [
|
|
||||||
"/var/lib/matrix-appservice-irc/registration.yml" # auto-created by irc appservice
|
|
||||||
];
|
|
||||||
|
|
||||||
services.matrix-appservice-irc.enable = true;
|
|
||||||
services.matrix-appservice-irc.registrationUrl = "http://127.0.0.1:8009";
|
|
||||||
services.matrix-appservice-irc.settings = {
|
|
||||||
homeserver = {
|
|
||||||
url = "http://127.0.0.1:8008";
|
|
||||||
dropMatrixMessagesAfterSecs = 300;
|
|
||||||
domain = "uninsane.org";
|
|
||||||
enablePresence = true;
|
|
||||||
bindPort = 9999;
|
|
||||||
bindHost = "127.0.0.1";
|
|
||||||
};
|
|
||||||
|
|
||||||
ircService = {
|
|
||||||
servers = {
|
|
||||||
"irc.esper.net" = ircServer {
|
|
||||||
name = "esper";
|
|
||||||
sasl = false;
|
|
||||||
# notable channels:
|
|
||||||
# - #merveilles
|
|
||||||
};
|
|
||||||
"irc.libera.chat" = ircServer {
|
|
||||||
name = "libera";
|
|
||||||
sasl = false;
|
|
||||||
# notable channels:
|
|
||||||
# - #hare
|
|
||||||
};
|
|
||||||
"irc.myanonamouse.net" = ircServer {
|
|
||||||
name = "MyAnonamouse";
|
|
||||||
additionalAddresses = [ "irc2.myanonamouse.net" ];
|
|
||||||
sasl = false;
|
|
||||||
};
|
|
||||||
"irc.oftc.net" = ircServer {
|
|
||||||
name = "oftc";
|
|
||||||
sasl = false;
|
|
||||||
# notable channels:
|
|
||||||
# - #sxmo
|
|
||||||
# - #sxmo-offtopic
|
|
||||||
};
|
|
||||||
"irc.rizon.net" = ircServer { name = "Rizon"; };
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.matrix-appservice-irc.serviceConfig = {
|
|
||||||
# XXX 2023/06/20: nixos specifies this + @aio and @memlock as forbidden
|
|
||||||
# the service actively uses at least one of these, and both of them are fairly innocuous
|
|
||||||
SystemCallFilter = lib.mkForce "~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @setuid @swap";
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,37 +0,0 @@
|
|||||||
# config options:
|
|
||||||
# - <https://github.com/mautrix/signal/blob/master/mautrix_signal/example-config.yaml>
|
|
||||||
{ config, pkgs, ... }:
|
|
||||||
{
|
|
||||||
sane.persist.sys.plaintext = [
|
|
||||||
{ user = "mautrix-signal"; group = "mautrix-signal"; path = "/var/lib/mautrix-signal"; }
|
|
||||||
{ user = "signald"; group = "signald"; path = "/var/lib/signald"; }
|
|
||||||
];
|
|
||||||
|
|
||||||
# allow synapse to read the registration file
|
|
||||||
users.users.matrix-synapse.extraGroups = [ "mautrix-signal" ];
|
|
||||||
|
|
||||||
services.signald.enable = true;
|
|
||||||
services.mautrix-signal.enable = true;
|
|
||||||
services.mautrix-signal.environmentFile =
|
|
||||||
config.sops.secrets.mautrix_signal_env.path;
|
|
||||||
|
|
||||||
services.mautrix-signal.settings.signal.socket_path = "/run/signald/signald.sock";
|
|
||||||
services.mautrix-signal.settings.homeserver.domain = "uninsane.org";
|
|
||||||
services.mautrix-signal.settings.bridge.permissions."@colin:uninsane.org" = "admin";
|
|
||||||
services.matrix-synapse.settings.app_service_config_files = [
|
|
||||||
# auto-created by mautrix-signal service
|
|
||||||
"/var/lib/mautrix-signal/signal-registration.yaml"
|
|
||||||
];
|
|
||||||
|
|
||||||
systemd.services.mautrix-signal.serviceConfig = {
|
|
||||||
# allow communication to signald
|
|
||||||
SupplementaryGroups = [ "signald" ];
|
|
||||||
ReadWritePaths = [ "/run/signald" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
sops.secrets."mautrix_signal_env" = {
|
|
||||||
mode = "0440";
|
|
||||||
owner = config.users.users.mautrix-signal.name;
|
|
||||||
group = config.users.users.matrix-synapse.name;
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,67 +0,0 @@
|
|||||||
# docs:
|
|
||||||
# - <https://nixos.wiki/wiki/NFS>
|
|
||||||
# - <https://wiki.gentoo.org/wiki/Nfs-utils>
|
|
||||||
|
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
services.nfs.server.enable = true;
|
|
||||||
|
|
||||||
# see which ports NFS uses with:
|
|
||||||
# - `rpcinfo -p`
|
|
||||||
sane.ports.ports."111" = {
|
|
||||||
protocol = [ "tcp" "udp" ];
|
|
||||||
visibleTo.lan = true;
|
|
||||||
description = "NFS server portmapper";
|
|
||||||
};
|
|
||||||
sane.ports.ports."2049" = {
|
|
||||||
protocol = [ "tcp" ];
|
|
||||||
visibleTo.lan = true;
|
|
||||||
description = "NFS server";
|
|
||||||
};
|
|
||||||
sane.ports.ports."4000" = {
|
|
||||||
protocol = [ "udp" ];
|
|
||||||
visibleTo.lan = true;
|
|
||||||
description = "NFS server status daemon";
|
|
||||||
};
|
|
||||||
sane.ports.ports."4001" = {
|
|
||||||
protocol = [ "tcp" "udp" ];
|
|
||||||
visibleTo.lan = true;
|
|
||||||
description = "NFS server lock daemon";
|
|
||||||
};
|
|
||||||
sane.ports.ports."4002" = {
|
|
||||||
protocol = [ "tcp" "udp" ];
|
|
||||||
visibleTo.lan = true;
|
|
||||||
description = "NFS server mount daemon";
|
|
||||||
};
|
|
||||||
|
|
||||||
# NFS4 allows these to float, but NFS3 mandates specific ports, so fix them for backwards compat.
|
|
||||||
services.nfs.server.lockdPort = 4001;
|
|
||||||
services.nfs.server.mountdPort = 4002;
|
|
||||||
services.nfs.server.statdPort = 4000;
|
|
||||||
|
|
||||||
# format:
|
|
||||||
# fspoint visibility(options)
|
|
||||||
# options:
|
|
||||||
# - see: <https://wiki.gentoo.org/wiki/Nfs-utils#Exports>
|
|
||||||
# - see [man 5 exports](https://linux.die.net/man/5/exports)
|
|
||||||
# - insecure: require clients use src port > 1024
|
|
||||||
# - rw, ro (default)
|
|
||||||
# - async, sync (default)
|
|
||||||
# - no_subtree_check (default), subtree_check: verify not just that files requested by the client live
|
|
||||||
# in the expected fs, but also that they live under whatever subdirectory of that fs is exported.
|
|
||||||
# - no_root_squash, root_squash (default): map requests from uid 0 to user `nobody`.
|
|
||||||
# - crossmnt: reveal filesystems that are mounted under this endpoint
|
|
||||||
# - fsid: must be zero for the root export
|
|
||||||
# - mountpoint[=/path]: only export the directory if it's a mountpoint. used to avoid exporting failed mounts.
|
|
||||||
#
|
|
||||||
# 10.0.0.0/8 to export (readonly) both to LAN (unencrypted) and wg vpn (encrypted)
|
|
||||||
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)
|
|
||||||
'';
|
|
||||||
|
|
||||||
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" ];
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,23 +0,0 @@
|
|||||||
# pict-rs is an image database/store used by Lemmy.
|
|
||||||
# i don't explicitly activate it here -- just adjust its defaults to be a bit friendlier
|
|
||||||
{ config, lib, ... }:
|
|
||||||
let
|
|
||||||
cfg = config.services.pict-rs;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
sane.persist.sys.plaintext = lib.mkIf cfg.enable [
|
|
||||||
{ user = "pict-rs"; group = "pict-rs"; path = cfg.dataDir; }
|
|
||||||
];
|
|
||||||
|
|
||||||
systemd.services.pict-rs.serviceConfig = {
|
|
||||||
# fix to use a normal user so we can configure perms correctly
|
|
||||||
DynamicUser = lib.mkForce false;
|
|
||||||
User = "pict-rs";
|
|
||||||
Group = "pict-rs";
|
|
||||||
};
|
|
||||||
users.groups.pict-rs = {};
|
|
||||||
users.users.pict-rs = {
|
|
||||||
group = "pict-rs";
|
|
||||||
isSystemUser = true;
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,138 +0,0 @@
|
|||||||
{ config, lib, pkgs, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
services.trust-dns.enable = true;
|
|
||||||
|
|
||||||
services.trust-dns.settings.listen_addrs_ipv4 = [
|
|
||||||
# specify each address explicitly, instead of using "*".
|
|
||||||
# this ensures responses are sent from the address at which the request was received.
|
|
||||||
config.sane.hosts.by-name."servo".lan-ip
|
|
||||||
"10.0.1.5"
|
|
||||||
];
|
|
||||||
# don't bind to IPv6 until i explicitly test that stack
|
|
||||||
services.trust-dns.settings.listen_addrs_ipv6 = [];
|
|
||||||
services.trust-dns.quiet = true;
|
|
||||||
# services.trust-dns.debug = true;
|
|
||||||
|
|
||||||
sane.ports.ports."53" = {
|
|
||||||
protocol = [ "udp" "tcp" ];
|
|
||||||
visibleTo.lan = true;
|
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-dns-hosting";
|
|
||||||
};
|
|
||||||
|
|
||||||
sane.dns.zones."uninsane.org".TTL = 900;
|
|
||||||
|
|
||||||
# SOA record structure: <https://en.wikipedia.org/wiki/SOA_record#Structure>
|
|
||||||
# SOA MNAME RNAME (... rest)
|
|
||||||
# MNAME = Master name server for this zone. this is where update requests should be sent.
|
|
||||||
# RNAME = admin contact (encoded email address)
|
|
||||||
# Serial = YYYYMMDDNN, where N is incremented every time this file changes, to trigger secondary NS to re-fetch it.
|
|
||||||
# Refresh = how frequently secondary NS should query master
|
|
||||||
# Retry = how long secondary NS should wait until re-querying master after a failure (must be < Refresh)
|
|
||||||
# Expire = how long secondary NS should continue to reply to queries after master fails (> Refresh + Retry)
|
|
||||||
sane.dns.zones."uninsane.org".inet = {
|
|
||||||
SOA."@" = ''
|
|
||||||
ns1.uninsane.org. admin-dns.uninsane.org. (
|
|
||||||
2022122101 ; Serial
|
|
||||||
4h ; Refresh
|
|
||||||
30m ; Retry
|
|
||||||
7d ; Expire
|
|
||||||
5m) ; Negative response TTL
|
|
||||||
'';
|
|
||||||
TXT."rev" = "2023052901";
|
|
||||||
|
|
||||||
CNAME."native" = "%CNAMENATIVE%";
|
|
||||||
A."@" = "%ANATIVE%";
|
|
||||||
A."wan" = "%AWAN%";
|
|
||||||
A."servo.lan" = config.sane.hosts.by-name."servo".lan-ip;
|
|
||||||
|
|
||||||
# XXX NS records must also not be CNAME
|
|
||||||
# it's best that we keep this identical, or a superset of, what org. lists as our NS.
|
|
||||||
# so, org. can specify ns2/ns3 as being to the VPN, with no mention of ns1. we provide ns1 here.
|
|
||||||
A."ns1" = "%ANATIVE%";
|
|
||||||
A."ns2" = "185.157.162.178";
|
|
||||||
A."ns3" = "185.157.162.178";
|
|
||||||
A."ovpns" = "185.157.162.178";
|
|
||||||
NS."@" = [
|
|
||||||
"ns1.uninsane.org."
|
|
||||||
"ns2.uninsane.org."
|
|
||||||
"ns3.uninsane.org."
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
services.trust-dns.settings.zones = [ "uninsane.org" ];
|
|
||||||
|
|
||||||
services.trust-dns.package =
|
|
||||||
let
|
|
||||||
sed = "${pkgs.gnused}/bin/sed";
|
|
||||||
zone-dir = "/var/lib/trust-dns";
|
|
||||||
zone-wan = "${zone-dir}/wan/uninsane.org.zone";
|
|
||||||
zone-lan = "${zone-dir}/lan/uninsane.org.zone";
|
|
||||||
zone-template = pkgs.writeText "uninsane.org.zone.in" config.sane.dns.zones."uninsane.org".rendered;
|
|
||||||
in pkgs.writeShellScriptBin "named" ''
|
|
||||||
# compute wan/lan values
|
|
||||||
mkdir -p ${zone-dir}/{ovpn,wan,lan}
|
|
||||||
wan=$(cat '${config.sane.services.dyn-dns.ipPath}')
|
|
||||||
lan=${config.sane.hosts.by-name."servo".lan-ip}
|
|
||||||
|
|
||||||
# create specializations that resolve native.uninsane.org to different CNAMEs
|
|
||||||
${sed} s/%AWAN%/$wan/ ${zone-template} \
|
|
||||||
| ${sed} s/%CNAMENATIVE%/wan/ \
|
|
||||||
| ${sed} s/%ANATIVE%/$wan/ \
|
|
||||||
> ${zone-wan}
|
|
||||||
${sed} s/%AWAN%/$wan/ ${zone-template} \
|
|
||||||
| ${sed} s/%CNAMENATIVE%/servo.lan/ \
|
|
||||||
| ${sed} s/%ANATIVE%/$lan/ \
|
|
||||||
> ${zone-lan}
|
|
||||||
|
|
||||||
# launch the different interfaces, separately
|
|
||||||
${pkgs.trust-dns}/bin/named --port 53 --zonedir ${zone-dir}/wan/ $@ &
|
|
||||||
WANPID=$!
|
|
||||||
${pkgs.trust-dns}/bin/named --port 1053 --zonedir ${zone-dir}/lan/ $@ &
|
|
||||||
LANPID=$!
|
|
||||||
|
|
||||||
# wait until any of the processes exits, then kill them all and exit error
|
|
||||||
while kill -0 $WANPID $LANPID ; do
|
|
||||||
sleep 5
|
|
||||||
done
|
|
||||||
kill $WANPID $LANPID
|
|
||||||
exit 1
|
|
||||||
'';
|
|
||||||
|
|
||||||
systemd.services.trust-dns.serviceConfig = {
|
|
||||||
DynamicUser = lib.mkForce false;
|
|
||||||
User = "trust-dns";
|
|
||||||
Group = "trust-dns";
|
|
||||||
};
|
|
||||||
users.groups.trust-dns = {};
|
|
||||||
users.users.trust-dns = {
|
|
||||||
group = "trust-dns";
|
|
||||||
isSystemUser = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
sane.services.dyn-dns.restartOnChange = [ "trust-dns.service" ];
|
|
||||||
|
|
||||||
networking.nat.enable = true;
|
|
||||||
networking.nat.extraCommands = ''
|
|
||||||
# redirect incoming DNS requests from LAN addresses
|
|
||||||
# to the LAN-specialized DNS service
|
|
||||||
# N.B.: use the `nixos-*` chains instead of e.g. PREROUTING
|
|
||||||
# because they get cleanly reset across activations or `systemctl restart firewall`
|
|
||||||
# instead of accumulating cruft
|
|
||||||
iptables -t nat -A nixos-nat-pre -p udp --dport 53 \
|
|
||||||
-m iprange --src-range 10.78.76.0-10.78.79.255 \
|
|
||||||
-j DNAT --to-destination :1053
|
|
||||||
iptables -t nat -A nixos-nat-pre -p tcp --dport 53 \
|
|
||||||
-m iprange --src-range 10.78.76.0-10.78.79.255 \
|
|
||||||
-j DNAT --to-destination :1053
|
|
||||||
'';
|
|
||||||
|
|
||||||
sane.ports.ports."1053" = {
|
|
||||||
# because the NAT above redirects in nixos-nat-pre, LAN requests behave as though they arrived on the external interface at the redirected port.
|
|
||||||
# TODO: try nixos-nat-post instead?
|
|
||||||
protocol = [ "udp" "tcp" ];
|
|
||||||
visibleTo.lan = true;
|
|
||||||
description = "colin-redirected-dns-for-lan-namespace";
|
|
||||||
};
|
|
||||||
}
|
|
16
hosts/common/bluetooth.nix
Normal file
16
hosts/common/bluetooth.nix
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{ lib, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
# persist external pairings by default
|
||||||
|
sane.persist.sys.plaintext = [ "/var/lib/bluetooth" ];
|
||||||
|
|
||||||
|
sane.fs."/var/lib/bluetooth".generated.acl.mode = "0700";
|
||||||
|
sane.fs."/var/lib/bluetooth/.secrets.stamp" = {
|
||||||
|
wantedBeforeBy = [ "bluetooth.service" ];
|
||||||
|
# XXX: install-bluetooth uses sed, but that's part of the default systemd unit path, it seems
|
||||||
|
generated.script.script = builtins.readFile ../../scripts/install-bluetooth + ''
|
||||||
|
touch "/var/lib/bluetooth/.secrets.stamp"
|
||||||
|
'';
|
||||||
|
generated.script.scriptArgs = [ "/run/secrets/bt" ];
|
||||||
|
};
|
||||||
|
}
|
15
hosts/common/cross.nix
Normal file
15
hosts/common/cross.nix
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{ ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
# the configuration of which specific package set `pkgs.cross` refers to happens elsewhere;
|
||||||
|
# here we just define them all.
|
||||||
|
nixpkgs.overlays = [
|
||||||
|
(next: prev: {
|
||||||
|
# non-emulated packages build *from* local *for* target.
|
||||||
|
# for large packages like the linux kernel which are expensive to build under emulation,
|
||||||
|
# the config can explicitly pull such packages from `pkgs.cross` to do more efficient cross-compilation.
|
||||||
|
crossFrom."x86_64-linux" = (prev.forceSystem "x86_64-linux" null).appendOverlays next.overlays;
|
||||||
|
crossFrom."aarch64-linux" = (prev.forceSystem "aarch64-linux" null).appendOverlays next.overlays;
|
||||||
|
})
|
||||||
|
];
|
||||||
|
}
|
@@ -1,91 +1,75 @@
|
|||||||
{ lib, pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
|
./bluetooth.nix
|
||||||
|
./cross.nix
|
||||||
./feeds.nix
|
./feeds.nix
|
||||||
./fs.nix
|
./fs.nix
|
||||||
./hardware.nix
|
./hardware
|
||||||
./home
|
./i2p.nix
|
||||||
./ids.nix
|
./ids.nix
|
||||||
./machine-id.nix
|
./machine-id.nix
|
||||||
./net.nix
|
./net.nix
|
||||||
./nix-path
|
|
||||||
./persist.nix
|
|
||||||
./programs
|
|
||||||
./secrets.nix
|
./secrets.nix
|
||||||
./ssh.nix
|
./ssh.nix
|
||||||
./users
|
./users.nix
|
||||||
./vpn.nix
|
./vpn.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
|
sane.home-manager.enable = true;
|
||||||
sane.nixcache.enable-trusted-keys = true;
|
sane.nixcache.enable-trusted-keys = true;
|
||||||
sane.nixcache.enable = lib.mkDefault true;
|
sane.packages.enableConsolePkgs = true;
|
||||||
sane.persist.enable = lib.mkDefault true;
|
sane.packages.enableSystemPkgs = true;
|
||||||
sane.programs.sysadminUtils.enableFor.system = lib.mkDefault true;
|
|
||||||
sane.programs.consoleUtils.enableFor.user.colin = lib.mkDefault true;
|
sane.persist.sys.plaintext = [
|
||||||
|
"/var/log"
|
||||||
|
"/var/backup" # for e.g. postgres dumps
|
||||||
|
# TODO: move elsewhere
|
||||||
|
"/var/lib/alsa" # preserve output levels, default devices
|
||||||
|
"/var/lib/colord" # preserve color calibrations (?)
|
||||||
|
"/var/lib/machines" # maybe not needed, but would be painful to add a VM and forget.
|
||||||
|
];
|
||||||
|
|
||||||
nixpkgs.config.allowUnfree = true;
|
nixpkgs.config.allowUnfree = true;
|
||||||
nixpkgs.config.allowBroken = true; # NIXPKGS_ALLOW_BROKEN
|
|
||||||
|
|
||||||
# time.timeZone = "America/Los_Angeles";
|
# time.timeZone = "America/Los_Angeles";
|
||||||
time.timeZone = "Etc/UTC"; # DST is too confusing for me => use a stable timezone
|
time.timeZone = "Etc/UTC"; # DST is too confusing for me => use a stable timezone
|
||||||
|
|
||||||
# allow `nix flake ...` command
|
# allow `nix flake ...` command
|
||||||
# TODO: is this still required?
|
|
||||||
nix.extraOptions = ''
|
nix.extraOptions = ''
|
||||||
experimental-features = nix-command flakes
|
experimental-features = nix-command flakes
|
||||||
'';
|
'';
|
||||||
# hardlinks identical files in the nix store to save 25-35% disk space.
|
|
||||||
# unclear _when_ this occurs. it's not a service.
|
|
||||||
# does the daemon continually scan the nix store?
|
|
||||||
# does the builder use some content-addressed db to efficiently dedupe?
|
|
||||||
nix.settings.auto-optimise-store = true;
|
|
||||||
|
|
||||||
systemd.services.nix-daemon.serviceConfig = {
|
# TODO: move this into home-manager?
|
||||||
# the nix-daemon manages nix builders
|
fonts = {
|
||||||
# kill nix-daemon subprocesses when systemd-oomd detects an out-of-memory condition
|
enableDefaultFonts = true;
|
||||||
# see:
|
fonts = with pkgs; [ font-awesome twitter-color-emoji hack-font ];
|
||||||
# - nixos PR that enabled systemd-oomd: <https://github.com/NixOS/nixpkgs/pull/169613>
|
fontconfig.enable = true;
|
||||||
# - systemd's docs on these properties: <https://www.freedesktop.org/software/systemd/man/systemd.resource-control.html#ManagedOOMSwap=auto%7Ckill>
|
fontconfig.defaultFonts = {
|
||||||
#
|
emoji = [ "Font Awesome 6 Free" "Twitter Color Emoji" ];
|
||||||
# systemd's docs warn that without swap, systemd-oomd might not be able to react quick enough to save the system.
|
monospace = [ "Hack" ];
|
||||||
# see `man oomd.conf` for further tunables that may help.
|
serif = [ "DejaVu Serif" ];
|
||||||
#
|
sansSerif = [ "DejaVu Sans" ];
|
||||||
# alternatively, apply this more broadly with `systemd.oomd.enableSystemSlice = true` or `enableRootSlice`
|
|
||||||
# TODO: also apply this to the guest user's slice (user-1100.slice)
|
|
||||||
# TODO: also apply this to distccd
|
|
||||||
ManagedOOMMemoryPressure = "kill";
|
|
||||||
ManagedOOMSwap = "kill";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
system.activationScripts.nixClosureDiff = {
|
|
||||||
supportsDryActivation = true;
|
|
||||||
text = ''
|
|
||||||
# show which packages changed versions or are new/removed in this upgrade
|
|
||||||
# source: <https://github.com/luishfonseca/dotfiles/blob/32c10e775d9ec7cc55e44592a060c1c9aadf113e/modules/upgrade-diff.nix>
|
|
||||||
${pkgs.nvd}/bin/nvd --nix-bin-dir=${pkgs.nix}/bin diff /run/current-system "$systemConfig"
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
# disable non-required packages like nano, perl, rsync, strace
|
# disable non-required packages like nano, perl, rsync, strace
|
||||||
environment.defaultPackages = [];
|
environment.defaultPackages = [];
|
||||||
|
|
||||||
# dconf docs: <https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/desktop_migration_and_administration_guide/profiles>
|
# programs.vim.defaultEditor = true;
|
||||||
# this lets programs temporarily write user-level dconf settings (aka gsettings).
|
environment.variables = {
|
||||||
# they're written to ~/.config/dconf/user, unless `DCONF_PROFILE` is set to something other than the default of /etc/dconf/profile/user
|
EDITOR = "vim";
|
||||||
# find keys/values with `dconf dump /`
|
# git claims it should use EDITOR, but it doesn't!
|
||||||
programs.dconf.enable = true;
|
GIT_EDITOR = "vim";
|
||||||
programs.dconf.packages = [
|
# TODO: these should be moved to `home.sessionVariables` (home-manager)
|
||||||
(pkgs.writeTextFile {
|
# Electron apps should use native wayland backend:
|
||||||
name = "dconf-user-profile";
|
# https://nixos.wiki/wiki/Slack#Wayland
|
||||||
destination = "/etc/dconf/profile/user";
|
# Discord under sway crashes with this.
|
||||||
text = ''
|
# NIXOS_OZONE_WL = "1";
|
||||||
user-db:user
|
# LIBGL_ALWAYS_SOFTWARE = "1";
|
||||||
system-db:site
|
};
|
||||||
'';
|
# enable zsh completions
|
||||||
})
|
environment.pathsToLink = [ "/share/zsh" ];
|
||||||
];
|
|
||||||
# sane.programs.glib.enableFor.user.colin = true; # for `gsettings`
|
|
||||||
|
|
||||||
# link debug symbols into /run/current-system/sw/lib/debug
|
# link debug symbols into /run/current-system/sw/lib/debug
|
||||||
# hopefully picked up by gdb automatically?
|
# hopefully picked up by gdb automatically?
|
||||||
|
@@ -1,13 +1,4 @@
|
|||||||
# where to find good stuff?
|
{ ... }:
|
||||||
# - podcast rec thread: <https://lemmy.ml/post/1565858>
|
|
||||||
#
|
|
||||||
# candidates:
|
|
||||||
# - The Nonlinear Library (podcast): <https://forum.effectivealtruism.org/posts/JTZTBienqWEAjGDRv/listen-to-more-ea-content-with-the-nonlinear-library>
|
|
||||||
# - has ~10 posts per day, text-to-speech; i would need better tagging before adding this
|
|
||||||
# - <https://www.metaculus.com/questions/11102/introducing-the-metaculus-journal-podcast/>
|
|
||||||
# - dead since 2022/10 - 2023/03
|
|
||||||
|
|
||||||
{ lib, sane-data, ... }:
|
|
||||||
let
|
let
|
||||||
hourly = { freq = "hourly"; };
|
hourly = { freq = "hourly"; };
|
||||||
daily = { freq = "daily"; };
|
daily = { freq = "daily"; };
|
||||||
@@ -21,9 +12,6 @@ let
|
|||||||
tech = { cat = "tech"; };
|
tech = { cat = "tech"; };
|
||||||
uncat = { cat = "uncat"; };
|
uncat = { cat = "uncat"; };
|
||||||
|
|
||||||
text = { format = "text"; };
|
|
||||||
img = { format = "image"; };
|
|
||||||
|
|
||||||
mkRss = format: url: { inherit url format; } // uncat // infrequent;
|
mkRss = format: url: { inherit url format; } // uncat // infrequent;
|
||||||
# format-specific helpers
|
# format-specific helpers
|
||||||
mkText = mkRss "text";
|
mkText = mkRss "text";
|
||||||
@@ -33,229 +21,131 @@ let
|
|||||||
# host-specific helpers
|
# host-specific helpers
|
||||||
mkSubstack = subdomain: { substack = subdomain; };
|
mkSubstack = subdomain: { substack = subdomain; };
|
||||||
|
|
||||||
fromDb = name:
|
|
||||||
let
|
|
||||||
raw = sane-data.feeds."${name}";
|
|
||||||
in {
|
|
||||||
url = raw.url;
|
|
||||||
# not sure the exact mapping with velocity here: entries per day?
|
|
||||||
freq = lib.mkIf (raw.velocity or 0 != 0) (lib.mkDefault (
|
|
||||||
if raw.velocity > 2 then
|
|
||||||
"hourly"
|
|
||||||
else if raw.velocity > 0.5 then
|
|
||||||
"daily"
|
|
||||||
else if raw.velocity > 0.1 then
|
|
||||||
"weekly"
|
|
||||||
else
|
|
||||||
"infrequent"
|
|
||||||
));
|
|
||||||
} // lib.optionalAttrs (raw.is_podcast or false) {
|
|
||||||
format = "podcast";
|
|
||||||
} // lib.optionalAttrs (raw.title or "" != "") {
|
|
||||||
title = lib.mkDefault raw.title;
|
|
||||||
};
|
|
||||||
|
|
||||||
podcasts = [
|
podcasts = [
|
||||||
(fromDb "lexfridman.com/podcast" // rat)
|
(mkPod "https://lexfridman.com/feed/podcast/" // rat // weekly)
|
||||||
## Astral Codex Ten
|
## Astral Codex Ten
|
||||||
(fromDb "sscpodcast.libsyn.com" // rat)
|
(mkPod "http://feeds.libsyn.com/108018/rss" // rat // daily)
|
||||||
## Less Wrong Curated
|
|
||||||
(fromDb "feeds.libsyn.com/421877" // rat)
|
|
||||||
## Econ Talk
|
## Econ Talk
|
||||||
(fromDb "feeds.simplecast.com/wgl4xEgL" // rat)
|
(mkPod "https://feeds.simplecast.com/wgl4xEgL" // rat // daily)
|
||||||
## Cory Doctorow -- both podcast & text entries
|
## Cory Doctorow
|
||||||
(fromDb "craphound.com" // pol)
|
(mkPod "https://feeds.feedburner.com/doctorow_podcast" // pol // infrequent)
|
||||||
## Maggie Killjoy -- referenced by Cory Doctorow
|
(mkPod "https://congressionaldish.libsyn.com/rss" // pol // infrequent)
|
||||||
(fromDb "omny.fm/shows/cool-people-who-did-cool-stuff" // pol)
|
## Civboot
|
||||||
(fromDb "congressionaldish.libsyn.com" // pol)
|
(mkPod "https://anchor.fm/s/34c7232c/podcast/rss" // tech // infrequent)
|
||||||
# (mkPod "https://podcasts.la.utexas.edu/this-is-democracy/feed/podcast/" // pol // weekly)
|
(mkPod "https://feeds.feedburner.com/80000HoursPodcast" // rat // weekly)
|
||||||
## Civboot -- https://anchor.fm/civboot
|
(mkPod "https://allinchamathjason.libsyn.com/rss" // pol // weekly)
|
||||||
(fromDb "anchor.fm/s/34c7232c/podcast/rss" // tech)
|
(mkPod "https://acquired.libsyn.com/rss" // tech // infrequent)
|
||||||
## Emerge: making sense of what's next -- <https://www.whatisemerging.com/emergepodcast>
|
(mkPod "https://rss.acast.com/deconstructed" // pol // infrequent)
|
||||||
(mkPod "https://anchor.fm/s/21bc734/podcast/rss" // pol // infrequent)
|
|
||||||
(fromDb "feeds.feedburner.com/80000HoursPodcast" // rat)
|
|
||||||
## Daniel Huberman on sleep
|
|
||||||
(fromDb "feeds.megaphone.fm/hubermanlab" // uncat)
|
|
||||||
## Multidisciplinary Association for Psychedelic Studies
|
|
||||||
(fromDb "mapspodcast.libsyn.com" // uncat)
|
|
||||||
(fromDb "allinchamathjason.libsyn.com" // pol)
|
|
||||||
(fromDb "feeds.transistor.fm/acquired" // tech)
|
|
||||||
## ACQ2 - more "Acquired" episodes
|
|
||||||
(fromDb "acquiredlpbonussecretsecret.libsyn.com" // tech)
|
|
||||||
# The Intercept - Deconstructed
|
|
||||||
(fromDb "rss.acast.com/deconstructed")
|
|
||||||
# (fromDb "rss.prod.firstlook.media/deconstructed/podcast.rss" // pol) #< possible URL rot
|
|
||||||
## The Daily
|
## The Daily
|
||||||
(mkPod "https://feeds.simplecast.com/54nAGcIl" // pol // daily)
|
(mkPod "https://feeds.simplecast.com/54nAGcIl" // pol // daily)
|
||||||
# The Intercept - Intercepted
|
(mkPod "https://rss.acast.com/intercepted-with-jeremy-scahill" // pol // weekly)
|
||||||
(fromDb "rss.acast.com/intercepted-with-jeremy-scahill")
|
(mkPod "https://podcast.posttv.com/itunes/post-reports.xml" // pol // weekly)
|
||||||
# (fromDb "rss.prod.firstlook.media/intercepted/podcast.rss" // pol) #< possible URL rot
|
|
||||||
(fromDb "podcast.posttv.com/itunes/post-reports.xml" // pol)
|
|
||||||
## Eric Weinstein
|
## Eric Weinstein
|
||||||
(fromDb "rss.art19.com/the-portal" // rat)
|
(mkPod "https://rss.art19.com/the-portal" // rat // infrequent)
|
||||||
(fromDb "darknetdiaries.com" // tech)
|
(mkPod "https://feeds.megaphone.fm/darknetdiaries" // tech // infrequent)
|
||||||
## Radiolab -- also available here, but ONLY OVER HTTP: <http://feeds.wnyc.org/radiolab>
|
(mkPod "http://feeds.wnyc.org/radiolab" // pol // infrequent)
|
||||||
(fromDb "feeds.feedburner.com/radiolab" // pol)
|
(mkPod "https://wakingup.libsyn.com/rss" // pol // infrequent)
|
||||||
## Sam Harris
|
## 99% Invisible
|
||||||
(fromDb "wakingup.libsyn.com" // pol)
|
(mkPod "https://feeds.simplecast.com/BqbsxVfO" // pol // infrequent)
|
||||||
## 99% Invisible -- also available here: <https://feeds.simplecast.com/BqbsxVfO>
|
(mkPod "https://rss.acast.com/ft-tech-tonic" // tech // infrequent)
|
||||||
(fromDb "feeds.99percentinvisible.org/99percentinvisible" // pol)
|
(mkPod "https://feeds.feedburner.com/dancarlin/history?format=xml" // rat // infrequent)
|
||||||
(fromDb "rss.acast.com/ft-tech-tonic" // tech)
|
## 60 minutes (NB: this features more than *just* audio?)
|
||||||
(fromDb "feeds.feedburner.com/dancarlin/history" // rat)
|
(mkPod "https://www.cbsnews.com/latest/rss/60-minutes" // pol // infrequent)
|
||||||
(fromDb "rss.art19.com/60-minutes" // pol)
|
|
||||||
## The Verge - Decoder
|
## The Verge - Decoder
|
||||||
(fromDb "feeds.megaphone.fm/recodedecode" // tech)
|
(mkPod "https://feeds.megaphone.fm/recodedecode" // tech // weekly)
|
||||||
## Matrix (chat) Live
|
## Matrix (chat) Live
|
||||||
(fromDb "feed.podbean.com/matrixlive/feed.xml" // tech)
|
(mkPod "https://feed.podbean.com/matrixlive/feed.xml" // tech // weekly)
|
||||||
(fromDb "cast.postmarketos.org" // tech)
|
## Michael Malice - Your Welcome
|
||||||
(fromDb "podcast.thelinuxexp.com" // tech)
|
(mkPod "https://www.podcastone.com/podcast?categoryID2=2232" // pol // weekly)
|
||||||
## Michael Malice - Your Welcome -- also available here: <https://origin.podcastone.com/podcast?categoryID2=2232>
|
|
||||||
(fromDb "rss.art19.com/your-welcome" // pol)
|
|
||||||
(fromDb "seattlenice.buzzsprout.com" // pol)
|
|
||||||
## Sci-Fi? has Peter Watts; author of No Moods, Ads or Cutesy Fucking Icons (rifters.com)
|
|
||||||
(fromDb "talesfromthebridge.buzzsprout.com" // tech)
|
|
||||||
## UnNamed Reverse Engineering Podcast
|
|
||||||
(fromDb "reverseengineering.libsyn.com/rss" // tech)
|
|
||||||
## The Witch Trials of J.K. Rowling
|
|
||||||
## - <https://www.thefp.com/witchtrials>
|
|
||||||
(mkPod "https://feeds.megaphone.fm/RUNMED9919162779" // pol // infrequent)
|
|
||||||
## Atlas Obscura
|
|
||||||
(fromDb "feeds.simplecast.com/xKJ93w_w" // uncat)
|
|
||||||
## Ezra Klein Show
|
|
||||||
(fromDb "feeds.simplecast.com/82FI35Px" // pol)
|
|
||||||
## Wireshark Podcast o_0
|
|
||||||
(fromDb "sharkbytes.transistor.fm" // tech)
|
|
||||||
];
|
];
|
||||||
|
|
||||||
texts = [
|
texts = [
|
||||||
# AGGREGATORS (> 1 post/day)
|
# AGGREGATORS (> 1 post/day)
|
||||||
(fromDb "lwn.net" // tech)
|
(mkText "https://www.lesswrong.com/feed.xml" // rat // hourly)
|
||||||
# (fromDb "lesswrong.com" // rat)
|
(mkText "http://www.econlib.org/index.xml" // pol // hourly)
|
||||||
# (fromDb "econlib.org" // pol)
|
|
||||||
|
|
||||||
# AGGREGATORS (< 1 post/day)
|
# AGGREGATORS (< 1 post/day)
|
||||||
(fromDb "palladiummag.com" // uncat)
|
(mkText "https://palladiummag.com/feed" // uncat // weekly)
|
||||||
(fromDb "profectusmag.com" // uncat)
|
(mkText "https://profectusmag.com/feed" // uncat // weekly)
|
||||||
(fromDb "semiaccurate.com" // tech)
|
(mkText "https://semiaccurate.com/feed" // tech // weekly)
|
||||||
(mkText "https://linuxphoneapps.org/blog/atom.xml" // tech // infrequent)
|
(mkText "https://linuxphoneapps.org/blog/atom.xml" // tech // infrequent)
|
||||||
(fromDb "tuxphones.com" // tech)
|
(mkText "https://spectrum.ieee.org/rss" // tech // weekly)
|
||||||
(fromDb "spectrum.ieee.org" // tech)
|
|
||||||
(fromDb "theregister.com" // tech)
|
|
||||||
(fromDb "thisweek.gnome.org" // tech)
|
|
||||||
# more nixos stuff here, but unclear how to subscribe: <https://nixos.org/blog/categories.html>
|
|
||||||
(mkText "https://nixos.org/blog/announcements-rss.xml" // tech // infrequent)
|
|
||||||
(mkText "https://nixos.org/blog/stories-rss.xml" // tech // weekly)
|
|
||||||
## n.b.: quality RSS list here: <https://forum.merveilles.town/thread/57/share-your-rss-feeds%21-6/>
|
|
||||||
(mkText "https://forum.merveilles.town/rss.xml" // pol // infrequent)
|
|
||||||
|
|
||||||
## No Moods, Ads or Cutesy Fucking Icons
|
## No Moods, Ads or Cutesy Fucking Icons
|
||||||
(fromDb "rifters.com/crawl" // uncat)
|
(mkText "https://www.rifters.com/crawl/?feed=rss2" // uncat // weekly)
|
||||||
|
|
||||||
# DEVELOPERS
|
# DEVELOPERS
|
||||||
(fromDb "blog.jmp.chat" // tech)
|
(mkText "https://uninsane.org/atom.xml" // infrequent // tech)
|
||||||
(fromDb "uninsane.org" // tech)
|
(mkText "https://mg.lol/blog/rss/" // infrequent // tech)
|
||||||
(fromDb "ascii.textfiles.com" // tech) # Jason Scott
|
|
||||||
(fromDb "xn--gckvb8fzb.com" // tech)
|
|
||||||
(fromDb "mg.lol" // tech)
|
|
||||||
# (fromDb "drewdevault.com" // tech)
|
|
||||||
## Ken Shirriff
|
## Ken Shirriff
|
||||||
(fromDb "righto.com" // tech)
|
(mkText "https://www.righto.com/feeds/posts/default" // tech // infrequent)
|
||||||
## shared blog by a few NixOS devs, notably onny
|
|
||||||
(fromDb "project-insanity.org" // tech)
|
|
||||||
## Vitalik Buterin
|
## Vitalik Buterin
|
||||||
(fromDb "vitalik.ca" // tech)
|
(mkText "https://vitalik.ca/feed.xml" // tech // infrequent)
|
||||||
## ian (Sanctuary)
|
## ian (Sanctuary)
|
||||||
(fromDb "sagacioussuricata.com" // tech)
|
(mkText "https://sagacioussuricata.com/feed.xml" // tech // infrequent)
|
||||||
## Bunnie Juang
|
## Bunnie Juang
|
||||||
(fromDb "bunniestudios.com" // tech)
|
(mkText "https://www.bunniestudios.com/blog/?feed=rss2" // tech // infrequent)
|
||||||
(fromDb "blog.danieljanus.pl" // tech)
|
(mkText "https://blog.danieljanus.pl/atom.xml" // tech // infrequent)
|
||||||
(fromDb "ianthehenry.com" // tech)
|
(mkText "https://ianthehenry.com/feed.xml" // tech // infrequent)
|
||||||
(fromDb "bitbashing.io" // tech)
|
(mkText "https://bitbashing.io/feed.xml" // tech // infrequent)
|
||||||
(fromDb "idiomdrottning.org" // uncat)
|
(mkText "https://idiomdrottning.org/feed.xml" // uncat // daily)
|
||||||
(mkText "http://boginjr.com/feed" // tech // infrequent)
|
|
||||||
(mkText "https://anish.lakhwara.com/home.html" // tech // weekly)
|
(mkText "https://anish.lakhwara.com/home.html" // tech // weekly)
|
||||||
(fromDb "jefftk.com" // tech)
|
(mkText "https://www.jefftk.com/news.rss" // tech // daily)
|
||||||
(fromDb "pomeroyb.com" // tech)
|
(mkText "https://pomeroyb.com/feed.xml" // tech // infrequent)
|
||||||
# (mkText "https://til.simonwillison.net/tils/feed.atom" // tech // weekly)
|
|
||||||
|
|
||||||
# TECH PROJECTS
|
|
||||||
(fromDb "blog.rust-lang.org" // tech)
|
|
||||||
|
|
||||||
# (TECH; POL) COMMENTATORS
|
# (TECH; POL) COMMENTATORS
|
||||||
## Matt Webb -- engineering-ish, but dreamy
|
(mkSubstack "edwardsnowden" // pol // infrequent)
|
||||||
(fromDb "interconnected.org/home/feed" // rat)
|
|
||||||
(fromDb "edwardsnowden.substack.com" // pol // text)
|
|
||||||
## Julia Evans
|
|
||||||
(mkText "https://jvns.ca/atom.xml" // tech // weekly)
|
|
||||||
(mkText "http://benjaminrosshoffman.com/feed" // pol // weekly)
|
(mkText "http://benjaminrosshoffman.com/feed" // pol // weekly)
|
||||||
## Ben Thompson
|
## Ben Thompson
|
||||||
(mkText "https://www.stratechery.com/rss" // pol // weekly)
|
(mkText "https://www.stratechery.com/rss" // pol // weekly)
|
||||||
## Balaji
|
## Balaji
|
||||||
(fromDb "balajis.com" // pol)
|
(mkText "https://balajis.com/rss" // pol // weekly)
|
||||||
(fromDb "ben-evans.com/benedictevans" // pol)
|
(mkText "https://www.ben-evans.com/benedictevans/rss.xml" // pol // weekly)
|
||||||
(fromDb "lynalden.com" // pol)
|
(mkText "https://www.lynalden.com/feed" // pol // infrequent)
|
||||||
(fromDb "austinvernon.site" // tech)
|
(mkText "https://austinvernon.site/rss.xml" // tech // infrequent)
|
||||||
(mkSubstack "oversharing" // pol // daily)
|
(mkSubstack "oversharing" // pol // daily)
|
||||||
(mkSubstack "byrnehobart" // pol // infrequent)
|
(mkSubstack "doomberg" // tech // weekly)
|
||||||
# (mkSubstack "doomberg" // tech // weekly) # articles are all pay-walled
|
|
||||||
## David Rosenthal
|
## David Rosenthal
|
||||||
(fromDb "blog.dshr.org" // pol)
|
(mkText "https://blog.dshr.org/rss.xml" // pol // weekly)
|
||||||
## Matt Levine
|
## Matt Levine
|
||||||
(mkText "https://www.bloomberg.com/opinion/authors/ARbTQlRLRjE/matthew-s-levine.rss" // pol // weekly)
|
(mkText "https://www.bloomberg.com/opinion/authors/ARbTQlRLRjE/matthew-s-levine.rss" // pol // weekly)
|
||||||
(fromDb "stpeter.im/atom.xml" // pol)
|
(mkText "https://stpeter.im/atom.xml" // pol // weekly)
|
||||||
## Peter Saint-Andre -- side project of stpeter.im
|
|
||||||
(fromDb "philosopher.coach" // rat)
|
|
||||||
(fromDb "morningbrew.com/feed" // pol)
|
|
||||||
|
|
||||||
# RATIONALITY/PHILOSOPHY/ETC
|
# RATIONALITY/PHILOSOPHY/ETC
|
||||||
(mkSubstack "samkriss" // humor // infrequent)
|
(mkSubstack "samkriss" // humor // infrequent)
|
||||||
(fromDb "unintendedconsequenc.es" // rat)
|
(mkText "https://unintendedconsequenc.es/feed" // rat // infrequent)
|
||||||
(fromDb "applieddivinitystudies.com" // rat)
|
(mkText "https://applieddivinitystudies.com/atom.xml" // rat // weekly)
|
||||||
(fromDb "slimemoldtimemold.com" // rat)
|
(mkText "https://slimemoldtimemold.com/feed.xml" // rat // weekly)
|
||||||
(fromDb "richardcarrier.info" // rat)
|
(mkText "https://www.richardcarrier.info/feed" // rat // weekly)
|
||||||
(fromDb "gwern.net" // rat)
|
(mkText "https://www.gwern.net/feed.xml" // uncat // infrequent)
|
||||||
## Jason Crawford
|
## Jason Crawford
|
||||||
(fromDb "rootsofprogress.org" // rat)
|
(mkText "https://rootsofprogress.org/feed.xml" // rat // weekly)
|
||||||
## Robin Hanson
|
## Robin Hanson
|
||||||
(fromDb "overcomingbias.com" // rat)
|
(mkText "https://www.overcomingbias.com/feed" // rat // daily)
|
||||||
## Scott Alexander
|
## Scott Alexander
|
||||||
(mkSubstack "astralcodexten" // rat // daily)
|
(mkSubstack "astralcodexten" // rat // daily)
|
||||||
## Paul Christiano
|
## Paul Christiano
|
||||||
(fromDb "sideways-view.com" // rat)
|
(mkText "https://sideways-view.com/feed" // rat // infrequent)
|
||||||
## Sean Carroll
|
## Sean Carroll
|
||||||
(fromDb "preposterousuniverse.com" // rat)
|
(mkText "https://www.preposterousuniverse.com/rss" // rat // infrequent)
|
||||||
(mkSubstack "eliqian" // rat // weekly)
|
|
||||||
(mkText "https://acoup.blog/feed" // rat // weekly)
|
|
||||||
(fromDb "mindingourway.com" // rat)
|
|
||||||
|
|
||||||
## mostly dating topics. not advice, or humor, but looking through a social lens
|
## mostly dating topics. not advice, or humor, but looking through a social lens
|
||||||
(fromDb "putanumonit.com" // rat)
|
(mkText "https://putanumonit.com/feed" // rat // infrequent)
|
||||||
|
|
||||||
# LOCAL
|
|
||||||
(fromDb "capitolhillseattle.com" // pol)
|
|
||||||
|
|
||||||
# CODE
|
# CODE
|
||||||
# (mkText "https://github.com/Kaiteki-Fedi/Kaiteki/commits/master.atom" // tech // infrequent)
|
# (mkText "https://github.com/Kaiteki-Fedi/Kaiteki/commits/master.atom" // tech // infrequent)
|
||||||
];
|
];
|
||||||
|
|
||||||
images = [
|
images = [
|
||||||
(fromDb "smbc-comics.com" // img // humor)
|
(mkImg "https://www.smbc-comics.com/comic/rss" // humor // daily)
|
||||||
(fromDb "xkcd.com" // img // humor)
|
(mkImg "https://xkcd.com/atom.xml" // humor // daily)
|
||||||
(fromDb "pbfcomics.com" // img // humor)
|
(mkImg "https://pbfcomics.com/feed" // humor // infrequent)
|
||||||
# (mkImg "http://dilbert.com/feed" // humor // daily)
|
# (mkImg "http://dilbert.com/feed" // humor // daily)
|
||||||
(fromDb "poorlydrawnlines.com/feed" // img // humor)
|
|
||||||
|
|
||||||
# ART
|
# ART
|
||||||
(fromDb "miniature-calendar.com" // img // art // daily)
|
(mkImg "https://miniature-calendar.com/feed" // art // daily)
|
||||||
];
|
];
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
sane.feeds = texts ++ images ++ podcasts;
|
sane.feeds = texts ++ images ++ podcasts;
|
||||||
|
|
||||||
assertions = builtins.map
|
|
||||||
(p: {
|
|
||||||
assertion = p.format or "unknown" == "podcast";
|
|
||||||
message = ''${p.url} is not a podcast: ${p.format or "unknown"}'';
|
|
||||||
})
|
|
||||||
podcasts;
|
|
||||||
}
|
}
|
||||||
|
@@ -1,134 +1,72 @@
|
|||||||
# docs
|
{ pkgs, ... }:
|
||||||
# - x-systemd options: <https://www.freedesktop.org/software/systemd/man/systemd.mount.html>
|
|
||||||
|
|
||||||
{ pkgs, sane-lib, ... }:
|
let sshOpts = rec {
|
||||||
|
fsType = "fuse.sshfs";
|
||||||
let fsOpts = rec {
|
optionsBase = [
|
||||||
common = [
|
"x-systemd.automount"
|
||||||
"_netdev"
|
"_netdev"
|
||||||
"noatime"
|
"user"
|
||||||
"user" # allow any user with access to the device to mount the fs
|
|
||||||
"x-systemd.requires=network-online.target"
|
|
||||||
"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
|
|
||||||
wg = [
|
|
||||||
"x-systemd.requires=wireguard-wg-home.service"
|
|
||||||
"x-systemd.after=wireguard-wg-home.service"
|
|
||||||
];
|
|
||||||
|
|
||||||
ssh = common ++ [
|
|
||||||
"identityfile=/home/colin/.ssh/id_ed25519"
|
"identityfile=/home/colin/.ssh/id_ed25519"
|
||||||
"allow_other"
|
"allow_other"
|
||||||
"default_permissions"
|
"default_permissions"
|
||||||
];
|
];
|
||||||
sshColin = ssh ++ [
|
optionsColin = optionsBase ++ [
|
||||||
"transform_symlinks"
|
"transform_symlinks"
|
||||||
"idmap=user"
|
"idmap=user"
|
||||||
"uid=1000"
|
"uid=1000"
|
||||||
"gid=100"
|
"gid=100"
|
||||||
];
|
];
|
||||||
sshRoot = ssh ++ [
|
|
||||||
|
optionsRoot = optionsBase ++ [
|
||||||
# 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:
|
|
||||||
# - <https://unix.stackexchange.com/questions/31979/stop-broken-nfs-mounts-from-locking-a-directory>
|
|
||||||
|
|
||||||
# NFS options: <https://linux.die.net/man/5/nfs>
|
|
||||||
# actimeo=n = how long (in seconds) to cache file/dir attributes (default: 3-60s)
|
|
||||||
# bg = retry failed mounts in the background
|
|
||||||
# retry=n = for how many minutes `mount` will retry NFS mount operation
|
|
||||||
# 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)
|
|
||||||
# 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.
|
|
||||||
nfs = common ++ [
|
|
||||||
# "actimeo=10"
|
|
||||||
"bg"
|
|
||||||
"retrans=4"
|
|
||||||
"retry=0"
|
|
||||||
"soft"
|
|
||||||
"timeo=15"
|
|
||||||
"nofail" # don't fail remote-fs.target when this mount fails (not an option for sshfs else would be common)
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
# 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
|
|
||||||
# defaults to compressing at most 50% size of RAM
|
|
||||||
# claimed compression ratio is about 2:1
|
|
||||||
# - 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)
|
|
||||||
# docs: <https://www.kernel.org/doc/Documentation/blockdev/zram.txt>
|
|
||||||
#
|
|
||||||
# to query effectiveness:
|
|
||||||
# `cat /sys/block/zram0/mm_stat`. whitespace separated fields:
|
|
||||||
# - *orig_data_size* (bytes)
|
|
||||||
# - *compr_data_size* (bytes)
|
|
||||||
# - mem_used_total (bytes)
|
|
||||||
# - mem_limit (bytes)
|
|
||||||
# - mem_used_max (bytes)
|
|
||||||
# - *same_pages* (pages which are e.g. all zeros (consumes no additional mem))
|
|
||||||
# - *pages_compacted* (pages which have been freed thanks to compression)
|
|
||||||
# - huge_pages (incompressible)
|
|
||||||
#
|
|
||||||
# see also:
|
|
||||||
# - `man zramctl`
|
|
||||||
zramSwap.enable = true;
|
|
||||||
# how much ram can be swapped into the zram device.
|
|
||||||
# this shouldn't be higher than the observed compression ratio.
|
|
||||||
# the default is 50% (why?)
|
|
||||||
# 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)
|
|
||||||
zramSwap.memoryPercent = 100;
|
|
||||||
|
|
||||||
# fileSystems."/mnt/servo-nfs" = {
|
|
||||||
# device = "servo-hn:/";
|
|
||||||
# noCheck = true;
|
|
||||||
# fsType = "nfs";
|
|
||||||
# options = fsOpts.nfs ++ fsOpts.auto ++ fsOpts.wg;
|
|
||||||
# };
|
|
||||||
fileSystems."/mnt/servo-nfs/media" = {
|
|
||||||
device = "servo-hn:/media";
|
|
||||||
noCheck = true;
|
|
||||||
fsType = "nfs";
|
|
||||||
options = fsOpts.nfs ++ fsOpts.auto ++ fsOpts.wg;
|
|
||||||
};
|
|
||||||
# fileSystems."/mnt/servo-media-nfs" = {
|
|
||||||
# device = "servo-hn:/media";
|
|
||||||
# noCheck = true;
|
|
||||||
# fsType = "nfs";
|
|
||||||
# options = fsOpts.common ++ fsOpts.auto;
|
|
||||||
# };
|
|
||||||
sane.fs."/mnt/servo-media" = sane-lib.fs.wantedSymlinkTo "/mnt/servo-nfs/media";
|
|
||||||
|
|
||||||
fileSystems."/mnt/desko-home" = {
|
|
||||||
device = "colin@desko:/home/colin";
|
|
||||||
fsType = "fuse.sshfs";
|
|
||||||
options = fsOpts.sshColin ++ fsOpts.noauto;
|
|
||||||
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.pathsToLink = [
|
||||||
# needed to achieve superuser access for user-mounted filesystems (see optionsRoot above)
|
# needed to achieve superuser access for user-mounted filesystems (see optionsRoot above)
|
||||||
# we can only link whole directories here, even though we're only interested in pkgs.openssh
|
# we can only link whole directories here, even though we're only interested in pkgs.openssh
|
||||||
"/libexec"
|
"/libexec"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
fileSystems."/mnt/servo-media-wan" = {
|
||||||
|
device = "colin@uninsane.org:/var/lib/uninsane/media";
|
||||||
|
inherit (sshOpts) fsType;
|
||||||
|
options = sshOpts.optionsColin;
|
||||||
|
noCheck = true;
|
||||||
|
};
|
||||||
|
fileSystems."/mnt/servo-media-lan" = {
|
||||||
|
device = "colin@servo:/var/lib/uninsane/media";
|
||||||
|
inherit (sshOpts) fsType;
|
||||||
|
options = sshOpts.optionsColin;
|
||||||
|
noCheck = true;
|
||||||
|
};
|
||||||
|
fileSystems."/mnt/servo-root-wan" = {
|
||||||
|
device = "colin@uninsane.org:/";
|
||||||
|
inherit (sshOpts) fsType;
|
||||||
|
options = sshOpts.optionsRoot;
|
||||||
|
noCheck = true;
|
||||||
|
};
|
||||||
|
fileSystems."/mnt/servo-root-lan" = {
|
||||||
|
device = "colin@servo:/";
|
||||||
|
inherit (sshOpts) fsType;
|
||||||
|
options = sshOpts.optionsRoot;
|
||||||
|
noCheck = true;
|
||||||
|
};
|
||||||
|
fileSystems."/mnt/desko-home" = {
|
||||||
|
device = "colin@desko:/home/colin";
|
||||||
|
inherit (sshOpts) fsType;
|
||||||
|
options = sshOpts.optionsColin;
|
||||||
|
noCheck = true;
|
||||||
|
};
|
||||||
|
fileSystems."/mnt/desko-root" = {
|
||||||
|
device = "colin@desko:/";
|
||||||
|
inherit (sshOpts) fsType;
|
||||||
|
options = sshOpts.optionsRoot;
|
||||||
|
noCheck = true;
|
||||||
|
};
|
||||||
|
|
||||||
environment.systemPackages = [
|
environment.systemPackages = [
|
||||||
pkgs.sshfs-fuse
|
pkgs.sshfs-fuse
|
||||||
];
|
];
|
||||||
|
@@ -23,15 +23,11 @@
|
|||||||
|
|
||||||
# non-free firmware
|
# non-free firmware
|
||||||
hardware.enableRedistributableFirmware = true;
|
hardware.enableRedistributableFirmware = true;
|
||||||
|
services.fwupd.enable = true;
|
||||||
|
|
||||||
# powertop will default to putting USB devices -- including HID -- to sleep after TWO SECONDS
|
# powertop will default to putting USB devices -- including HID -- to sleep after TWO SECONDS
|
||||||
powerManagement.powertop.enable = false;
|
powerManagement.powertop.enable = false;
|
||||||
|
|
||||||
services.logind.extraConfig = ''
|
|
||||||
# don’t shutdown when power button is short-pressed
|
|
||||||
HandlePowerKey=ignore
|
|
||||||
'';
|
|
||||||
|
|
||||||
# services.snapper.configs = {
|
# services.snapper.configs = {
|
||||||
# root = {
|
# root = {
|
||||||
# subvolume = "/";
|
# subvolume = "/";
|
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
|
./all.nix
|
||||||
./x86_64.nix
|
./x86_64.nix
|
||||||
];
|
];
|
||||||
}
|
}
|
@@ -1,7 +1,8 @@
|
|||||||
{ lib, pkgs, ... }:
|
{ lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
{
|
{
|
||||||
config = lib.mkIf (pkgs.system == "x86_64-linux") {
|
config = mkIf (pkgs.system == "x86_64-linux") {
|
||||||
boot.initrd.availableKernelModules = [
|
boot.initrd.availableKernelModules = [
|
||||||
"xhci_pci" "ahci" "sd_mod" "sdhci_pci" # nixos-generate-config defaults
|
"xhci_pci" "ahci" "sd_mod" "sdhci_pci" # nixos-generate-config defaults
|
||||||
"usb_storage" # rpi needed this to boot from usb storage, i think.
|
"usb_storage" # rpi needed this to boot from usb storage, i think.
|
||||||
@@ -9,6 +10,11 @@
|
|||||||
# efi_pstore evivars
|
# efi_pstore evivars
|
||||||
];
|
];
|
||||||
|
|
||||||
|
# enable cross compilation
|
||||||
|
boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
|
||||||
|
# nixpkgs.config.allowUnsupportedSystem = true;
|
||||||
|
# nixpkgs.crossSystem.system = "aarch64-linux";
|
||||||
|
|
||||||
powerManagement.cpuFreqGovernor = "powersave";
|
powerManagement.cpuFreqGovernor = "powersave";
|
||||||
hardware.cpu.amd.updateMicrocode = true; # desktop
|
hardware.cpu.amd.updateMicrocode = true; # desktop
|
||||||
hardware.cpu.intel.updateMicrocode = true; # laptop
|
hardware.cpu.intel.updateMicrocode = true; # laptop
|
@@ -1,9 +0,0 @@
|
|||||||
{ ... }:
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
./keyring
|
|
||||||
./mime.nix
|
|
||||||
./ssh.nix
|
|
||||||
./xdg-dirs.nix
|
|
||||||
];
|
|
||||||
}
|
|
@@ -1,17 +0,0 @@
|
|||||||
{ config, pkgs, sane-lib, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
init-keyring = pkgs.static-nix-shell.mkBash {
|
|
||||||
pname = "init-keyring";
|
|
||||||
src = ./.;
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
sane.user.persist.private = [ ".local/share/keyrings" ];
|
|
||||||
|
|
||||||
sane.user.fs."private/.local/share/keyrings/default" = {
|
|
||||||
generated.command = [ "${init-keyring}/bin/init-keyring" ];
|
|
||||||
wantedBy = [ config.sane.fs."/home/colin/private".unit ];
|
|
||||||
wantedBeforeBy = [ ]; # don't created this as part of `multi-user.target`
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,28 +0,0 @@
|
|||||||
{ config, lib, ...}:
|
|
||||||
|
|
||||||
let
|
|
||||||
# ProgramConfig -> { "<mime-type>" = { priority, desktop }; }
|
|
||||||
weightedMimes = prog: builtins.mapAttrs (_key: desktop: { priority = prog.mime.priority; desktop = desktop; }) prog.mime.associations;
|
|
||||||
# [ { "<mime-type>" = { priority, desktop } ]; } ] -> { "<mime-type>" = [ { priority, desktop } ... ]; }
|
|
||||||
mergeMimes = mimes: lib.foldAttrs (item: acc: [item] ++ acc) [] mimes;
|
|
||||||
# [ { priority, desktop } ... ] -> Self
|
|
||||||
sortOneMimeType = associations: builtins.sort (l: r: assert l.priority != r.priority; l.priority < r.priority) associations;
|
|
||||||
sortMimes = mimes: builtins.mapAttrs (_k: sortOneMimeType) mimes;
|
|
||||||
removePriorities = mimes: builtins.mapAttrs (_k: associations: builtins.map (a: a.desktop) associations) mimes;
|
|
||||||
|
|
||||||
# [ ProgramConfig ]
|
|
||||||
enabledPrograms = builtins.filter (p: p.enabled) (builtins.attrValues config.sane.programs);
|
|
||||||
# [ { "<mime-type>" = { prority, desktop } ]
|
|
||||||
enabledWeightedMimes = builtins.map weightedMimes enabledPrograms;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
# the xdg mime type for a file can be found with:
|
|
||||||
# - `xdg-mime query filetype path/to/thing.ext`
|
|
||||||
# the default handler for a mime type can be found with:
|
|
||||||
# - `xdg-mime query default <mimetype>` (e.g. x-scheme-handler/http)
|
|
||||||
#
|
|
||||||
# we can have single associations or a list of associations.
|
|
||||||
# there's also options to *remove* [non-default] associations from specific apps
|
|
||||||
xdg.mime.enable = true;
|
|
||||||
xdg.mime.defaultApplications = removePriorities (sortMimes (mergeMimes enabledWeightedMimes));
|
|
||||||
}
|
|
@@ -1,29 +0,0 @@
|
|||||||
# TODO: this should be moved to users/colin.nix
|
|
||||||
{ config, lib, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
host = config.networking.hostName;
|
|
||||||
user-pubkey-full = config.sane.ssh.pubkeys."colin@${host}" or {};
|
|
||||||
user-pubkey = user-pubkey-full.asUserKey or null;
|
|
||||||
host-keys = lib.filter (k: k.user == "root") (lib.attrValues config.sane.ssh.pubkeys);
|
|
||||||
known-hosts-text = lib.concatStringsSep
|
|
||||||
"\n"
|
|
||||||
(builtins.map (k: k.asHostKey) host-keys)
|
|
||||||
;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
# ssh key is stored in private storage
|
|
||||||
sane.user.persist.private = [
|
|
||||||
{ type = "file"; path = ".ssh/id_ed25519"; }
|
|
||||||
];
|
|
||||||
sane.user.fs.".ssh/id_ed25519.pub" = lib.mkIf (user-pubkey != null) {
|
|
||||||
symlink.text = user-pubkey;
|
|
||||||
};
|
|
||||||
sane.user.fs.".ssh/known_hosts".symlink.text = known-hosts-text;
|
|
||||||
|
|
||||||
users.users.colin.openssh.authorizedKeys.keys =
|
|
||||||
let
|
|
||||||
user-keys = lib.filter (k: k.user == "colin") (lib.attrValues config.sane.ssh.pubkeys);
|
|
||||||
in
|
|
||||||
builtins.map (k: k.asUserKey) user-keys;
|
|
||||||
}
|
|
@@ -1,20 +0,0 @@
|
|||||||
{ ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
# XDG defines things like ~/Desktop, ~/Downloads, etc.
|
|
||||||
# these clutter the home, so i mostly don't use them.
|
|
||||||
sane.user.fs.".config/user-dirs.dirs".symlink.text = ''
|
|
||||||
XDG_DESKTOP_DIR="$HOME/.xdg/Desktop"
|
|
||||||
XDG_DOCUMENTS_DIR="$HOME/dev"
|
|
||||||
XDG_DOWNLOAD_DIR="$HOME/tmp"
|
|
||||||
XDG_MUSIC_DIR="$HOME/Music"
|
|
||||||
XDG_PICTURES_DIR="$HOME/Pictures"
|
|
||||||
XDG_PUBLICSHARE_DIR="$HOME/.xdg/Public"
|
|
||||||
XDG_TEMPLATES_DIR="$HOME/.xdg/Templates"
|
|
||||||
XDG_VIDEOS_DIR="$HOME/Videos"
|
|
||||||
'';
|
|
||||||
|
|
||||||
# prevent `xdg-user-dirs-update` from overriding/updating our config
|
|
||||||
# see <https://manpages.ubuntu.com/manpages/bionic/man5/user-dirs.conf.5.html>
|
|
||||||
sane.user.fs.".config/user-dirs.conf".symlink.text = "enabled=False";
|
|
||||||
}
|
|
4
hosts/common/i2p.nix
Normal file
4
hosts/common/i2p.nix
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
services.i2p.enable = true;
|
||||||
|
}
|
@@ -1,6 +1,3 @@
|
|||||||
# TODO: migrate to nixpkgs `config.ids.uids`
|
|
||||||
# - note that nixpkgs' `config.ids.uids` is strictly a database: it doesn't set anything by default
|
|
||||||
# whereas our impl sets the gid/uid of the user/group specified if they exist.
|
|
||||||
{ ... }:
|
{ ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -15,8 +12,6 @@
|
|||||||
sane.ids.acme.gid = 996;
|
sane.ids.acme.gid = 996;
|
||||||
sane.ids.pleroma.uid = 997;
|
sane.ids.pleroma.uid = 997;
|
||||||
sane.ids.acme.uid = 998;
|
sane.ids.acme.uid = 998;
|
||||||
sane.ids.matrix-appservice-irc.uid = 993;
|
|
||||||
sane.ids.matrix-appservice-irc.gid = 992;
|
|
||||||
|
|
||||||
# greetd (used by sway)
|
# greetd (used by sway)
|
||||||
sane.ids.greeter.uid = 999;
|
sane.ids.greeter.uid = 999;
|
||||||
@@ -26,24 +21,6 @@
|
|||||||
sane.ids.freshrss.uid = 2401;
|
sane.ids.freshrss.uid = 2401;
|
||||||
sane.ids.freshrss.gid = 2401;
|
sane.ids.freshrss.gid = 2401;
|
||||||
sane.ids.mediawiki.uid = 2402;
|
sane.ids.mediawiki.uid = 2402;
|
||||||
sane.ids.signald.uid = 2403;
|
|
||||||
sane.ids.signald.gid = 2403;
|
|
||||||
sane.ids.mautrix-signal.uid = 2404;
|
|
||||||
sane.ids.mautrix-signal.gid = 2404;
|
|
||||||
sane.ids.navidrome.uid = 2405;
|
|
||||||
sane.ids.navidrome.gid = 2405;
|
|
||||||
sane.ids.calibre-web.uid = 2406;
|
|
||||||
sane.ids.calibre-web.gid = 2406;
|
|
||||||
sane.ids.komga.uid = 2407;
|
|
||||||
sane.ids.komga.gid = 2407;
|
|
||||||
sane.ids.lemmy.uid = 2408;
|
|
||||||
sane.ids.lemmy.gid = 2408;
|
|
||||||
sane.ids.pict-rs.uid = 2409;
|
|
||||||
sane.ids.pict-rs.gid = 2409;
|
|
||||||
sane.ids.sftpgo.uid = 2410;
|
|
||||||
sane.ids.sftpgo.gid = 2410;
|
|
||||||
sane.ids.trust-dns.uid = 2411;
|
|
||||||
sane.ids.trust-dns.gid = 2411;
|
|
||||||
|
|
||||||
sane.ids.colin.uid = 1000;
|
sane.ids.colin.uid = 1000;
|
||||||
sane.ids.guest.uid = 1100;
|
sane.ids.guest.uid = 1100;
|
||||||
@@ -52,12 +29,11 @@
|
|||||||
sane.ids.sshd.uid = 2001; # 997
|
sane.ids.sshd.uid = 2001; # 997
|
||||||
sane.ids.sshd.gid = 2001; # 997
|
sane.ids.sshd.gid = 2001; # 997
|
||||||
sane.ids.polkituser.gid = 2002; # 998
|
sane.ids.polkituser.gid = 2002; # 998
|
||||||
sane.ids.systemd-coredump.gid = 2003; # 996 # 2023/02/12-2023/02/28: upstream temporarily specified this as 151
|
sane.ids.systemd-coredump.gid = 2003; # 996
|
||||||
sane.ids.nscd.uid = 2004;
|
sane.ids.nscd.uid = 2004;
|
||||||
sane.ids.nscd.gid = 2004;
|
sane.ids.nscd.gid = 2004;
|
||||||
sane.ids.systemd-oom.uid = 2005;
|
sane.ids.systemd-oom.uid = 2005;
|
||||||
sane.ids.systemd-oom.gid = 2005;
|
sane.ids.systemd-oom.gid = 2005;
|
||||||
sane.ids.wireshark.gid = 2006;
|
|
||||||
|
|
||||||
# found on graphical hosts
|
# found on graphical hosts
|
||||||
sane.ids.nm-iodine.uid = 2101; # desko/moby/lappy
|
sane.ids.nm-iodine.uid = 2101; # desko/moby/lappy
|
||||||
|
@@ -1,6 +1,16 @@
|
|||||||
{ lib, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
|
# if using router's DNS, these mappings will already exist.
|
||||||
|
# if using a different DNS provider (which servo does), then we need to explicity provide them.
|
||||||
|
# ugly hack. would be better to get servo to somehow use the router's DNS
|
||||||
|
networking.hosts = {
|
||||||
|
"192.168.0.5" = [ "servo" ];
|
||||||
|
"192.168.0.20" = [ "lappy" ];
|
||||||
|
"192.168.0.22" = [ "desko" ];
|
||||||
|
"192.168.0.48" = [ "moby" ];
|
||||||
|
};
|
||||||
|
|
||||||
# the default backend is "wpa_supplicant".
|
# the default backend is "wpa_supplicant".
|
||||||
# wpa_supplicant reliably picks weak APs to connect to.
|
# wpa_supplicant reliably picks weak APs to connect to.
|
||||||
# see: <https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/474>
|
# see: <https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/474>
|
||||||
@@ -11,37 +21,23 @@
|
|||||||
# - `man iwd.config` for global config
|
# - `man iwd.config` for global config
|
||||||
# - `man iwd.network` for per-SSID config
|
# - `man iwd.network` for per-SSID config
|
||||||
# use `iwctl` to control
|
# use `iwctl` to control
|
||||||
# networking.networkmanager.wifi.backend = "iwd";
|
networking.networkmanager.wifi.backend = "iwd";
|
||||||
# networking.wireless.iwd.enable = true;
|
networking.wireless.iwd.enable = true;
|
||||||
# networking.wireless.iwd.settings = {
|
networking.wireless.iwd.settings = {
|
||||||
# # auto-connect to a stronger network if signal drops below this value
|
# auto-connect to a stronger network if signal drops below this value
|
||||||
# # bedroom -> bedroom connection is -35 to -40 dBm
|
# bedroom -> bedroom connection is -35 to -40 dBm
|
||||||
# # bedroom -> living room connection is -60 dBm
|
# bedroom -> living room connection is -60 dBm
|
||||||
# General.RoamThreshold = "-52"; # default -70
|
General.RoamThreshold = "-52"; # default -70
|
||||||
# General.RoamThreshold5G = "-52"; # default -76
|
General.RoamThreshold5G = "-52"; # default -76
|
||||||
# };
|
};
|
||||||
|
|
||||||
# plugins mostly add support for establishing different VPN connections.
|
sane.fs."/var/lib/iwd/.secrets.psk.stamp" = {
|
||||||
# the default plugin set includes mostly proprietary VPNs:
|
wantedBeforeBy = [ "iwd.service" ];
|
||||||
# - fortisslvpn (Fortinet)
|
generated.acl.mode = "0600";
|
||||||
# - iodine (DNS tunnels)
|
# XXX: install-iwd uses sed, but that's part of the default systemd unit path, it seems
|
||||||
# - l2tp
|
generated.script.script = builtins.readFile ../../scripts/install-iwd + ''
|
||||||
# - openconnect (Cisco Anyconnect / Juniper / ocserv)
|
touch "/var/lib/iwd/.secrets.psk.stamp"
|
||||||
# - openvpn
|
|
||||||
# - vpnc (Cisco VPN)
|
|
||||||
# - sstp
|
|
||||||
#
|
|
||||||
# i don't use these, and notably they drag in huge dependency sets and don't cross compile well.
|
|
||||||
# e.g. openconnect drags in webkitgtk (for SSO)!
|
|
||||||
networking.networkmanager.plugins = lib.mkForce [];
|
|
||||||
|
|
||||||
networking.firewall.allowedUDPPorts = [
|
|
||||||
1900 # to received UPnP advertisements. required by sane-ip-check-upnp
|
|
||||||
];
|
|
||||||
|
|
||||||
# keyfile.path = where networkmanager should look for connection credentials
|
|
||||||
networking.networkmanager.extraConfig = ''
|
|
||||||
[keyfile]
|
|
||||||
path=/var/lib/NetworkManager/system-connections
|
|
||||||
'';
|
'';
|
||||||
|
generated.script.scriptArgs = [ "/run/secrets/iwd" "/var/lib/iwd" ];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@@ -1,13 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
# allow `nix-shell` (and probably nix-index?) to locate our patched and custom packages
|
|
||||||
nix.nixPath = [
|
|
||||||
"nixpkgs=${pkgs.path}"
|
|
||||||
# note the import starts at repo root: this allows `./overlay/default.nix` to access the stuff at the root
|
|
||||||
# "nixpkgs-overlays=${../../..}/hosts/common/nix-path/overlay"
|
|
||||||
# as long as my system itself doesn't rely on NIXPKGS at runtime, we can point the overlays to git
|
|
||||||
# to avoid switching so much during development
|
|
||||||
"nixpkgs-overlays=/home/colin/dev/nixos/hosts/common/nix-path/overlay"
|
|
||||||
];
|
|
||||||
}
|
|
@@ -1,4 +0,0 @@
|
|||||||
# XXX: NIX_PATH=...:nixpkgs-overlays=... will import every overlay in the directory
|
|
||||||
# so we prefer to give it a directory with just this *one* overlay, otherwise it imports conflicting overlays
|
|
||||||
# and gets stuck in a loop until it OOMs
|
|
||||||
import ../../../../overlays/all.nix
|
|
@@ -1,16 +0,0 @@
|
|||||||
{ ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
sane.persist.stores.private.origin = "/home/colin/private";
|
|
||||||
# store /home/colin/a/b in /home/private/a/b instead of /home/private/home/colin/a/b
|
|
||||||
sane.persist.stores.private.prefix = "/home/colin";
|
|
||||||
|
|
||||||
sane.persist.sys.plaintext = [
|
|
||||||
# TODO: these should be private.. somehow
|
|
||||||
"/var/log"
|
|
||||||
"/var/backup" # for e.g. postgres dumps
|
|
||||||
];
|
|
||||||
sane.persist.sys.cryptClearOnBoot = [
|
|
||||||
"/var/lib/systemd/coredump"
|
|
||||||
];
|
|
||||||
}
|
|
@@ -1,9 +0,0 @@
|
|||||||
# Terminal UI mail client
|
|
||||||
{ ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
sane.programs.aerc = {
|
|
||||||
secrets.".config/aerc/accounts.conf" = ../../../secrets/common/aerc_accounts.conf.bin;
|
|
||||||
mime.associations."x-scheme-handler/mailto" = "aerc.desktop";
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,254 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
declPackageSet = pkgs: {
|
|
||||||
package = null;
|
|
||||||
suggestedPrograms = pkgs;
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
sane.programs = {
|
|
||||||
# PACKAGE SETS
|
|
||||||
"sane-scripts.backup" = declPackageSet [
|
|
||||||
"sane-scripts.backup-ls"
|
|
||||||
"sane-scripts.backup-restore"
|
|
||||||
];
|
|
||||||
"sane-scripts.bittorrent" = declPackageSet [
|
|
||||||
"sane-scripts.bt-add"
|
|
||||||
"sane-scripts.bt-rm"
|
|
||||||
"sane-scripts.bt-search"
|
|
||||||
"sane-scripts.bt-show"
|
|
||||||
];
|
|
||||||
"sane-scripts.dev" = declPackageSet [
|
|
||||||
"sane-scripts.dev-cargo-loop"
|
|
||||||
"sane-scripts.git-init"
|
|
||||||
];
|
|
||||||
"sane-scripts.cli" = declPackageSet [
|
|
||||||
"sane-scripts.deadlines"
|
|
||||||
"sane-scripts.find-dotfiles"
|
|
||||||
"sane-scripts.ip-check"
|
|
||||||
"sane-scripts.ip-reconnect"
|
|
||||||
"sane-scripts.private-change-passwd"
|
|
||||||
"sane-scripts.private-do"
|
|
||||||
"sane-scripts.private-init"
|
|
||||||
"sane-scripts.private-lock"
|
|
||||||
"sane-scripts.private-unlock"
|
|
||||||
"sane-scripts.rcp"
|
|
||||||
"sane-scripts.reboot"
|
|
||||||
"sane-scripts.reclaim-boot-space"
|
|
||||||
"sane-scripts.reclaim-disk-space"
|
|
||||||
"sane-scripts.secrets-dump"
|
|
||||||
"sane-scripts.secrets-unlock"
|
|
||||||
"sane-scripts.secrets-update-keys"
|
|
||||||
"sane-scripts.shutdown"
|
|
||||||
"sane-scripts.ssl-dump"
|
|
||||||
"sane-scripts.sudo-redirect"
|
|
||||||
"sane-scripts.sync-from-servo"
|
|
||||||
"sane-scripts.vpn-down"
|
|
||||||
"sane-scripts.vpn-up"
|
|
||||||
"sane-scripts.which"
|
|
||||||
"sane-scripts.wipe-browser"
|
|
||||||
];
|
|
||||||
"sane-scripts.sys-utils" = declPackageSet [
|
|
||||||
"sane-scripts.ip-port-forward"
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
sysadminUtils = declPackageSet [
|
|
||||||
"btrfs-progs"
|
|
||||||
"cacert.unbundled" # some services require unbundled /etc/ssl/certs
|
|
||||||
"cryptsetup"
|
|
||||||
"dig"
|
|
||||||
"efibootmgr"
|
|
||||||
"fatresize"
|
|
||||||
"fd"
|
|
||||||
"file"
|
|
||||||
# "fwupd"
|
|
||||||
"gawk"
|
|
||||||
"git"
|
|
||||||
"gptfdisk"
|
|
||||||
"hdparm"
|
|
||||||
"htop"
|
|
||||||
"iftop"
|
|
||||||
"inetutils" # for telnet
|
|
||||||
"iotop"
|
|
||||||
"iptables"
|
|
||||||
"jq"
|
|
||||||
"killall"
|
|
||||||
"lsof"
|
|
||||||
"miniupnpc"
|
|
||||||
"nano"
|
|
||||||
# "ncdu" # ncurses disk usage. doesn't cross compile (zig)
|
|
||||||
"neovim"
|
|
||||||
"netcat"
|
|
||||||
"nethogs"
|
|
||||||
"nmap"
|
|
||||||
"openssl"
|
|
||||||
"parted"
|
|
||||||
"pciutils"
|
|
||||||
"powertop"
|
|
||||||
"pstree"
|
|
||||||
"ripgrep"
|
|
||||||
"screen"
|
|
||||||
"smartmontools"
|
|
||||||
"socat"
|
|
||||||
"strace"
|
|
||||||
"subversion"
|
|
||||||
"tcpdump"
|
|
||||||
"tree"
|
|
||||||
"usbutils"
|
|
||||||
"wget"
|
|
||||||
"wirelesstools" # iwlist
|
|
||||||
];
|
|
||||||
sysadminExtraUtils = declPackageSet [
|
|
||||||
"backblaze-b2"
|
|
||||||
"duplicity"
|
|
||||||
"sane-scripts.backup"
|
|
||||||
"sqlite" # to debug sqlite3 databases
|
|
||||||
];
|
|
||||||
|
|
||||||
# TODO: split these into smaller groups.
|
|
||||||
# - moby doesn't want a lot of these.
|
|
||||||
# - categories like
|
|
||||||
# - dev?
|
|
||||||
# - debugging?
|
|
||||||
consoleUtils = declPackageSet [
|
|
||||||
"alsaUtils" # for aplay, speaker-test
|
|
||||||
# "cdrtools"
|
|
||||||
"clinfo"
|
|
||||||
"dmidecode"
|
|
||||||
"dtrx" # `unar` alternative, "Do The Right eXtraction"
|
|
||||||
"efivar"
|
|
||||||
# "flashrom"
|
|
||||||
"git" # needed as a user package, for config.
|
|
||||||
# "gnupg"
|
|
||||||
# "gocryptfs"
|
|
||||||
# "gopass"
|
|
||||||
# "gopass-jsonapi"
|
|
||||||
"helix" # text editor
|
|
||||||
"kitty" # TODO: move to GUI, but `ssh servo` from kitty sets `TERM=xterm-kitty` in the remove and breaks things
|
|
||||||
"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
|
|
||||||
"lshw"
|
|
||||||
# "memtester"
|
|
||||||
"neovim" # needed as a user package, for swap persistence
|
|
||||||
# "nettools"
|
|
||||||
# "networkmanager"
|
|
||||||
# "nixos-generators"
|
|
||||||
"nmon"
|
|
||||||
# "node2nix"
|
|
||||||
# "oathToolkit" # for oathtool
|
|
||||||
# "ponymix"
|
|
||||||
"pulsemixer"
|
|
||||||
"python3"
|
|
||||||
# "python3Packages.eyeD3" # music tagging
|
|
||||||
"ripgrep" # needed as a user package so that its user-level config file can be installed
|
|
||||||
"rsync"
|
|
||||||
"sane-scripts.bittorrent"
|
|
||||||
"sane-scripts.cli"
|
|
||||||
"snapper"
|
|
||||||
"sops"
|
|
||||||
"speedtest-cli"
|
|
||||||
# "ssh-to-age"
|
|
||||||
"sudo"
|
|
||||||
# "tageditor" # music tagging
|
|
||||||
# "unar"
|
|
||||||
"wireguard-tools"
|
|
||||||
"xdg-terminal-exec"
|
|
||||||
"xdg-utils" # for xdg-open
|
|
||||||
# "yarn"
|
|
||||||
"zsh"
|
|
||||||
];
|
|
||||||
|
|
||||||
desktopConsoleUtils = declPackageSet [
|
|
||||||
"gh" # MS GitHub cli
|
|
||||||
"nix-index"
|
|
||||||
"nixpkgs-review"
|
|
||||||
"sane-scripts.dev"
|
|
||||||
"sequoia"
|
|
||||||
];
|
|
||||||
|
|
||||||
consoleMediaUtils = declPackageSet [
|
|
||||||
"ffmpeg"
|
|
||||||
"imagemagick"
|
|
||||||
"sox"
|
|
||||||
"yt-dlp"
|
|
||||||
];
|
|
||||||
|
|
||||||
tuiApps = declPackageSet [
|
|
||||||
"aerc" # email client
|
|
||||||
"msmtp" # sendmail
|
|
||||||
"offlineimap" # email mailbox sync
|
|
||||||
"sfeed" # RSS fetcher
|
|
||||||
"visidata" # TUI spreadsheet viewer/editor
|
|
||||||
"w3m" # web browser
|
|
||||||
];
|
|
||||||
|
|
||||||
iphoneUtils = declPackageSet [
|
|
||||||
"ifuse"
|
|
||||||
"ipfs"
|
|
||||||
"libimobiledevice"
|
|
||||||
"sane-scripts.sync-from-iphone"
|
|
||||||
];
|
|
||||||
|
|
||||||
devPkgs = declPackageSet [
|
|
||||||
"clang"
|
|
||||||
"nodejs"
|
|
||||||
"tree-sitter"
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
# INDIVIDUAL PACKAGE DEFINITIONS
|
|
||||||
|
|
||||||
dino.persist.private = [ ".local/share/dino" ];
|
|
||||||
|
|
||||||
# creds, but also 200 MB of node modules, etc
|
|
||||||
discord.persist.private = [ ".config/discord" ];
|
|
||||||
|
|
||||||
# `emote` will show a first-run dialog based on what's in this directory.
|
|
||||||
# mostly, it just keeps a LRU of previously-used emotes to optimize display order.
|
|
||||||
# TODO: package [smile](https://github.com/mijorus/smile) for probably a better mobile experience.
|
|
||||||
emote.persist.plaintext = [ ".local/share/Emote" ];
|
|
||||||
|
|
||||||
fluffychat-moby.persist.plaintext = [ ".local/share/chat.fluffy.fluffychat" ];
|
|
||||||
|
|
||||||
# MS GitHub stores auth token in .config
|
|
||||||
# TODO: we can populate gh's stuff statically; it even lets us use the same oauth across machines
|
|
||||||
gh.persist.private = [ ".config/gh" ];
|
|
||||||
|
|
||||||
# actual monero blockchain (not wallet/etc; safe to delete, just slow to regenerate)
|
|
||||||
# XXX: is it really safe to persist this? it doesn't have info that could de-anonymize if captured?
|
|
||||||
monero-gui.persist.plaintext = [ ".bitmonero" ];
|
|
||||||
|
|
||||||
mumble.persist.private = [ ".local/share/Mumble" ];
|
|
||||||
|
|
||||||
# settings (electron app)
|
|
||||||
obsidian.persist.plaintext = [ ".config/obsidian" ];
|
|
||||||
|
|
||||||
# creds, media
|
|
||||||
signal-desktop.persist.private = [ ".config/Signal" ];
|
|
||||||
|
|
||||||
# printer/filament settings
|
|
||||||
slic3r.persist.plaintext = [ ".Slic3r" ];
|
|
||||||
|
|
||||||
# creds, widevine .so download. TODO: could easily manage these statically.
|
|
||||||
spotify.persist.plaintext = [ ".config/spotify" ];
|
|
||||||
|
|
||||||
tdesktop.persist.private = [ ".local/share/TelegramDesktop" ];
|
|
||||||
|
|
||||||
tokodon.persist.private = [ ".cache/KDE/tokodon" ];
|
|
||||||
|
|
||||||
# hardenedMalloc solves an "unable to connect to Tor" error when pressing the "connect" button
|
|
||||||
# - still required as of 2023/07/14
|
|
||||||
tor-browser-bundle-bin.package = pkgs.tor-browser-bundle-bin.override {
|
|
||||||
useHardenedMalloc = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
whalebird.persist.private = [ ".config/Whalebird" ];
|
|
||||||
|
|
||||||
yarn.persist.plaintext = [ ".cache/yarn" ];
|
|
||||||
|
|
||||||
# zcash coins. safe to delete, just slow to regenerate (10-60 minutes)
|
|
||||||
zecwallet-lite.persist.private = [ ".zcash" ];
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,44 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
let
|
|
||||||
chattyNoOauth = pkgs.chatty.override {
|
|
||||||
# the OAuth feature (presumably used for web-based logins) pulls a full webkitgtk.
|
|
||||||
# especially when using the gtk3 version of evolution-data-server, it's an ancient webkitgtk_4_1.
|
|
||||||
# disable OAuth for a faster build & smaller closure
|
|
||||||
evolution-data-server = pkgs.evolution-data-server.override {
|
|
||||||
enableOAuth2 = false;
|
|
||||||
gnome-online-accounts = pkgs.gnome-online-accounts.override {
|
|
||||||
# disables the upstream "goabackend" feature -- presumably "Gnome Online Accounts Backend"
|
|
||||||
# frees us from webkit_4_1, in turn.
|
|
||||||
enableBackend = false;
|
|
||||||
gvfs = pkgs.gvfs.override {
|
|
||||||
# saves 20 minutes of build time, for unused feature
|
|
||||||
samba = null;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
chatty-latest = pkgs.chatty-latest.override {
|
|
||||||
evolution-data-server-gtk4 = pkgs.evolution-data-server-gtk4.override {
|
|
||||||
gnome-online-accounts = pkgs.gnome-online-accounts.override {
|
|
||||||
# disables the upstream "goabackend" feature -- presumably "Gnome Online Accounts Backend"
|
|
||||||
# frees us from webkit_4_1, in turn.
|
|
||||||
enableBackend = false;
|
|
||||||
gvfs = pkgs.gvfs.override {
|
|
||||||
# saves 20 minutes of build time, for unused feature
|
|
||||||
samba = null;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
sane.programs.chatty = {
|
|
||||||
# package = chattyNoOauth;
|
|
||||||
package = chatty-latest;
|
|
||||||
suggestedPrograms = [ "gnome-keyring" ];
|
|
||||||
persist.private = [
|
|
||||||
".local/share/chatty" # matrix avatars and files
|
|
||||||
# ".purple" # XMPP stuff
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,11 +0,0 @@
|
|||||||
{ ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
sane.programs.cozy = {
|
|
||||||
# cozy uses a sqlite db for its config and exposes no CLI options other than --help and --debug
|
|
||||||
persist.plaintext = [
|
|
||||||
".local/share/cozy" # sqlite db (config & index?)
|
|
||||||
".cache/cozy" # offline cache
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,58 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
./aerc.nix
|
|
||||||
./assorted.nix
|
|
||||||
./chatty.nix
|
|
||||||
./cozy.nix
|
|
||||||
./element-desktop.nix
|
|
||||||
./epiphany.nix
|
|
||||||
./evince.nix
|
|
||||||
./firefox.nix
|
|
||||||
./fontconfig.nix
|
|
||||||
./fractal.nix
|
|
||||||
./fwupd.nix
|
|
||||||
./git.nix
|
|
||||||
./gnome-feeds.nix
|
|
||||||
./gnome-keyring.nix
|
|
||||||
./gpodder.nix
|
|
||||||
./gthumb.nix
|
|
||||||
./helix.nix
|
|
||||||
./imagemagick.nix
|
|
||||||
./jellyfin-media-player.nix
|
|
||||||
./kitty
|
|
||||||
./komikku.nix
|
|
||||||
./koreader
|
|
||||||
./libreoffice.nix
|
|
||||||
./lemoa.nix
|
|
||||||
./megapixels.nix
|
|
||||||
./mepo.nix
|
|
||||||
./mpv.nix
|
|
||||||
./msmtp.nix
|
|
||||||
./neovim.nix
|
|
||||||
./newsflash.nix
|
|
||||||
./nheko.nix
|
|
||||||
./nix-index.nix
|
|
||||||
./obsidian.nix
|
|
||||||
./offlineimap.nix
|
|
||||||
./ripgrep.nix
|
|
||||||
./sfeed.nix
|
|
||||||
./splatmoji.nix
|
|
||||||
./steam.nix
|
|
||||||
./sublime-music.nix
|
|
||||||
./tangram.nix
|
|
||||||
./tuba.nix
|
|
||||||
./vlc.nix
|
|
||||||
./wireshark.nix
|
|
||||||
./xarchiver.nix
|
|
||||||
./zeal.nix
|
|
||||||
./zsh
|
|
||||||
];
|
|
||||||
|
|
||||||
config = {
|
|
||||||
# XXX: this might not be necessary. try removing this and cacert.unbundled (servo)?
|
|
||||||
environment.etc."ssl/certs".source = "${pkgs.cacert.unbundled}/etc/ssl/certs/*";
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,9 +0,0 @@
|
|||||||
{ ... }:
|
|
||||||
{
|
|
||||||
sane.programs.element-desktop = {
|
|
||||||
# creds/session keys, etc
|
|
||||||
persist.private = [ ".config/Element" ];
|
|
||||||
|
|
||||||
suggestedPrograms = [ "gnome-keyring" ];
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,45 +0,0 @@
|
|||||||
# epiphany web browser
|
|
||||||
# - GTK4/webkitgtk
|
|
||||||
#
|
|
||||||
# usability notes:
|
|
||||||
# - touch-based scroll works well (for moby)
|
|
||||||
# - URL bar constantly resets cursor to the start of the line as i type
|
|
||||||
# - maybe due to the URLbar suggestions getting in the way
|
|
||||||
{ pkgs, ... }:
|
|
||||||
{
|
|
||||||
sane.programs.epiphany = {
|
|
||||||
# XXX(2023/07/08): running on moby without this hack fails, with:
|
|
||||||
# - `bwrap: Can't make symlink at /var/run: File exists`
|
|
||||||
# this could be due to:
|
|
||||||
# - epiphany is somewhere following a symlink into /var/run instead of /run
|
|
||||||
# - (nothing in `env` or in this repo touches /var/run)
|
|
||||||
# - no xdg-desktop-portal is installed (unlikely)
|
|
||||||
#
|
|
||||||
# a few other users have hit this, in different contexts:
|
|
||||||
# - <https://gitlab.gnome.org/GNOME/gnome-builder/-/issues/1164>
|
|
||||||
# - <https://github.com/flatpak/flatpak/issues/3477>
|
|
||||||
# - <https://github.com/NixOS/nixpkgs/issues/197085>
|
|
||||||
package = pkgs.epiphany.overrideAttrs (upstream: {
|
|
||||||
preFixup = ''
|
|
||||||
gappsWrapperArgs+=(
|
|
||||||
--set WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS "1"
|
|
||||||
);
|
|
||||||
'' + (upstream.preFixup or "");
|
|
||||||
});
|
|
||||||
persist.private = [
|
|
||||||
".cache/epiphany"
|
|
||||||
".local/share/epiphany"
|
|
||||||
# also .config/epiphany, but appears empty
|
|
||||||
];
|
|
||||||
mime.priority = 200; # default priority is 100: install epiphany only as a fallback
|
|
||||||
mime.associations = let
|
|
||||||
desktop = "org.gnome.Epiphany.desktop";
|
|
||||||
in {
|
|
||||||
"text/html" = desktop;
|
|
||||||
"x-scheme-handler/http" = desktop;
|
|
||||||
"x-scheme-handler/https" = desktop;
|
|
||||||
"x-scheme-handler/about" = desktop;
|
|
||||||
"x-scheme-handler/unknown" = desktop;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,4 +0,0 @@
|
|||||||
{ ... }:
|
|
||||||
{
|
|
||||||
sane.programs.evince.mime.associations."application/pdf" = "org.gnome.Evince.desktop";
|
|
||||||
}
|
|
@@ -1,262 +0,0 @@
|
|||||||
# common settings to toggle (at runtime, in about:config):
|
|
||||||
# > security.ssl.require_safe_negotiation
|
|
||||||
|
|
||||||
# librewolf is a forked firefox which patches firefox to allow more things
|
|
||||||
# (like default search engines) to be configurable at runtime.
|
|
||||||
# many of the settings below won't have effect without those patches.
|
|
||||||
# see: https://gitlab.com/librewolf-community/settings/-/blob/master/distribution/policies.json
|
|
||||||
|
|
||||||
{ config, lib, pkgs, ...}:
|
|
||||||
with lib;
|
|
||||||
let
|
|
||||||
cfg = config.sane.programs.firefox.config;
|
|
||||||
mobile-prefs = lib.optionals false pkgs.librewolf-pmos-mobile.extraPrefsFiles;
|
|
||||||
# allow easy switching between firefox and librewolf with `defaultSettings`, below
|
|
||||||
librewolfSettings = {
|
|
||||||
browser = pkgs.librewolf-unwrapped;
|
|
||||||
extraPrefsFiles = pkgs.librewolf-unwrapped.extraPrefsFiles ++ mobile-prefs;
|
|
||||||
libName = "librewolf";
|
|
||||||
dotDir = ".librewolf";
|
|
||||||
cacheDir = ".cache/librewolf";
|
|
||||||
desktop = "librewolf.desktop";
|
|
||||||
};
|
|
||||||
firefoxSettings = {
|
|
||||||
browser = pkgs.firefox-esr-unwrapped;
|
|
||||||
extraPrefsFiles = mobile-prefs;
|
|
||||||
libName = "firefox";
|
|
||||||
dotDir = ".mozilla/firefox";
|
|
||||||
cacheDir = ".cache/mozilla";
|
|
||||||
desktop = "firefox.desktop";
|
|
||||||
};
|
|
||||||
# defaultSettings = firefoxSettings;
|
|
||||||
defaultSettings = librewolfSettings;
|
|
||||||
|
|
||||||
addon = name: extid: hash: pkgs.fetchFirefoxAddon {
|
|
||||||
inherit name hash;
|
|
||||||
url = "https://addons.mozilla.org/firefox/downloads/latest/${name}/latest.xpi";
|
|
||||||
# extid can be found by unar'ing the above xpi, and copying browser_specific_settings.gecko.id field
|
|
||||||
fixedExtid = extid;
|
|
||||||
};
|
|
||||||
localAddon = pkg: pkgs.fetchFirefoxAddon {
|
|
||||||
inherit (pkg) name;
|
|
||||||
src = "${pkg}/share/mozilla/extensions/\\{ec8030f7-c20a-464f-9b0e-13a3a9e97384\\}/${pkg.extid}.xpi";
|
|
||||||
fixedExtid = pkg.extid;
|
|
||||||
};
|
|
||||||
|
|
||||||
package = pkgs.wrapFirefox cfg.browser.browser {
|
|
||||||
# inherit the default librewolf.cfg
|
|
||||||
# it can be further customized via ~/.librewolf/librewolf.overrides.cfg
|
|
||||||
inherit (cfg.browser) extraPrefsFiles libName;
|
|
||||||
|
|
||||||
extraNativeMessagingHosts = optional cfg.addons.browserpass-extension.enable pkgs.browserpass;
|
|
||||||
# extraNativeMessagingHosts = [ pkgs.gopass-native-messaging-host ];
|
|
||||||
|
|
||||||
nixExtensions = concatMap (ext: optional ext.enable ext.package) (attrValues cfg.addons);
|
|
||||||
|
|
||||||
extraPolicies = {
|
|
||||||
FirefoxHome = {
|
|
||||||
Search = true;
|
|
||||||
Pocket = false;
|
|
||||||
Snippets = false;
|
|
||||||
TopSites = false;
|
|
||||||
Highlights = false;
|
|
||||||
};
|
|
||||||
NoDefaultBookmarks = true;
|
|
||||||
OfferToSaveLogins = false;
|
|
||||||
OfferToSaveLoginsDefault = false;
|
|
||||||
PasswordManagerEnabled = false;
|
|
||||||
SearchEngines = {
|
|
||||||
Default = "DuckDuckGo";
|
|
||||||
};
|
|
||||||
UserMessaging = {
|
|
||||||
ExtensionRecommendations = false;
|
|
||||||
FeatureRecommendations = false;
|
|
||||||
SkipOnboarding = true;
|
|
||||||
UrlbarInterventions = false;
|
|
||||||
WhatsNew = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
# these were taken from Librewolf
|
|
||||||
AppUpdateURL = "https://localhost";
|
|
||||||
DisableAppUpdate = true;
|
|
||||||
OverrideFirstRunPage = "";
|
|
||||||
OverridePostUpdatePage = "";
|
|
||||||
DisableSystemAddonUpdate = true;
|
|
||||||
DisableFirefoxStudies = true;
|
|
||||||
DisableTelemetry = true;
|
|
||||||
DisableFeedbackCommands = true;
|
|
||||||
DisablePocket = true;
|
|
||||||
DisableSetDesktopBackground = false;
|
|
||||||
|
|
||||||
# remove many default search providers
|
|
||||||
# XXX this seems to prevent the `nixExtensions` from taking effect
|
|
||||||
# Extensions.Uninstall = [
|
|
||||||
# "google@search.mozilla.org"
|
|
||||||
# "bing@search.mozilla.org"
|
|
||||||
# "amazondotcom@search.mozilla.org"
|
|
||||||
# "ebay@search.mozilla.org"
|
|
||||||
# "twitter@search.mozilla.org"
|
|
||||||
# ];
|
|
||||||
# XXX doesn't seem to have any effect...
|
|
||||||
# docs: https://github.com/mozilla/policy-templates#homepage
|
|
||||||
# Homepage = {
|
|
||||||
# HomepageURL = "https://uninsane.org/";
|
|
||||||
# StartPage = "homepage";
|
|
||||||
# };
|
|
||||||
# NewTabPage = true;
|
|
||||||
};
|
|
||||||
# extraPrefs = ...
|
|
||||||
};
|
|
||||||
|
|
||||||
addonOpts = types.submodule {
|
|
||||||
options = {
|
|
||||||
package = mkOption {
|
|
||||||
type = types.package;
|
|
||||||
};
|
|
||||||
enable = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
configOpts = {
|
|
||||||
options = {
|
|
||||||
browser = mkOption {
|
|
||||||
default = defaultSettings;
|
|
||||||
type = types.anything;
|
|
||||||
};
|
|
||||||
persistData = mkOption {
|
|
||||||
description = "optional store name to which persist browsing data (like history)";
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
persistCache = mkOption {
|
|
||||||
description = "optional store name to which persist browser cache";
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = "cryptClearOnBoot";
|
|
||||||
};
|
|
||||||
addons = mkOption {
|
|
||||||
type = types.attrsOf addonOpts;
|
|
||||||
default = {};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
config = mkMerge [
|
|
||||||
({
|
|
||||||
sane.programs.firefox.configOption = mkOption {
|
|
||||||
type = types.submodule configOpts;
|
|
||||||
default = {};
|
|
||||||
};
|
|
||||||
sane.programs.firefox.config.addons = {
|
|
||||||
browserpass-extension = {
|
|
||||||
package = pkgs.firefox-extensions.browserpass-extension;
|
|
||||||
enable = lib.mkDefault true;
|
|
||||||
};
|
|
||||||
bypass-paywalls-clean = {
|
|
||||||
package = pkgs.firefox-extensions.bypass-paywalls-clean;
|
|
||||||
enable = lib.mkDefault true;
|
|
||||||
};
|
|
||||||
ether-metamask = {
|
|
||||||
package = pkgs.firefox-extensions.ether-metamask;
|
|
||||||
enable = lib.mkDefault false; # until i can disable the first-run notification
|
|
||||||
};
|
|
||||||
i2p-in-private-browsing = {
|
|
||||||
package = pkgs.firefox-extensions.i2p-in-private-browsing;
|
|
||||||
enable = lib.mkDefault config.services.i2p.enable;
|
|
||||||
};
|
|
||||||
sidebery = {
|
|
||||||
package = pkgs.firefox-extensions.sidebery;
|
|
||||||
enable = lib.mkDefault true;
|
|
||||||
};
|
|
||||||
sponsorblock = {
|
|
||||||
package = pkgs.firefox-extensions.sponsorblock;
|
|
||||||
enable = lib.mkDefault true;
|
|
||||||
};
|
|
||||||
ublacklist = {
|
|
||||||
package = pkgs.firefox-extensions.ublacklist;
|
|
||||||
enable = lib.mkDefault true;
|
|
||||||
};
|
|
||||||
ublock-origin = {
|
|
||||||
package = pkgs.firefox-extensions.ublock-origin;
|
|
||||||
enable = lib.mkDefault true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
})
|
|
||||||
({
|
|
||||||
sane.programs.firefox = {
|
|
||||||
inherit package;
|
|
||||||
|
|
||||||
mime.associations = let
|
|
||||||
inherit (cfg.browser) desktop;
|
|
||||||
in {
|
|
||||||
"text/html" = desktop;
|
|
||||||
"x-scheme-handler/http" = desktop;
|
|
||||||
"x-scheme-handler/https" = desktop;
|
|
||||||
"x-scheme-handler/about" = desktop;
|
|
||||||
"x-scheme-handler/unknown" = desktop;
|
|
||||||
};
|
|
||||||
|
|
||||||
# env.BROWSER = "${package}/bin/${cfg.browser.libName}";
|
|
||||||
env.BROWSER = cfg.browser.libName; # used by misc tools like xdg-email, as fallback
|
|
||||||
|
|
||||||
# uBlock filter list configuration.
|
|
||||||
# specifically, enable the GDPR cookie prompt blocker.
|
|
||||||
# data.toOverwrite.filterLists is additive (i.e. it supplements the default filters)
|
|
||||||
# this configuration method is documented here:
|
|
||||||
# - <https://github.com/gorhill/uBlock/issues/2986#issuecomment-364035002>
|
|
||||||
# the specific attribute path is found via scraping ublock code here:
|
|
||||||
# - <https://github.com/gorhill/uBlock/blob/master/src/js/storage.js>
|
|
||||||
# - <https://github.com/gorhill/uBlock/blob/master/assets/assets.json>
|
|
||||||
fs."${cfg.browser.dotDir}/managed-storage/uBlock0@raymondhill.net.json".symlink.text = ''
|
|
||||||
{
|
|
||||||
"name": "uBlock0@raymondhill.net",
|
|
||||||
"description": "ignored",
|
|
||||||
"type": "storage",
|
|
||||||
"data": {
|
|
||||||
"toOverwrite": "{\"filterLists\": [\"fanboy-cookiemonster\"]}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
# TODO: this is better suited in `extraPrefs` during `wrapFirefox` call
|
|
||||||
fs."${cfg.browser.dotDir}/${cfg.browser.libName}.overrides.cfg".symlink.text = ''
|
|
||||||
// if we can't query the revocation status of a SSL cert because the issuer is offline,
|
|
||||||
// treat it as unrevoked.
|
|
||||||
// see: <https://librewolf.net/docs/faq/#im-getting-sec_error_ocsp_server_error-what-can-i-do>
|
|
||||||
defaultPref("security.OCSP.require", false);
|
|
||||||
'';
|
|
||||||
fs."${cfg.browser.dotDir}/default".dir = {};
|
|
||||||
# instruct Firefox to put the profile in a predictable directory (so we can do things like persist just it).
|
|
||||||
# XXX: the directory *must* exist, even if empty; Firefox will not create the directory itself.
|
|
||||||
fs."${cfg.browser.dotDir}/profiles.ini".symlink.text = ''
|
|
||||||
[Profile0]
|
|
||||||
Name=default
|
|
||||||
IsRelative=1
|
|
||||||
Path=default
|
|
||||||
Default=1
|
|
||||||
|
|
||||||
[General]
|
|
||||||
StartWithLastProfile=1
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
})
|
|
||||||
(mkIf config.sane.programs.firefox.enabled {
|
|
||||||
# TODO: move the persistence into the sane.programs API (above)
|
|
||||||
# flush the cache to disk to avoid it taking up too much tmp.
|
|
||||||
sane.user.persist.byPath."${cfg.browser.cacheDir}".store =
|
|
||||||
if (cfg.persistData != null) then
|
|
||||||
cfg.persistData
|
|
||||||
else
|
|
||||||
"cryptClearOnBoot"
|
|
||||||
;
|
|
||||||
|
|
||||||
sane.user.persist.byPath."${cfg.browser.dotDir}/default".store =
|
|
||||||
if (cfg.persistData != null) then
|
|
||||||
cfg.persistData
|
|
||||||
else
|
|
||||||
"cryptClearOnBoot"
|
|
||||||
;
|
|
||||||
})
|
|
||||||
];
|
|
||||||
}
|
|
@@ -1,15 +0,0 @@
|
|||||||
{ config, lib, pkgs, ... }:
|
|
||||||
{
|
|
||||||
fonts = lib.mkIf config.sane.programs.fontconfig.enabled {
|
|
||||||
fontconfig.enable = true;
|
|
||||||
fontconfig.defaultFonts = {
|
|
||||||
emoji = [ "Font Awesome 6 Free" "Noto Color Emoji" ];
|
|
||||||
monospace = [ "Hack" ];
|
|
||||||
serif = [ "DejaVu Serif" ];
|
|
||||||
sansSerif = [ "DejaVu Sans" ];
|
|
||||||
};
|
|
||||||
#vvv enables dejavu_fonts, freefont_ttf, gyre-fonts, liberation_ttf, unifont, noto-fonts-emoji
|
|
||||||
enableDefaultPackages = true;
|
|
||||||
packages = with pkgs; [ font-awesome noto-fonts-emoji hack-font ];
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,12 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
{
|
|
||||||
sane.programs.fractal = {
|
|
||||||
# package = pkgs.fractal-latest;
|
|
||||||
package = pkgs.fractal-next;
|
|
||||||
|
|
||||||
# XXX by default fractal stores its state in ~/.local/share/stable/<UUID>.
|
|
||||||
persist.private = [ ".local/share/stable" ];
|
|
||||||
|
|
||||||
suggestedPrograms = [ "gnome-keyring" ];
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,7 +0,0 @@
|
|||||||
{ config, lib, ... }:
|
|
||||||
{
|
|
||||||
services.fwupd = lib.mkIf config.sane.programs.fwupd.enabled {
|
|
||||||
# enables the dbus service, which i think the frontend speaks to.
|
|
||||||
enable = true;
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,41 +0,0 @@
|
|||||||
{ lib, pkgs, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
# TODO: use formats.gitIni or lib.generators.toGitINI
|
|
||||||
# - see: <repo:nixos/nixpkgs:pkgs/pkgs-lib/formats.nix>
|
|
||||||
mkCfg = lib.generators.toINI { };
|
|
||||||
in
|
|
||||||
{
|
|
||||||
sane.programs.git.fs.".config/git/config".symlink.text = mkCfg {
|
|
||||||
# top-level options documented:
|
|
||||||
# - <https://git-scm.com/docs/git-config#_variables>
|
|
||||||
|
|
||||||
user.name = "Colin";
|
|
||||||
user.email = "colin@uninsane.org";
|
|
||||||
|
|
||||||
alias.br = "branch";
|
|
||||||
alias.co = "checkout";
|
|
||||||
alias.cp = "cherry-pick";
|
|
||||||
alias.d = "difftool";
|
|
||||||
alias.dif = "diff"; # common typo
|
|
||||||
alias.difsum = "diff --compact-summary"; #< show only the list of files which changed, not contents
|
|
||||||
alias.rb = "rebase";
|
|
||||||
alias.st = "status";
|
|
||||||
alias.stat = "status";
|
|
||||||
|
|
||||||
# difftastic docs:
|
|
||||||
# - <https://difftastic.wilfred.me.uk/git.html>
|
|
||||||
diff.tool = "difftastic";
|
|
||||||
difftool.prompt = false;
|
|
||||||
"difftool \"difftastic\"".cmd = ''${pkgs.difftastic}/bin/difft "$LOCAL" "$REMOTE"'';
|
|
||||||
# now run `git difftool` to use difftastic git
|
|
||||||
|
|
||||||
# render dates as YYYY-MM-DD HH:MM:SS +TZ
|
|
||||||
log.date = "iso";
|
|
||||||
|
|
||||||
sendemail.annotate = "yes";
|
|
||||||
sendemail.confirm = "always";
|
|
||||||
|
|
||||||
stash.showPatch = true;
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,40 +0,0 @@
|
|||||||
# gnome feeds RSS viewer
|
|
||||||
{ config, lib, sane-lib, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
feeds = sane-lib.feeds;
|
|
||||||
all-feeds = config.sane.feeds;
|
|
||||||
wanted-feeds = feeds.filterByFormat ["text" "image"] all-feeds;
|
|
||||||
in {
|
|
||||||
sane.programs.gnome-feeds.fs.".config/org.gabmus.gfeeds.json".symlink.text = builtins.toJSON {
|
|
||||||
# feed format is a map from URL to a dict,
|
|
||||||
# with dict["tags"] a list of string tags.
|
|
||||||
feeds = sane-lib.mapToAttrs (feed: {
|
|
||||||
name = feed.url;
|
|
||||||
value.tags = [ feed.cat feed.freq ];
|
|
||||||
}) wanted-feeds;
|
|
||||||
dark_reader = false;
|
|
||||||
new_first = true;
|
|
||||||
# windowsize = {
|
|
||||||
# width = 350;
|
|
||||||
# height = 650;
|
|
||||||
# };
|
|
||||||
max_article_age_days = 90;
|
|
||||||
enable_js = false;
|
|
||||||
max_refresh_threads = 3;
|
|
||||||
# saved_items = {};
|
|
||||||
# read_items = [];
|
|
||||||
show_read_items = true;
|
|
||||||
full_article_title = true;
|
|
||||||
# views: "webview", "reader", "rsscont"
|
|
||||||
default_view = "rsscont";
|
|
||||||
open_links_externally = true;
|
|
||||||
full_feed_name = false;
|
|
||||||
refresh_on_startup = true;
|
|
||||||
tags = lib.unique (
|
|
||||||
(builtins.catAttrs "cat" wanted-feeds) ++ (builtins.catAttrs "freq" wanted-feeds)
|
|
||||||
);
|
|
||||||
open_youtube_externally = false;
|
|
||||||
media_player = "vlc"; # default: mpv
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,10 +0,0 @@
|
|||||||
{ config, lib, pkgs, ... }:
|
|
||||||
{
|
|
||||||
sane.programs.gnome-keyring = {
|
|
||||||
package = pkgs.gnome.gnome-keyring;
|
|
||||||
};
|
|
||||||
# adds gnome-keyring as a xdg-data-portal (xdg.portal)
|
|
||||||
services.gnome.gnome-keyring = lib.mkIf config.sane.programs.gnome-keyring.enabled {
|
|
||||||
enable = true;
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,18 +0,0 @@
|
|||||||
# gnome feeds RSS viewer
|
|
||||||
{ config, pkgs, sane-lib, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
feeds = sane-lib.feeds;
|
|
||||||
all-feeds = config.sane.feeds;
|
|
||||||
wanted-feeds = feeds.filterByFormat ["podcast"] all-feeds;
|
|
||||||
in {
|
|
||||||
sane.programs.gpodder = {
|
|
||||||
package = pkgs.gpodder-adaptive-configured;
|
|
||||||
# package = pkgs.gpodder-configured;
|
|
||||||
fs.".config/gpodderFeeds.opml".symlink.text = feeds.feedsToOpml wanted-feeds;
|
|
||||||
|
|
||||||
# XXX: we preserve the whole thing because if we only preserve gPodder/Downloads
|
|
||||||
# then startup is SLOW during feed import, and we might end up with zombie eps in the dl dir.
|
|
||||||
persist.plaintext = [ "gPodder" ];
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,13 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
{
|
|
||||||
sane.programs.gthumb = {
|
|
||||||
# compile without webservices to avoid the expensive webkitgtk dependency
|
|
||||||
package = pkgs.gthumb.override { withWebservices = false; };
|
|
||||||
mime.associations = {
|
|
||||||
"image/heif" = "org.gnome.gThumb.desktop"; # apple codec
|
|
||||||
"image/png" = "org.gnome.gThumb.desktop";
|
|
||||||
"image/jpeg" = "org.gnome.gThumb.desktop";
|
|
||||||
"image/svg+xml" = "org.gnome.gThumb.desktop";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,22 +0,0 @@
|
|||||||
# Helix text editor
|
|
||||||
# debug log: `~/.cache/helix/helix.log`
|
|
||||||
# binary name is `hx`
|
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
sane.programs.helix = {
|
|
||||||
# grammars need to be persisted when developing them
|
|
||||||
# - `hx --grammar fetch` and `hx --grammar build`
|
|
||||||
# but otherwise, they ship as part of HELIX_RUNTIME, in the nix store
|
|
||||||
# persist.plaintext = [ ".config/helix/runtime/grammars" ];
|
|
||||||
fs.".config/helix/config.toml".symlink.text = ''
|
|
||||||
# docs: <https://docs.helix-editor.com/configuration.html>
|
|
||||||
[editor.soft-wrap]
|
|
||||||
enable = true
|
|
||||||
|
|
||||||
[editor.whitespace.render]
|
|
||||||
space = "all"
|
|
||||||
tab = "all"
|
|
||||||
newline = "none"
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,9 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
{
|
|
||||||
sane.programs.imagemagick = {
|
|
||||||
package = pkgs.imagemagick.override {
|
|
||||||
ghostscriptSupport = true;
|
|
||||||
};
|
|
||||||
suggestedPrograms = [ "ghostscript" ];
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,15 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
sane.programs.jellyfin-media-player = {
|
|
||||||
# package = pkgs.jellyfin-media-player;
|
|
||||||
# qt6 version is slightly buggy, but also most qtwebengine apps (e.g. zeal) are on qt5
|
|
||||||
# so using qt6 would force yet *another* qtwebengine compile.
|
|
||||||
# package = pkgs.jellyfin-media-player-qt6;
|
|
||||||
|
|
||||||
# jellyfin stores things in a bunch of directories: this one persists auth info.
|
|
||||||
# it *might* be possible to populate this externally (it's Qt stuff), but likely to
|
|
||||||
# be fragile and take an hour+ to figure out.
|
|
||||||
persist.plaintext = [ ".local/share/Jellyfin Media Player" ];
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,47 +0,0 @@
|
|||||||
# vim:ft=kitty
|
|
||||||
|
|
||||||
## name: PaperColor Dark
|
|
||||||
## author: Nikyle Nguyen
|
|
||||||
## license: MIT
|
|
||||||
## blurb: Dark color scheme inspired by Google's Material Design
|
|
||||||
|
|
||||||
# special
|
|
||||||
foreground #d0d0d0
|
|
||||||
background #1c1c1c
|
|
||||||
cursor #d0d0d0
|
|
||||||
cursor_text_color background
|
|
||||||
|
|
||||||
# black
|
|
||||||
color0 #1c1c1c
|
|
||||||
color8 #585858
|
|
||||||
|
|
||||||
# red
|
|
||||||
color1 #af005f
|
|
||||||
color9 #5faf5f
|
|
||||||
|
|
||||||
# green
|
|
||||||
# "color2" is the green color used by ls to indicate executability
|
|
||||||
# both as text color
|
|
||||||
# or as bg color when the text is blue (color4)
|
|
||||||
color2 #246a28
|
|
||||||
color10 #2df200
|
|
||||||
|
|
||||||
# yellow
|
|
||||||
color3 #d7af5f
|
|
||||||
color11 #af87d7
|
|
||||||
|
|
||||||
# blue
|
|
||||||
color4 #78c6ef
|
|
||||||
color12 #ffaf00
|
|
||||||
|
|
||||||
# magenta
|
|
||||||
color5 #808080
|
|
||||||
color13 #ff5faf
|
|
||||||
|
|
||||||
# cyan
|
|
||||||
color6 #d7875f
|
|
||||||
color14 #00afaf
|
|
||||||
|
|
||||||
# white
|
|
||||||
color7 #d0d0d0
|
|
||||||
color15 #5f8787
|
|
@@ -1,73 +0,0 @@
|
|||||||
{ lib, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
sane.programs.kitty = {
|
|
||||||
fs.".config/kitty/kitty.conf".symlink.text = ''
|
|
||||||
# docs: https://sw.kovidgoyal.net/kitty/conf/
|
|
||||||
# disable terminal bell (when e.g. you backspace too many times)
|
|
||||||
enable_audio_bell no
|
|
||||||
|
|
||||||
map ctrl+n new_os_window_with_cwd
|
|
||||||
include ${./PaperColor_dark.conf}
|
|
||||||
'';
|
|
||||||
env.TERMINAL = lib.mkDefault "kitty";
|
|
||||||
};
|
|
||||||
|
|
||||||
# include ${pkgs.kitty-themes}/themes/PaperColor_dark.conf
|
|
||||||
|
|
||||||
# THEME CHOICES:
|
|
||||||
# docs: https://github.com/kovidgoyal/kitty-themes
|
|
||||||
# theme = "1984 Light"; # dislike: awful, harsh blues/teals
|
|
||||||
# theme = "Adventure Time"; # dislike: harsh (dark)
|
|
||||||
# theme = "Atom One Light"; # GOOD: light theme. all color combos readable. not a huge fan of the blue.
|
|
||||||
# theme = "Belafonte Day"; # dislike: too low contrast for text colors
|
|
||||||
# theme = "Belafonte Night"; # better: dark theme that's easy on the eyes. all combos readable. low contrast.
|
|
||||||
# theme = "Catppuccin"; # dislike: a bit pale/low-contrast (dark)
|
|
||||||
# theme = "Desert"; # mediocre: colors are harsh
|
|
||||||
# theme = "Earthsong"; # BEST: dark theme. readable, good contrast. unique, but decent colors.
|
|
||||||
# theme = "Espresso Libre"; # better: dark theme. readable, but meh colors
|
|
||||||
# theme = "Forest Night"; # decent: very pastel. it's workable, but unconventional and muted/flat.
|
|
||||||
# theme = "Gruvbox Material Light Hard"; # mediocre light theme.
|
|
||||||
# theme = "kanagawabones"; # better: dark theme. colors are too background-y
|
|
||||||
# theme = "Kaolin Dark"; # dislike: too dark
|
|
||||||
# theme = "Kaolin Breeze"; # mediocre: not-too-harsh light theme, but some parts are poor contrast
|
|
||||||
# theme = "Later This Evening"; # mediocre: not-too-harsh dark theme, but cursor is poor contrast
|
|
||||||
# theme = "Material"; # decent: light theme, few colors.
|
|
||||||
# theme = "Mayukai"; # decent: not-too-harsh dark theme. the teal is a bit straining
|
|
||||||
# theme = "Nord"; # mediocre: pale background, low contrast
|
|
||||||
# theme = "One Half Light"; # better: not-too-harsh light theme. contrast could be better
|
|
||||||
# theme = "PaperColor Dark"; # BEST: dark theme, very readable still the colors are background-y
|
|
||||||
# theme = "Parasio Dark"; # dislike: too low contrast
|
|
||||||
# theme = "Pencil Light"; # better: not-too-harsh light theme. decent contrast.
|
|
||||||
# theme = "Pnevma"; # dislike: too low contrast
|
|
||||||
# theme = "Piatto Light"; # better: readable light theme. pleasing colors. powerline prompt is hard to read.
|
|
||||||
# theme = "Rosé Pine Dawn"; # GOOD: light theme. all color combinations are readable. it is very mild -- may need to manually tweak contrast. tasteful colors
|
|
||||||
# theme = "Rosé Pine Moon"; # GOOD: dark theme. tasteful colors. but background is a bit intense
|
|
||||||
# theme = "Sea Shells"; # mediocre. not all color combos are readable
|
|
||||||
# theme = "Solarized Light"; # mediocre: not-too-harsh light theme; GREAT background; but some colors are low contrast
|
|
||||||
# theme = "Solarized Dark Higher Contrast"; # better: dark theme, decent colors
|
|
||||||
# theme = "Sourcerer"; # mediocre: ugly colors
|
|
||||||
# theme = "Space Gray"; # mediocre: too muted
|
|
||||||
# theme = "Space Gray Eighties"; # better: all readable, decent colors
|
|
||||||
# theme = "Spacemacs"; # mediocre: too muted
|
|
||||||
# theme = "Spring"; # mediocre: readable light theme, but the teal is ugly.
|
|
||||||
# theme = "Srcery"; # better: highly readable. colors are ehhh
|
|
||||||
# theme = "Substrata"; # decent: nice colors, but a bit flat.
|
|
||||||
# theme = "Sundried"; # mediocre: the solar text makes me squint
|
|
||||||
# theme = "Symfonic"; # mediocre: the dark purple has low contrast to the black bg.
|
|
||||||
# theme = "Tango Light"; # dislike: teal is too grating
|
|
||||||
# theme = "Tokyo Night Day"; # medicore: too muted
|
|
||||||
# theme = "Tokyo Night"; # better: tasteful. a bit flat
|
|
||||||
# theme = "Tomorrow"; # GOOD: all color combinations are readable. contrast is slightly better than Rose. on the blander side
|
|
||||||
# theme = "Treehouse"; # dislike: the orange is harsh on my eyes.
|
|
||||||
# theme = "Urple"; # dislike: weird palette
|
|
||||||
# theme = "Warm Neon"; # decent: not-too-harsh dark theme. the green is a bit unattractive
|
|
||||||
# theme = "Wild Cherry"; # GOOD: dark theme: nice colors. a bit flat
|
|
||||||
# theme = "Xcodedark"; # dislike: bad palette
|
|
||||||
# theme = "citylights"; # decent: dark theme. some parts have just a bit low contrast
|
|
||||||
# theme = "neobones_light"; # better light theme. the background is maybe too muted
|
|
||||||
# theme = "vimbones";
|
|
||||||
# theme = "zenbones_dark"; # mediocre: readable, but meh colors
|
|
||||||
# theme = "zenbones_light"; # decent: light theme. all colors are readable. contrast is passable but not excellent. highlight color is BAD
|
|
||||||
# theme = "zenwritten_dark"; # mediocre: looks same as zenbones_dark
|
|
||||||
}
|
|
@@ -1,8 +0,0 @@
|
|||||||
{ ... }:
|
|
||||||
{
|
|
||||||
sane.programs.komikku = {
|
|
||||||
secrets.".local/share/komikku/keyrings/plaintext.keyring" = ../../../secrets/common/komikku_accounts.json.bin;
|
|
||||||
# downloads end up here, and without the toplevel database komikku doesn't know they exist.
|
|
||||||
persist.plaintext = [ ".local/share/komikku" ];
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,42 +0,0 @@
|
|||||||
-- as of 2023.05.1, koreader FTP browser always fails to load.
|
|
||||||
-- it's convinced that it's offline, and asks to connect to wifi.
|
|
||||||
-- this seems to be because of the following in <frontend/device/sdl/device.lua>:
|
|
||||||
--
|
|
||||||
-- function Device:initNetworkManager(NetworkMgr)
|
|
||||||
-- function NetworkMgr:isWifiOn() return true end
|
|
||||||
-- function NetworkMgr:isConnected()
|
|
||||||
-- -- Pull the default gateway first, so we don't even try to ping anything if there isn't one...
|
|
||||||
-- local default_gw = Device:getDefaultRoute()
|
|
||||||
-- if not default_gw then
|
|
||||||
-- return false
|
|
||||||
-- end
|
|
||||||
-- return 0 == os.execute("ping -c1 -w2 " .. default_gw .. " > /dev/null")
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
--
|
|
||||||
-- specifically, `os.execute` is not *expected* to return 0. it returns `true` on success:
|
|
||||||
-- <https://www.lua.org/manual/5.3/manual.html#pdf-os.execute>
|
|
||||||
-- this apparently changed from 5.1 -> 5.2
|
|
||||||
--
|
|
||||||
-- XXX: this same bug likely applies to `isCommand` and `runCommand` in <frontend/device/sdl/device.lua>
|
|
||||||
-- - that would manifest as wikipedia links failing to open in external application (xdg-open)
|
|
||||||
|
|
||||||
local logger = require("logger")
|
|
||||||
logger.info("applying colin patch")
|
|
||||||
|
|
||||||
local Device = require("device")
|
|
||||||
logger.info("Device:" .. tostring(Device))
|
|
||||||
|
|
||||||
local orig_initNetworkManager = Device.initNetworkManager
|
|
||||||
Device.initNetworkManager = function(self, NetworkMgr)
|
|
||||||
logger.info("Device:initNetworkManager")
|
|
||||||
orig_initNetworkManager(self, NetworkMgr)
|
|
||||||
function NetworkMgr:isConnected()
|
|
||||||
logger.info("mocked `NetworkMgr:isConnected` to return true")
|
|
||||||
return true
|
|
||||||
-- unpatch to show that the boolean form works
|
|
||||||
-- local rc = os.execute("ping -c1 -w2 10.78.79.1 > /dev/null")
|
|
||||||
-- logger.info("ping rc: " .. tostring(rc))
|
|
||||||
-- return rc
|
|
||||||
end
|
|
||||||
end
|
|
@@ -1,48 +0,0 @@
|
|||||||
{ config, lib, pkgs, sane-lib, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
feeds = sane-lib.feeds;
|
|
||||||
allFeeds = config.sane.feeds;
|
|
||||||
wantedFeeds = feeds.filterByFormat [ "image" "text" ] allFeeds;
|
|
||||||
koreaderRssEntries = builtins.map (feed:
|
|
||||||
# format:
|
|
||||||
# { "<rss/atom url>", limit = <int>, download_full_article=<bool>, include_images=<bool>, enable_filter=<bool>, filter_element = "<css selector>"},
|
|
||||||
# limit = 0 => download and keep *all* articles
|
|
||||||
# download_full_article = true => populate feed by downloading the webpage -- not just what's encoded in the RSS <article> tags
|
|
||||||
# - use this for articles where the RSS only encodes content previews
|
|
||||||
# - in practice, most articles don't work with download_full_article = false
|
|
||||||
# enable_filter = true => only render content that matches the filter_element css selector.
|
|
||||||
let fields = [
|
|
||||||
(lib.escapeShellArg feed.url)
|
|
||||||
"limit = 5"
|
|
||||||
"download_full_article = true"
|
|
||||||
"include_images = true"
|
|
||||||
"enable_filter = false"
|
|
||||||
"filter_element = \"\""
|
|
||||||
]; in "{ ${lib.concatStringsSep ", " fields } }"
|
|
||||||
) wantedFeeds;
|
|
||||||
in {
|
|
||||||
sane.programs.koreader = {
|
|
||||||
package = pkgs.koreader-from-src;
|
|
||||||
# koreader applies these lua "patches" at boot:
|
|
||||||
# - <https://github.com/koreader/koreader/wiki/User-patches>
|
|
||||||
# - TODO: upstream this patch to koreader
|
|
||||||
# fs.".config/koreader/patches".symlink.target = "${./.}";
|
|
||||||
fs.".config/koreader/patches/2-colin-NetworkManager-isConnected.lua".symlink.target = "${./2-colin-NetworkManager-isConnected.lua}";
|
|
||||||
|
|
||||||
# koreader news plugin, enabled by default. file format described here:
|
|
||||||
# - <repo:koreader/koreader:plugins/newsdownloader.koplugin/feed_config.lua>
|
|
||||||
fs.".config/koreader/news/feed_config.lua".symlink.text = ''
|
|
||||||
return {--do NOT change this line
|
|
||||||
${lib.concatStringsSep ",\n " koreaderRssEntries}
|
|
||||||
}--do NOT change this line
|
|
||||||
'';
|
|
||||||
|
|
||||||
# koreader on aarch64 errors if there's no fonts directory (sandboxing thing, i guess)
|
|
||||||
fs.".local/share/fonts".dir = {};
|
|
||||||
|
|
||||||
# history, cache, dictionaries...
|
|
||||||
# could be more explicit if i symlinked the history.lua file to somewhere it can persist better.
|
|
||||||
persist.plaintext = [ ".config/koreader" ];
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,7 +0,0 @@
|
|||||||
{ ... }:
|
|
||||||
{
|
|
||||||
sane.programs.lemoa = {
|
|
||||||
# creds
|
|
||||||
persist.private = [ ".local/share/io.github.lemmygtk.lemoa" ];
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,20 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
sane.programs.libreoffice = {
|
|
||||||
# package = pkgs.libreoffice-bin;
|
|
||||||
# package = pkgs.libreoffice-still;
|
|
||||||
package = pkgs.libreoffice-fresh;
|
|
||||||
|
|
||||||
# disable first-run stuff
|
|
||||||
fs.".config/libreoffice/4/user/registrymodifications.xcu".symlink.text = ''
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<oor:items xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
|
||||||
<item oor:path="/org.openoffice.Office.Common/Misc"><prop oor:name="FirstRun" oor:op="fuse"><value>false</value></prop></item>
|
|
||||||
<item oor:path="/org.openoffice.Office.Common/Misc"><prop oor:name="ShowTipOfTheDay" oor:op="fuse"><value>false</value></prop></item>
|
|
||||||
</oor:items>
|
|
||||||
'';
|
|
||||||
# <item oor:path="/org.openoffice.Setup/Product"><prop oor:name="LastTimeDonateShown" oor:op="fuse"><value>1667693880</value></prop></item>
|
|
||||||
# <item oor:path="/org.openoffice.Setup/Product"><prop oor:name="LastTimeGetInvolvedShown" oor:op="fuse"><value>1667693880</value></prop></item>
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,11 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
{
|
|
||||||
sane.programs.megapixels.package = pkgs.megapixels.override {
|
|
||||||
# megapixels uses zbar to read barcodes.
|
|
||||||
# zbar by default ships zbarcam-gtk and zbarcam-qt, neither of which megapixels needs.
|
|
||||||
# but the latter takes a dep on qt, which bloats the closure and the build, so disable this feature.
|
|
||||||
zbar = pkgs.zbar.override {
|
|
||||||
enableVideo = false;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,26 +0,0 @@
|
|||||||
# docs: <https://git.sr.ht/~mil/mepo>
|
|
||||||
# irc #mepo:irc.oftc.net
|
|
||||||
{ config, lib, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
sane.programs.mepo = {
|
|
||||||
persist.plaintext = [ ".cache/mepo/tiles" ];
|
|
||||||
# ~/.cache/mepo/savestate has precise coordinates and pins: keep those private
|
|
||||||
persist.private = [
|
|
||||||
{ type = "file"; path = ".cache/mepo/savestate"; }
|
|
||||||
];
|
|
||||||
|
|
||||||
# give mepo access to gpsd for location data, if that's enabled.
|
|
||||||
# same with geoclue2.
|
|
||||||
suggestedPrograms = lib.optional config.services.gpsd.enable "gpsd"
|
|
||||||
++ lib.optional config.services.geoclue2.enable "geoclue2-with-demo-agent"
|
|
||||||
;
|
|
||||||
};
|
|
||||||
|
|
||||||
# programs.mepo = lib.mkIf config.sane.programs.mepo.enabled {
|
|
||||||
# # enable location services (via geoclue)
|
|
||||||
# enable = true;
|
|
||||||
# # more precise, via gpsd ("may require additional config")
|
|
||||||
# # programs.mepo.gpsd.enable = true
|
|
||||||
# };
|
|
||||||
}
|
|
@@ -1,82 +0,0 @@
|
|||||||
# mpv docs:
|
|
||||||
# - <https://mpv.io/manual/master>
|
|
||||||
# - <https://github.com/mpv-player/mpv/wiki>
|
|
||||||
# curated mpv mods/scripts/users:
|
|
||||||
# - <https://github.com/stax76/awesome-mpv>
|
|
||||||
{ pkgs, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
sane.programs.mpv = {
|
|
||||||
package = pkgs.wrapMpv pkgs.mpv-unwrapped {
|
|
||||||
youtubeSupport = false; #< XXX(2023/08/03): doesn't cross compile until next staging -> master merge
|
|
||||||
scripts = with pkgs.mpvScripts; [
|
|
||||||
mpris
|
|
||||||
# uosc
|
|
||||||
pkgs.mpv-uosc-latest
|
|
||||||
];
|
|
||||||
};
|
|
||||||
persist.plaintext = [ ".config/mpv/watch_later" ];
|
|
||||||
fs.".config/mpv/input.conf".symlink.text = ''
|
|
||||||
# let volume keys be interpreted by the system.
|
|
||||||
# this is important for sxmo.
|
|
||||||
VOLUME_UP ignore
|
|
||||||
VOLUME_DOWN ignore
|
|
||||||
'';
|
|
||||||
fs.".config/mpv/mpv.conf".symlink.text = ''
|
|
||||||
save-position-on-quit=yes
|
|
||||||
keep-open=yes
|
|
||||||
|
|
||||||
# use uosc instead (for On Screen Controls)
|
|
||||||
osc=no
|
|
||||||
# uosc provides its own seeking/volume indicators, so you also don't need this
|
|
||||||
osd-bar=no
|
|
||||||
# uosc will draw its own window controls if you disable window border
|
|
||||||
border=no
|
|
||||||
'';
|
|
||||||
fs.".config/mpv/script-opts/osc.conf".symlink.text = ''
|
|
||||||
# make the on-screen controls *always* visible
|
|
||||||
# unfortunately, this applies to full-screen as well
|
|
||||||
# - docs: <https://mpv.io/manual/master/#on-screen-controller-visibility>
|
|
||||||
# if uosc is installed, this file is unused
|
|
||||||
visibility=always
|
|
||||||
'';
|
|
||||||
fs.".config/mpv/script-opts/uosc.conf".symlink.text = let
|
|
||||||
play_pause_btn = "cycle:play_arrow:pause:no=pause/yes=play_arrow";
|
|
||||||
rev_btn = "command:replay_10:seek -10";
|
|
||||||
fwd_btn = "command:forward_30:seek 30";
|
|
||||||
in ''
|
|
||||||
# docs:
|
|
||||||
# - <https://github.com/tomasklaen/uosc>
|
|
||||||
# - <https://superuser.com/questions/1775550/add-new-buttons-to-mpv-uosc-ui>
|
|
||||||
timeline_style=bar
|
|
||||||
timeline_persistency=paused,audio
|
|
||||||
controls_persistency=paused,audio
|
|
||||||
volume_persistency=audio
|
|
||||||
volume_opacity=0.75
|
|
||||||
|
|
||||||
# speed_persistency=paused,audio
|
|
||||||
# vvv want a close button?
|
|
||||||
top_bar=always
|
|
||||||
top_bar_persistency=paused
|
|
||||||
|
|
||||||
controls=menu,<video>subtitles,<has_many_audio>audio,<has_many_video>video,<has_many_edition>editions,<stream>stream-quality,space,${rev_btn},${play_pause_btn},${fwd_btn},space,speed:1.0,gap,<video>fullscreen
|
|
||||||
|
|
||||||
text_border=6.0
|
|
||||||
font_bold=yes
|
|
||||||
background_text=ff8080
|
|
||||||
foreground=ff8080
|
|
||||||
|
|
||||||
ui_scale=1.0
|
|
||||||
'';
|
|
||||||
|
|
||||||
mime.priority = 200; # default = 100; 200 means to yield to other apps
|
|
||||||
mime.associations."audio/flac" = "mpv.desktop";
|
|
||||||
mime.associations."audio/mpeg" = "mpv.desktop";
|
|
||||||
mime.associations."audio/x-vorbis+ogg" = "mpv.desktop";
|
|
||||||
mime.associations."video/mp4" = "mpv.desktop";
|
|
||||||
mime.associations."video/quicktime" = "mpv.desktop";
|
|
||||||
mime.associations."video/webm" = "mpv.desktop";
|
|
||||||
mime.associations."video/x-matroska" = "mpv.desktop";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@@ -1,25 +0,0 @@
|
|||||||
# docs: <https://nixos.wiki/wiki/Msmtp>
|
|
||||||
# validate with e.g.
|
|
||||||
# - `echo -e "Content-Type: text/plain\r\nSubject: Test\r\n\r\nHello World" | sendmail test@uninsane.org`
|
|
||||||
{ config, lib, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
sane.programs.msmtp = {
|
|
||||||
secrets.".config/msmtp/password.txt" = ../../../secrets/common/msmtp_password.txt.bin;
|
|
||||||
};
|
|
||||||
|
|
||||||
programs.msmtp = lib.mkIf config.sane.programs.msmtp.enabled {
|
|
||||||
enable = true;
|
|
||||||
accounts = {
|
|
||||||
default = {
|
|
||||||
auth = true;
|
|
||||||
tls = true;
|
|
||||||
tls_starttls = false; # needed else sendmail hangs
|
|
||||||
from = "Colin <colin@uninsane.org>";
|
|
||||||
host = "mx.uninsane.org";
|
|
||||||
user = "colin";
|
|
||||||
passwordeval = "cat ~/.config/msmtp/password.txt";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,148 +0,0 @@
|
|||||||
{ config, lib, pkgs, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
inherit (builtins) map;
|
|
||||||
inherit (lib) concatMapStrings mkIf optionalString;
|
|
||||||
# this structure roughly mirrors home-manager's `programs.neovim.plugins` option
|
|
||||||
plugins = with pkgs.vimPlugins; [
|
|
||||||
{
|
|
||||||
# docs: fzf-vim (fuzzy finder): https://github.com/junegunn/fzf.vim
|
|
||||||
plugin = fzf-vim;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
# treesitter syntax highlighting: https://nixos.wiki/wiki/Tree_sitters
|
|
||||||
# docs: https://github.com/nvim-treesitter/nvim-treesitter
|
|
||||||
# config taken from: https://github.com/i077/system/blob/master/modules/home/neovim/default.nix
|
|
||||||
# this is required for tree-sitter to even highlight
|
|
||||||
plugin = nvim-treesitter.withPlugins (_: nvim-treesitter.allGrammars ++ [
|
|
||||||
# XXX: this is apparently not enough to enable syntax highlighting!
|
|
||||||
# nvim-treesitter ships its own queries which may be distinct from e.g. helix.
|
|
||||||
# the queries aren't included when i ship the grammar in this manner
|
|
||||||
pkgs.tree-sitter-nix-shell
|
|
||||||
]);
|
|
||||||
type = "lua";
|
|
||||||
config = ''
|
|
||||||
require'nvim-treesitter.configs'.setup {
|
|
||||||
highlight = {
|
|
||||||
enable = true,
|
|
||||||
-- disable treesitter on Rust so that we can use SyntaxRange
|
|
||||||
-- and leverage TeX rendering in rust projects
|
|
||||||
disable = { "rust", "tex", "latex" },
|
|
||||||
-- disable = { "tex", "latex" },
|
|
||||||
-- true to also use builtin vim syntax highlighting when treesitter fails
|
|
||||||
additional_vim_regex_highlighting = false
|
|
||||||
},
|
|
||||||
incremental_selection = {
|
|
||||||
enable = true,
|
|
||||||
keymaps = {
|
|
||||||
init_selection = "gnn",
|
|
||||||
node_incremental = "grn",
|
|
||||||
mcope_incremental = "grc",
|
|
||||||
node_decremental = "grm"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
indent = {
|
|
||||||
enable = true,
|
|
||||||
disable = {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vim.o.foldmethod = 'expr'
|
|
||||||
vim.o.foldexpr = 'nvim_treesitter#foldexpr()'
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
{
|
|
||||||
# docs: tex-conceal-vim: https://github.com/KeitaNakamura/tex-conceal.vim/
|
|
||||||
plugin = tex-conceal-vim;
|
|
||||||
type = "viml";
|
|
||||||
config = ''
|
|
||||||
" present prettier fractions
|
|
||||||
let g:tex_conceal_frac=1
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
{
|
|
||||||
# source: <https://github.com/LnL7/vim-nix>
|
|
||||||
# fixes auto-indent (incl tab size) when editing .nix files
|
|
||||||
plugin = vim-nix;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
# docs: surround-nvim: https://github.com/ur4ltz/surround.nvim/
|
|
||||||
# docs: vim-surround: https://github.com/tpope/vim-surround
|
|
||||||
plugin = vim-surround;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
plugin = vim-SyntaxRange;
|
|
||||||
type = "viml";
|
|
||||||
config = ''
|
|
||||||
" enable markdown-style codeblock highlighting for tex code
|
|
||||||
autocmd BufEnter * call SyntaxRange#Include('```tex', '```', 'tex', 'NonText')
|
|
||||||
" autocmd Syntax tex set conceallevel=2
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
];
|
|
||||||
plugin-packages = map (p: p.plugin) plugins;
|
|
||||||
plugin-config-viml = concatMapStrings (p: optionalString (p.type or "" == "viml") p.config) plugins;
|
|
||||||
plugin-config-lua = concatMapStrings (p: optionalString (p.type or "" == "lua") p.config) plugins;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
# private because there could be sensitive things in the swap
|
|
||||||
sane.programs.neovim = {
|
|
||||||
persist.private = [ ".cache/vim-swap" ];
|
|
||||||
env.EDITOR = "vim";
|
|
||||||
# git claims it should use EDITOR, but it doesn't!
|
|
||||||
env.GIT_EDITOR = "vim";
|
|
||||||
};
|
|
||||||
|
|
||||||
programs.neovim = mkIf config.sane.programs.neovim.enabled {
|
|
||||||
# neovim: https://github.com/neovim/neovim
|
|
||||||
enable = true;
|
|
||||||
viAlias = true;
|
|
||||||
vimAlias = true;
|
|
||||||
configure = {
|
|
||||||
packages.plugins = {
|
|
||||||
start = plugin-packages;
|
|
||||||
};
|
|
||||||
customRC = ''
|
|
||||||
" let the terminal handle mouse events, that way i get OS-level ctrl+shift+c/etc
|
|
||||||
" this used to be default, until <https://github.com/neovim/neovim/pull/19290>
|
|
||||||
set mouse=
|
|
||||||
|
|
||||||
" copy/paste to system clipboard
|
|
||||||
set clipboard=unnamedplus
|
|
||||||
|
|
||||||
" screw tabs; always expand them into spaces
|
|
||||||
set expandtab
|
|
||||||
|
|
||||||
" at least don't open files with sections folded by default
|
|
||||||
set nofoldenable
|
|
||||||
|
|
||||||
" allow text substitutions for certain glyphs.
|
|
||||||
" higher number = more aggressive substitution (0, 1, 2, 3)
|
|
||||||
" i only make use of this for tex, but it's unclear how to
|
|
||||||
" apply that *just* to tex and retain the SyntaxRange stuff.
|
|
||||||
set conceallevel=2
|
|
||||||
|
|
||||||
" horizontal rule under the active line
|
|
||||||
" set cursorline
|
|
||||||
|
|
||||||
" highlight trailing space & related syntax errors (doesn't seem to work??)
|
|
||||||
" let c_space_errors=1
|
|
||||||
" let python_space_errors=1
|
|
||||||
|
|
||||||
" enable highlighting of leading/trailing spaces,
|
|
||||||
" and especially tabs
|
|
||||||
" source: https://www.reddit.com/r/neovim/comments/chlmfk/highlight_trailing_whitespaces_in_neovim/
|
|
||||||
set list
|
|
||||||
set listchars=tab:▷\·,trail:·,extends:◣,precedes:◢,nbsp:○
|
|
||||||
|
|
||||||
""""" PLUGIN CONFIG (vim)
|
|
||||||
${plugin-config-viml}
|
|
||||||
|
|
||||||
""""" PLUGIN CONFIG (lua)
|
|
||||||
lua <<EOF
|
|
||||||
${plugin-config-lua}
|
|
||||||
EOF
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,9 +0,0 @@
|
|||||||
{ ... }:
|
|
||||||
{
|
|
||||||
# not strictly necessary, but allows caching articles; offline use, etc.
|
|
||||||
sane.programs.nheko.persist.private = [
|
|
||||||
".config/nheko" # config file (including client token)
|
|
||||||
".cache/nheko" # media cache
|
|
||||||
".local/share/nheko" # per-account state database
|
|
||||||
];
|
|
||||||
}
|
|
@@ -1,7 +0,0 @@
|
|||||||
{ config, lib, ... }:
|
|
||||||
{
|
|
||||||
# provides `nix-locate`, backed by the manually run `nix-index`
|
|
||||||
sane.programs.nix-index = {
|
|
||||||
persist.plaintext = [ ".cache/nix-index" ];
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,4 +0,0 @@
|
|||||||
{ ... }:
|
|
||||||
{
|
|
||||||
sane.programs.obsidian.mime.associations."text/markdown" = "obsidian.desktop";
|
|
||||||
}
|
|
@@ -1,12 +0,0 @@
|
|||||||
# mail archiving/synchronization tool.
|
|
||||||
#
|
|
||||||
# manually download all emails for an account with
|
|
||||||
# - `offlineimap -a <accountname>`
|
|
||||||
#
|
|
||||||
# view account names inside the secrets file, listed below.
|
|
||||||
{ ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
sane.programs.offlineimap.secrets.".config/offlineimap/config" = ../../../secrets/common/offlineimaprc.bin;
|
|
||||||
}
|
|
||||||
|
|
@@ -1,9 +0,0 @@
|
|||||||
{ ... }:
|
|
||||||
{
|
|
||||||
# .ignore file is read by ripgrep (rg), silver searcher (ag), maybe others.
|
|
||||||
# ignore translation files by default when searching, as they tend to have
|
|
||||||
# a LOT of duplicate text.
|
|
||||||
sane.programs.ripgrep.fs.".ignore".symlink.text = ''
|
|
||||||
po/
|
|
||||||
'';
|
|
||||||
}
|
|
@@ -1,28 +0,0 @@
|
|||||||
# simple RSS and Atom parser
|
|
||||||
# - <https://codemadness.org/sfeed-simple-feed-parser.html>
|
|
||||||
# - used by sxmo
|
|
||||||
# - man 5 sfeedrc
|
|
||||||
#
|
|
||||||
# call `sfeed_update` to query each feed and populate entries in ~/.sfeed/feeds
|
|
||||||
{ lib, config, sane-lib, ... }:
|
|
||||||
let
|
|
||||||
feeds = sane-lib.feeds;
|
|
||||||
allFeeds = config.sane.feeds;
|
|
||||||
wantedFeeds = feeds.filterByFormat ["text"] allFeeds;
|
|
||||||
sfeedEntries = builtins.map (feed:
|
|
||||||
# format:
|
|
||||||
# feed <name> <feedurl> [basesiteurl] [encoding]
|
|
||||||
lib.escapeShellArgs [ "feed" (if feed.title != null then feed.title else feed.url) feed.url ]
|
|
||||||
) wantedFeeds;
|
|
||||||
in {
|
|
||||||
sane.programs.sfeed = {
|
|
||||||
fs.".sfeed/sfeedrc".symlink.text = ''
|
|
||||||
feeds() {
|
|
||||||
${lib.concatStringsSep "\n " sfeedEntries}
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
|
|
||||||
# this is where the parsed feed items go
|
|
||||||
persist.plaintext = [ ".sfeed/feeds" ];
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,20 +0,0 @@
|
|||||||
# borrows from:
|
|
||||||
# - default config: <https://github.com/cspeterson/splatmoji/blob/master/splatmoji.config>
|
|
||||||
# - wayland: <https://github.com/cspeterson/splatmoji/issues/32#issuecomment-830862566>
|
|
||||||
{ pkgs, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
sane.programs.splatmoji = {
|
|
||||||
persist.plaintext = [ ".local/state/splatmoji" ];
|
|
||||||
fs.".config/splatmoji/splatmoji.config".symlink.text = ''
|
|
||||||
# XXX doesn't seem to understand ~ as shorthand for `$HOME`
|
|
||||||
history_file=/home/colin/.local/state/splatmoji/history
|
|
||||||
history_length=5
|
|
||||||
paste_command=${pkgs.wtype}/bin/wtype -M Ctrl -k v
|
|
||||||
# rofi_command=${pkgs.wofi}/bin/wofi --dmenu --insensitive --cache-file /dev/null
|
|
||||||
rofi_command=${pkgs.fuzzel}/bin/fuzzel -d -i -w 60
|
|
||||||
xdotool_command=${pkgs.wtype}/bin/wtype
|
|
||||||
xsel_command=${pkgs.findutils}/bin/xargs ${pkgs.wl-clipboard}/bin/wl-copy
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,16 +0,0 @@
|
|||||||
{ config, lib, ...}:
|
|
||||||
{
|
|
||||||
sane.programs.steam = {
|
|
||||||
persist.plaintext = [
|
|
||||||
".steam"
|
|
||||||
".local/share/Steam"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
# steam requires system-level config for e.g. firewall or controller support
|
|
||||||
programs.steam = lib.mkIf config.sane.programs.steam.enabled {
|
|
||||||
enable = true;
|
|
||||||
# not sure if needed: stole this whole snippet from the wiki
|
|
||||||
remotePlay.openFirewall = true; # Open ports in the firewall for Steam Remote Play
|
|
||||||
dedicatedServer.openFirewall = true; # Open ports in the firewall for Source Dedicated Server
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,14 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
sane.programs.sublime-music = {
|
|
||||||
package = pkgs.sublime-music-mobile;
|
|
||||||
# sublime music persists any downloaded albums here.
|
|
||||||
# it doesn't obey a conventional ~/Music/{Artist}/{Album}/{Track} notation, so no symlinking
|
|
||||||
# config (e.g. server connection details) is persisted in ~/.config/sublime-music/config.json
|
|
||||||
# possible to pass config as a CLI arg (sublime-music -c config.json)
|
|
||||||
persist.plaintext = [ ".local/share/sublime-music" ];
|
|
||||||
|
|
||||||
secrets.".config/sublime-music/config.json" = ../../../secrets/common/sublime_music_config.json.bin;
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,42 +0,0 @@
|
|||||||
# Tangram is a GTK/webkit browser
|
|
||||||
# it views each tab as a distinct application, persisted, and where the 'home' button action is specific to each tab.
|
|
||||||
# it supports ephemeral tabs, but UX is heavily geared to GCing those as early as possible.
|
|
||||||
|
|
||||||
{ pkgs, ... }:
|
|
||||||
let
|
|
||||||
dconfProfile = pkgs.writeTextFile {
|
|
||||||
name = "dconf-tangram-profile";
|
|
||||||
destination = "/etc/dconf/profile/tangram";
|
|
||||||
text = ''
|
|
||||||
user-db:tangram
|
|
||||||
system-db:site
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
sane.programs.tangram = {
|
|
||||||
# XXX(2023/07/08): running on moby without disabling the webkit sandbox fails, with:
|
|
||||||
# - `bwrap: Can't make symlink at /var/run: File exists`
|
|
||||||
# see epiphany.nix for more info
|
|
||||||
package = pkgs.tangram.overrideAttrs (upstream: {
|
|
||||||
preFixup = ''
|
|
||||||
gappsWrapperArgs+=(
|
|
||||||
--set WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS "1"
|
|
||||||
--set DCONF_PROFILE "${dconfProfile}/etc/dconf/profile/tangram"
|
|
||||||
);
|
|
||||||
'' + (upstream.preFixup or "");
|
|
||||||
});
|
|
||||||
|
|
||||||
persist.private = [
|
|
||||||
".cache/Tangram"
|
|
||||||
".local/share/Tangram"
|
|
||||||
# dconf achieves atomic writes via `mv`, so a symlink doesn't work
|
|
||||||
# moreover, i have to persist the *whole* directory:
|
|
||||||
# - `user-db:tangram/user` causes a schema failure
|
|
||||||
# - bind-mounting `~/private/.config/dconf/tangram` causes dconf to try a cross-fs `mv`, which fails
|
|
||||||
# - dconf provides no way to specify an alternate ~/.config/dconf dir, except by overriding XDG_CONFIG_HOME
|
|
||||||
# { type = "file"; path = ".config/dconf/tangram"; method = "bind"; }
|
|
||||||
".config/dconf"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,4 +0,0 @@
|
|||||||
{ ... }:
|
|
||||||
{
|
|
||||||
sane.programs.tuba.suggestedPrograms = [ "gnome-keyring" ];
|
|
||||||
}
|
|
@@ -1,37 +0,0 @@
|
|||||||
{ config, lib, sane-lib, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
feeds = sane-lib.feeds;
|
|
||||||
all-feeds = config.sane.feeds;
|
|
||||||
wanted-feeds = feeds.filterByFormat ["podcast"] all-feeds;
|
|
||||||
podcast-urls = lib.concatStringsSep "|" (
|
|
||||||
builtins.map (feed: feed.url) wanted-feeds
|
|
||||||
);
|
|
||||||
in
|
|
||||||
{
|
|
||||||
sane.programs.vlc = {
|
|
||||||
persist.private = [
|
|
||||||
# vlc remembers play position in ~/.config/vlc/vlc-qt-interface.conf
|
|
||||||
# filenames are stored in plaintext (unlike mpv, which i think hashes them)
|
|
||||||
".config/vlc"
|
|
||||||
# vlc caches artwork. i'm not sure where it gets the artwork (internet? embedded metadata?)
|
|
||||||
".cache/vlc"
|
|
||||||
];
|
|
||||||
fs.".config/vlc/vlcrc".symlink.text = ''
|
|
||||||
[podcast]
|
|
||||||
podcast-urls=${podcast-urls}
|
|
||||||
[core]
|
|
||||||
metadata-network-access=0
|
|
||||||
[qt]
|
|
||||||
qt-privacy-ask=0
|
|
||||||
'';
|
|
||||||
|
|
||||||
mime.associations."audio/flac" = "vlc.desktop";
|
|
||||||
mime.associations."audio/mpeg" = "vlc.desktop";
|
|
||||||
mime.associations."audio/x-vorbis+ogg" = "vlc.desktop";
|
|
||||||
mime.associations."video/mp4" = "vlc.desktop";
|
|
||||||
mime.associations."video/quicktime" = "vlc.desktop";
|
|
||||||
mime.associations."video/webm" = "vlc.desktop";
|
|
||||||
mime.associations."video/x-matroska" = "vlc.desktop";
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,4 +0,0 @@
|
|||||||
{ config, ... }:
|
|
||||||
{
|
|
||||||
programs.wireshark.enable = config.sane.programs.wireshark.enabled;
|
|
||||||
}
|
|
@@ -1,7 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
{
|
|
||||||
sane.programs.xarchiver.package = pkgs.xarchiver.override {
|
|
||||||
# unar doesn't cross compile well, so disable support for it
|
|
||||||
unar = null;
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,56 +0,0 @@
|
|||||||
{ config, lib, pkgs, ... }:
|
|
||||||
let
|
|
||||||
inherit (builtins) map;
|
|
||||||
inherit (lib) mkIf mkOption optionalString types;
|
|
||||||
cfg = config.sane.programs.docsets.config;
|
|
||||||
configOpts = types.submodule {
|
|
||||||
options = {
|
|
||||||
rustPkgs = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [ ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
in {
|
|
||||||
sane.programs.zeal = {
|
|
||||||
# package = pkgs.zeal-qt6; #< TODO: upgrade system to qt6 versions of everything (i.e. jellyfin-media-player, nheko)
|
|
||||||
package = pkgs.zeal-qt5;
|
|
||||||
persist.plaintext = [
|
|
||||||
".cache/Zeal"
|
|
||||||
".local/share/Zeal"
|
|
||||||
];
|
|
||||||
fs.".local/share/Zeal/Zeal/docsets/system".symlink.target = "/run/current-system/sw/share/docset";
|
|
||||||
suggestedPrograms = [ "docsets" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
sane.programs.docsets = {
|
|
||||||
configOption = mkOption {
|
|
||||||
type = configOpts;
|
|
||||||
default = {};
|
|
||||||
};
|
|
||||||
package = pkgs.symlinkJoin {
|
|
||||||
name = "docsets";
|
|
||||||
# build each package with rust docs
|
|
||||||
paths = map (name:
|
|
||||||
let
|
|
||||||
orig = pkgs."${name}";
|
|
||||||
withDocs = orig.overrideAttrs (upstream: {
|
|
||||||
nativeBuildInputs = upstream.nativeBuildInputs or [] ++ [
|
|
||||||
pkgs.cargoDocsetHook
|
|
||||||
];
|
|
||||||
});
|
|
||||||
in
|
|
||||||
"${toString withDocs}/share/docset"
|
|
||||||
) cfg.rustPkgs;
|
|
||||||
# link only the docs (not any binaries)
|
|
||||||
postBuild = optionalString (cfg.rustPkgs != []) ''
|
|
||||||
mkdir -p $out/share/docset
|
|
||||||
mv $out/*.docset $out/share/docset
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
environment.pathsToLink = mkIf config.sane.programs.zeal.enabled [
|
|
||||||
"/share/docset"
|
|
||||||
];
|
|
||||||
}
|
|
@@ -1,147 +0,0 @@
|
|||||||
# zsh files/init order
|
|
||||||
# - see `man zsh` => "STARTUP/SHUTDOWN FILES"
|
|
||||||
# - /etc/zshenv
|
|
||||||
# - $ZDOTDIR/.zshenv
|
|
||||||
# - if login shell:
|
|
||||||
# - /etc/zprofile
|
|
||||||
# - $ZDOTDIR/.zprofile
|
|
||||||
# - if interactive:
|
|
||||||
# - /etc/zshrc
|
|
||||||
# - $ZDOTDIR/.zshrc
|
|
||||||
# - if login (again):
|
|
||||||
# - /etc/zlogin
|
|
||||||
# - ZDOTDIR/.zlogin
|
|
||||||
# - at exit:
|
|
||||||
# - $ZDOTDIR/.zlogout
|
|
||||||
# - /etc/zlogout
|
|
||||||
|
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
inherit (lib) mkIf mkMerge mkOption types;
|
|
||||||
cfg = config.sane.zsh;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
./p10k.nix
|
|
||||||
./starship.nix
|
|
||||||
];
|
|
||||||
options = {
|
|
||||||
sane.zsh = {
|
|
||||||
showDeadlines = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
description = "show upcoming deadlines (from my PKM) upon shell init";
|
|
||||||
};
|
|
||||||
p10k = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = false;
|
|
||||||
description = "enable powerlevel10k prompt and prezto";
|
|
||||||
};
|
|
||||||
starship = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
description = "enable starship prompt";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkMerge [
|
|
||||||
({
|
|
||||||
sane.programs.zsh = {
|
|
||||||
persist.private = [
|
|
||||||
# we don't need to full zsh dir -- just the history file --
|
|
||||||
# but zsh will sometimes backup the history file and symlinking just the file messes things up
|
|
||||||
".local/share/zsh"
|
|
||||||
];
|
|
||||||
persist.plaintext = [
|
|
||||||
# cache gitstatus otherwise p10k fetches it from the net EVERY BOOT
|
|
||||||
".cache/gitstatus"
|
|
||||||
];
|
|
||||||
|
|
||||||
fs.".config/zsh/.zshrc".symlink.text = ''
|
|
||||||
# zsh/prezto complains if zshrc doesn't exist or is empty;
|
|
||||||
# preserve this comment to prevent that from ever happening.
|
|
||||||
'' + lib.optionalString cfg.showDeadlines ''
|
|
||||||
${pkgs.sane-scripts.deadlines}/bin/sane-deadlines
|
|
||||||
'' + ''
|
|
||||||
|
|
||||||
HISTFILE="$HOME/.local/share/zsh/history"
|
|
||||||
|
|
||||||
# auto-cd into any of these dirs by typing them and pressing 'enter':
|
|
||||||
hash -d 3rd="/home/colin/dev/3rd"
|
|
||||||
hash -d dev="/home/colin/dev"
|
|
||||||
hash -d knowledge="/home/colin/knowledge"
|
|
||||||
hash -d nixos="/home/colin/nixos"
|
|
||||||
hash -d nixpkgs="/home/colin/dev/3rd/nixpkgs"
|
|
||||||
hash -d ref="/home/colin/ref"
|
|
||||||
hash -d secrets="/home/colin/knowledge/secrets"
|
|
||||||
hash -d tmp="/home/colin/tmp"
|
|
||||||
hash -d uninsane="/home/colin/dev/uninsane"
|
|
||||||
hash -d Videos="/home/colin/Videos"
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
})
|
|
||||||
(mkIf config.sane.programs.zsh.enabled {
|
|
||||||
# enable zsh completions
|
|
||||||
environment.pathsToLink = [ "/share/zsh" ];
|
|
||||||
|
|
||||||
programs.zsh = {
|
|
||||||
enable = true;
|
|
||||||
shellAliases = {
|
|
||||||
":q" = "exit";
|
|
||||||
# common typos
|
|
||||||
"cd.." = "cd ..";
|
|
||||||
"cd../" = "cd ../";
|
|
||||||
};
|
|
||||||
setOptions = [
|
|
||||||
# docs: `man zshoptions`
|
|
||||||
# nixos defaults:
|
|
||||||
"HIST_FCNTL_LOCK"
|
|
||||||
"HIST_IGNORE_DUPS"
|
|
||||||
"SHARE_HISTORY"
|
|
||||||
# customizations:
|
|
||||||
"AUTO_CD" # type directory name to go there
|
|
||||||
"AUTO_MENU" # show auto-complete menu on double-tab
|
|
||||||
"CDABLE_VARS" # allow auto-cd to use my `hash` aliases -- not just immediate subdirs
|
|
||||||
"CLOBBER" # allow `foo > bar.txt` to overwrite bar.txt
|
|
||||||
"NO_CORRECT" # don't try to correct commands
|
|
||||||
"PIPE_FAIL" # when `cmd_a | cmd_b`, make $? be non-zero if *any* of cmd_a or cmd_b fail
|
|
||||||
"RM_STAR_SILENT" # disable `rm *` confirmations
|
|
||||||
];
|
|
||||||
|
|
||||||
# .zshenv config:
|
|
||||||
shellInit = ''
|
|
||||||
ZDOTDIR=$HOME/.config/zsh
|
|
||||||
'';
|
|
||||||
|
|
||||||
# system-wide .zshrc config:
|
|
||||||
interactiveShellInit = ''
|
|
||||||
# zmv is a way to do rich moves/renames, with pattern matching/substitution.
|
|
||||||
# see for an example: <https://filipe.kiss.ink/zmv-zsh-rename/>
|
|
||||||
autoload -Uz zmv
|
|
||||||
|
|
||||||
HISTORY_IGNORE='(sane-shutdown *|sane-reboot *|rm *|nixos-rebuild.* switch|switch)'
|
|
||||||
|
|
||||||
# extra aliases
|
|
||||||
# TODO: move to `shellAliases` config?
|
|
||||||
function nd() {
|
|
||||||
mkdir -p "$1";
|
|
||||||
pushd "$1";
|
|
||||||
}
|
|
||||||
|
|
||||||
function switch() {
|
|
||||||
sudo nixos-rebuild --flake . switch --keep-going;
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
|
|
||||||
syntaxHighlighting.enable = true;
|
|
||||||
vteIntegration = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
# enable a command-not-found hook to show nix packages that might provide the binary typed.
|
|
||||||
# programs.nix-index.enableZshIntegration = true;
|
|
||||||
programs.command-not-found.enable = false;
|
|
||||||
})
|
|
||||||
];
|
|
||||||
}
|
|
@@ -1,75 +0,0 @@
|
|||||||
{ config, lib, pkgs, ...}:
|
|
||||||
|
|
||||||
let
|
|
||||||
# powerlevel10k prompt config
|
|
||||||
# p10k.zsh is the auto-generated config, and i overwrite those defaults here, below.
|
|
||||||
p10k-overrides = ''
|
|
||||||
# powerlevel10k launches a gitstatusd daemon to accelerate git prompt queries.
|
|
||||||
# this keeps open file handles for any git repo i touch for 60 minutes (by default).
|
|
||||||
# that prevents unmounting whatever device the git repo is on -- particularly problematic for ~/private.
|
|
||||||
# i can disable gitstatusd and get slower fallback git queries:
|
|
||||||
# - either universally
|
|
||||||
# - or selectively by path
|
|
||||||
# see: <https://github.com/romkatv/powerlevel10k/issues/246>
|
|
||||||
typeset -g POWERLEVEL9K_VCS_DISABLED_DIR_PATTERN='(/home/colin/private/*|/home/colin/knowledge/*)'
|
|
||||||
# typeset -g POWERLEVEL9K_DISABLE_GITSTATUS=true
|
|
||||||
|
|
||||||
# show user@host also when logged into the current machine.
|
|
||||||
# default behavior is to show it only over ssh.
|
|
||||||
typeset -g POWERLEVEL9K_CONTEXT_{DEFAULT,SUDO}_CONTENT_EXPANSION='$P9K_CONTENT'
|
|
||||||
'';
|
|
||||||
|
|
||||||
prezto-init = ''
|
|
||||||
source ${pkgs.zsh-autosuggestions}/share/zsh-autosuggestions/zsh-autosuggestions.zsh
|
|
||||||
source ${pkgs.zsh-syntax-highlighting}/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
|
|
||||||
source ${pkgs.zsh-prezto}/share/zsh-prezto/init.zsh
|
|
||||||
'';
|
|
||||||
in {
|
|
||||||
config = lib.mkIf config.sane.zsh.p10k {
|
|
||||||
sane.programs.zsh = {
|
|
||||||
# prezto = oh-my-zsh fork; controls prompt, auto-completion, etc.
|
|
||||||
# see: https://github.com/sorin-ionescu/prezto
|
|
||||||
# this file is auto-sourced by the prezto init.zsh script.
|
|
||||||
# TODO: i should work to move away from prezto:
|
|
||||||
# - it's FUCKING SLOW to initialize (that might also be powerlevel10k tho)
|
|
||||||
# - it messes with my other `setopt`s
|
|
||||||
fs.".config/zsh/.zpreztorc".symlink.text = ''
|
|
||||||
zstyle ':prezto:*:*' color 'yes'
|
|
||||||
zstyle ':prezto:module:utility' correct 'no' # prezto: don't setopt CORRECT
|
|
||||||
|
|
||||||
# modules (they ship with prezto):
|
|
||||||
# ENVIRONMENT: configures jobs to persist after shell exit; other basic niceties
|
|
||||||
# TERMINAL: auto-titles terminal (e.g. based on cwd)
|
|
||||||
# EDITOR: configures shortcuts like Ctrl+U=undo, Ctrl+L=clear
|
|
||||||
# HISTORY: `history-stat` alias, setopts for good history defaults
|
|
||||||
# DIRECTORY: sets AUTO_CD, adds `d` alias to list directory stack, and `1`-`9` to cd that far back the stack. also overrides CLOBBER and some other options
|
|
||||||
# SPECTRUM: helpers for term colors and styling. used by prompts? might be unnecessary
|
|
||||||
# UTILITY: configures aliases like `ll`, `la`, disables globbing for things like rsync
|
|
||||||
# adds aliases like `get` to fetch a file. also adds `http-serve` alias??
|
|
||||||
# COMPLETION: tab completion. requires `utility` module prior to loading
|
|
||||||
zstyle ':prezto:load' pmodule \
|
|
||||||
'environment' \
|
|
||||||
'terminal' \
|
|
||||||
'editor' \
|
|
||||||
'history' \
|
|
||||||
'spectrum' \
|
|
||||||
'utility' \
|
|
||||||
'completion' \
|
|
||||||
'prompt'
|
|
||||||
|
|
||||||
# default keymap. try also `vicmd` (vim normal mode, AKA "cmd mode") or `vi`.
|
|
||||||
zstyle ':prezto:module:editor' key-bindings 'emacs'
|
|
||||||
|
|
||||||
zstyle ':prezto:module:prompt' theme 'powerlevel10k'
|
|
||||||
|
|
||||||
# disable `mv` confirmation (and `rm`, too, unfortunately)
|
|
||||||
zstyle ':prezto:module:utility' safe-ops 'no'
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
programs.zsh.interactiveShellInit = (builtins.readFile ./p10k.zsh)
|
|
||||||
+ p10k-overrides
|
|
||||||
+ prezto-init
|
|
||||||
;
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,101 +0,0 @@
|
|||||||
# starship prompt: <https://starship.rs/config/#prompt>
|
|
||||||
# my own config heavily based off:
|
|
||||||
# - <https://starship.rs/presets/pastel-powerline.html>
|
|
||||||
{ config, lib, pkgs, ...}:
|
|
||||||
|
|
||||||
let
|
|
||||||
enabled = config.sane.zsh.starship;
|
|
||||||
toml = pkgs.formats.toml {};
|
|
||||||
colors = {
|
|
||||||
# colors sorted by the order they appear in the status bar
|
|
||||||
_01_purple = "#9A348E";
|
|
||||||
_02_pink = "#DA627D";
|
|
||||||
_03_orange = "#FCA17D";
|
|
||||||
_04_teal = "#86BBD8";
|
|
||||||
_05_blue = "#06969A";
|
|
||||||
_06_blue = "#33658A";
|
|
||||||
};
|
|
||||||
in {
|
|
||||||
config = lib.mkIf config.sane.zsh.starship {
|
|
||||||
sane.programs.zsh = lib.mkIf enabled {
|
|
||||||
fs.".config/zsh/.zshrc".symlink.text = ''
|
|
||||||
eval "$(${pkgs.starship}/bin/starship init zsh)"
|
|
||||||
'';
|
|
||||||
fs.".config/starship.toml".symlink.target = toml.generate "starship.toml" {
|
|
||||||
format = builtins.concatStringsSep "" [
|
|
||||||
"[](${colors._01_purple})"
|
|
||||||
"$os"
|
|
||||||
"$username"
|
|
||||||
"$hostname"
|
|
||||||
"[](bg:${colors._02_pink} fg:${colors._01_purple})"
|
|
||||||
"$directory"
|
|
||||||
"[](fg:${colors._02_pink} bg:${colors._03_orange})"
|
|
||||||
"$git_branch"
|
|
||||||
"$git_status"
|
|
||||||
"[](fg:${colors._03_orange} bg:${colors._04_teal})"
|
|
||||||
"[](fg:${colors._04_teal} bg:${colors._05_blue})"
|
|
||||||
"[](fg:${colors._05_blue} bg:${colors._06_blue})"
|
|
||||||
"$time"
|
|
||||||
"$status"
|
|
||||||
"[ ](fg:${colors._06_blue})"
|
|
||||||
];
|
|
||||||
add_newline = false; # no blank line before prompt
|
|
||||||
|
|
||||||
os.style = "bg:${colors._01_purple}";
|
|
||||||
os.format = "[$symbol]($style)";
|
|
||||||
os.disabled = false;
|
|
||||||
# os.symbols.NixOS = "❄️"; # removes the space after logo
|
|
||||||
|
|
||||||
# TODO: tune foreground color of username
|
|
||||||
username.style_user = "bg:${colors._01_purple}";
|
|
||||||
username.style_root = "bold bg:${colors._01_purple}";
|
|
||||||
username.format = "[$user ]($style)";
|
|
||||||
|
|
||||||
hostname.style = "bold bg:${colors._01_purple}";
|
|
||||||
hostname.format = "[$ssh_symbol$hostname ]($style)";
|
|
||||||
|
|
||||||
directory.style = "bg:${colors._02_pink} fg:#ffffff";
|
|
||||||
directory.format = "[ $path ]($style)";
|
|
||||||
directory.truncation_length = 3;
|
|
||||||
directory.truncation_symbol = "…/";
|
|
||||||
|
|
||||||
# git_branch.symbol = ""; # looks good in nerd fonts
|
|
||||||
git_branch.symbol = "";
|
|
||||||
git_branch.style = "bg:${colors._03_orange} fg:#ffffff";
|
|
||||||
# git_branch.style = "bg:#FF8262";
|
|
||||||
git_branch.format = "[ $symbol $branch ]($style)";
|
|
||||||
|
|
||||||
git_status.style = "bold bg:${colors._03_orange} fg:#ffffff";
|
|
||||||
# git_status.style = "bg:#FF8262";
|
|
||||||
git_status.format = "[$all_status$ahead_behind ]($style)";
|
|
||||||
git_status.ahead = "⇡$count";
|
|
||||||
git_status.behind = "⇣$count";
|
|
||||||
# git_status.diverged = "⇣$behind_count⇡$ahead_count";
|
|
||||||
git_status.diverged = "⇡$ahead_count⇣$behind_count";
|
|
||||||
git_status.modified = "*";
|
|
||||||
git_status.stashed = "";
|
|
||||||
git_status.untracked = "";
|
|
||||||
|
|
||||||
|
|
||||||
time.disabled = true;
|
|
||||||
time.time_format = "%R"; # Hour:Minute Format
|
|
||||||
time.style = "bg:${colors._06_blue}";
|
|
||||||
time.format = "[ $time ]($style)";
|
|
||||||
|
|
||||||
status.disabled = false;
|
|
||||||
status.style = "bg:${colors._06_blue}";
|
|
||||||
# status.success_symbol = "♥ ";
|
|
||||||
# status.success_symbol = "💖";
|
|
||||||
# status.success_symbol = "💙";
|
|
||||||
# status.success_symbol = "💚";
|
|
||||||
# status.success_symbol = "💜";
|
|
||||||
# status.success_symbol = "✔️'";
|
|
||||||
status.success_symbol = "";
|
|
||||||
status.symbol = "❌";
|
|
||||||
# status.symbol = "❗️";
|
|
||||||
# status.symbol = "‼️";
|
|
||||||
status.format = "[$symbol]($style)";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,53 +1,38 @@
|
|||||||
# SOPS configuration:
|
{ config, ... }:
|
||||||
# docs: https://github.com/Mic92/sops-nix
|
|
||||||
#
|
|
||||||
# for each new user you want to edit sops files:
|
|
||||||
# create a private age key from ssh key:
|
|
||||||
# $ mkdir -p ~/.config/sops/age; ssh-to-age -private-key -i ~/.ssh/id_ed25519 > ~/.config/sops/age/keys.txt; chmod 600 ~/.config/sops/age/keys.txt
|
|
||||||
# if the private key was password protected, then first decrypt it:
|
|
||||||
# $ cp ~/.ssh/id_ed25519 /tmp/id_ed25519
|
|
||||||
# $ ssh-keygen -p -N "" -f /tmp/id_ed25519
|
|
||||||
#
|
|
||||||
# for each user you want to decrypt secrets:
|
|
||||||
# $ cat ~/.ssh/id_ed25519.pub | ssh-to-age
|
|
||||||
# add the result to .sops.yaml
|
|
||||||
# since we specify ssh pubkeys in the nix config, you can just grep for `ssh-ed25519` here and use those instead
|
|
||||||
#
|
|
||||||
# for each host you want to decrypt secrets:
|
|
||||||
# $ cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-to-age
|
|
||||||
# add the result to .sops.yaml
|
|
||||||
# $ sops updatekeys secrets/example.yaml
|
|
||||||
#
|
|
||||||
# to create a new secret:
|
|
||||||
# $ sops secrets/example.yaml
|
|
||||||
# control access below (sops.secret.<x>.owner = ...)
|
|
||||||
#
|
|
||||||
# to read a secret:
|
|
||||||
# $ cat /run/secrets/example_key
|
|
||||||
|
|
||||||
{ config, lib, sane-lib, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
inherit (lib.strings) hasSuffix removeSuffix;
|
|
||||||
secretsForHost = host: let
|
|
||||||
extraAttrsForPath = path: lib.optionalAttrs (sane-lib.path.isChild "guest" path && builtins.hasAttr "guest" config.users.users) {
|
|
||||||
owner = "guest";
|
|
||||||
};
|
|
||||||
in sane-lib.joinAttrsets (
|
|
||||||
map
|
|
||||||
(path: lib.optionalAttrs (hasSuffix ".bin" path) (sane-lib.nameValueToAttrs {
|
|
||||||
name = removeSuffix ".bin" path;
|
|
||||||
value = {
|
|
||||||
sopsFile = ../../secrets/${host}/${path};
|
|
||||||
format = "binary";
|
|
||||||
} // (extraAttrsForPath path);
|
|
||||||
}))
|
|
||||||
(sane-lib.enumerateFilePaths ../../secrets/${host})
|
|
||||||
);
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
|
# SOPS configuration:
|
||||||
|
# docs: https://github.com/Mic92/sops-nix
|
||||||
|
#
|
||||||
|
# for each new user you want to edit sops files:
|
||||||
|
# create a private age key from ssh key:
|
||||||
|
# $ mkdir -p ~/.config/sops/age; ssh-to-age -private-key -i ~/.ssh/id_ed25519 > ~/.config/sops/age/keys.txt; chmod 600 ~/.config/sops/age/keys.txt
|
||||||
|
# if the private key was password protected, then first decrypt it:
|
||||||
|
# $ cp ~/.ssh/id_ed25519 /tmp/id_ed25519
|
||||||
|
# $ ssh-keygen -p -N "" -f /tmp/id_ed25519
|
||||||
|
#
|
||||||
|
# for each user you want to decrypt secrets:
|
||||||
|
# $ cat ~/.ssh/id_ed25519.pub | ssh-to-age
|
||||||
|
# add the result to .sops.yaml
|
||||||
|
# since we specify ssh pubkeys in the nix config, you can just grep for `ssh-ed25519` here and use those instead
|
||||||
|
#
|
||||||
|
# for each host you want to decrypt secrets:
|
||||||
|
# $ cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-to-age
|
||||||
|
# add the result to .sops.yaml
|
||||||
|
# $ sops updatekeys secrets/example.yaml
|
||||||
|
#
|
||||||
|
# to create a new secret:
|
||||||
|
# $ sops secrets/example.yaml
|
||||||
|
# control access below (sops.secret.<x>.owner = ...)
|
||||||
|
#
|
||||||
|
# to read a secret:
|
||||||
|
# $ cat /run/secrets/example_key
|
||||||
|
|
||||||
# sops.age.sshKeyPaths = [ "/home/colin/.ssh/id_ed25519_dec" ];
|
# sops.age.sshKeyPaths = [ "/home/colin/.ssh/id_ed25519_dec" ];
|
||||||
|
# This will add secrets.yaml to the nix store
|
||||||
|
# You can avoid this by adding a string to the full path instead, i.e.
|
||||||
|
# sops.defaultSopsFile = "/root/.sops/secrets/example.yaml";
|
||||||
|
sops.defaultSopsFile = ../../secrets/universal.yaml;
|
||||||
sops.gnupg.sshKeyPaths = []; # disable RSA key import
|
sops.gnupg.sshKeyPaths = []; # disable RSA key import
|
||||||
# This is using an age key that is expected to already be in the filesystem
|
# This is using an age key that is expected to already be in the filesystem
|
||||||
# sops.age.keyFile = "/home/colin/.ssh/age.pub";
|
# sops.age.keyFile = "/home/colin/.ssh/age.pub";
|
||||||
@@ -60,15 +45,80 @@ in
|
|||||||
# };
|
# };
|
||||||
# sops.secrets."myservice/my_subdir/my_secret" = {};
|
# sops.secrets."myservice/my_subdir/my_secret" = {};
|
||||||
|
|
||||||
sops.secrets = lib.mkMerge [
|
## universal secrets
|
||||||
(secretsForHost "common")
|
# TODO: glob these?
|
||||||
(secretsForHost config.networking.hostName)
|
|
||||||
{
|
sops.secrets."jackett_apikey" = {
|
||||||
"jackett_apikey".owner = config.users.users.colin.name;
|
sopsFile = ../../secrets/universal.yaml;
|
||||||
"mx-sanebot-env".owner = config.users.users.colin.name;
|
owner = config.users.users.colin.name;
|
||||||
"transmission_passwd".owner = config.users.users.colin.name;
|
};
|
||||||
}
|
sops.secrets."router_passwd" = {
|
||||||
];
|
sopsFile = ../../secrets/universal.yaml;
|
||||||
|
};
|
||||||
|
sops.secrets."wg_ovpnd_us_privkey" = {
|
||||||
|
sopsFile = ../../secrets/universal.yaml;
|
||||||
|
};
|
||||||
|
sops.secrets."wg_ovpnd_us-atl_privkey" = {
|
||||||
|
sopsFile = ../../secrets/universal.yaml;
|
||||||
|
};
|
||||||
|
sops.secrets."wg_ovpnd_us-mi_privkey" = {
|
||||||
|
sopsFile = ../../secrets/universal.yaml;
|
||||||
|
};
|
||||||
|
sops.secrets."wg_ovpnd_ukr_privkey" = {
|
||||||
|
sopsFile = ../../secrets/universal.yaml;
|
||||||
|
};
|
||||||
|
|
||||||
|
sops.secrets."snippets" = {
|
||||||
|
sopsFile = ../../secrets/universal/snippets.bin;
|
||||||
|
format = "binary";
|
||||||
|
owner = config.users.users.colin.name;
|
||||||
|
};
|
||||||
|
|
||||||
|
sops.secrets."bt/car" = {
|
||||||
|
sopsFile = ../../secrets/universal/bt/car.bin;
|
||||||
|
format = "binary";
|
||||||
|
};
|
||||||
|
sops.secrets."bt/earbuds" = {
|
||||||
|
sopsFile = ../../secrets/universal/bt/earbuds.bin;
|
||||||
|
format = "binary";
|
||||||
|
};
|
||||||
|
sops.secrets."bt/portable-speaker" = {
|
||||||
|
sopsFile = ../../secrets/universal/bt/portable-speaker.bin;
|
||||||
|
format = "binary";
|
||||||
|
};
|
||||||
|
|
||||||
|
sops.secrets."iwd/community-university.psk" = {
|
||||||
|
sopsFile = ../../secrets/universal/net/community-university.psk.bin;
|
||||||
|
format = "binary";
|
||||||
|
};
|
||||||
|
sops.secrets."iwd/friend-libertarian-dod.psk" = {
|
||||||
|
sopsFile = ../../secrets/universal/net/friend-libertarian-dod.psk.bin;
|
||||||
|
format = "binary";
|
||||||
|
};
|
||||||
|
sops.secrets."iwd/friend-rationalist-empathist.psk" = {
|
||||||
|
sopsFile = ../../secrets/universal/net/friend-rationalist-empathist.psk.bin;
|
||||||
|
format = "binary";
|
||||||
|
};
|
||||||
|
sops.secrets."iwd/home-bedroom.psk" = {
|
||||||
|
sopsFile = ../../secrets/universal/net/home-bedroom.psk.bin;
|
||||||
|
format = "binary";
|
||||||
|
};
|
||||||
|
sops.secrets."iwd/home-shared-24G.psk" = {
|
||||||
|
sopsFile = ../../secrets/universal/net/home-shared-24G.psk.bin;
|
||||||
|
format = "binary";
|
||||||
|
};
|
||||||
|
sops.secrets."iwd/home-shared.psk" = {
|
||||||
|
sopsFile = ../../secrets/universal/net/home-shared.psk.bin;
|
||||||
|
format = "binary";
|
||||||
|
};
|
||||||
|
sops.secrets."iwd/iphone" = {
|
||||||
|
sopsFile = ../../secrets/universal/net/iphone.psk.bin;
|
||||||
|
format = "binary";
|
||||||
|
};
|
||||||
|
sops.secrets."iwd/parents" = {
|
||||||
|
sopsFile = ../../secrets/universal/net/parents.psk.bin;
|
||||||
|
format = "binary";
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,8 +1,5 @@
|
|||||||
{ config, lib, sane-data, sane-lib, ... }:
|
{ config, lib, sane-data, sane-lib, ... }:
|
||||||
|
|
||||||
let
|
|
||||||
inherit (builtins) attrValues head map mapAttrs tail;
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
sane.ssh.pubkeys =
|
sane.ssh.pubkeys =
|
||||||
let
|
let
|
||||||
@@ -10,45 +7,18 @@ in
|
|||||||
keyNameForPath = path:
|
keyNameForPath = path:
|
||||||
let
|
let
|
||||||
rev = lib.reverseList path;
|
rev = lib.reverseList path;
|
||||||
name = head rev;
|
name = builtins.head rev;
|
||||||
host = lib.concatStringsSep "." (tail rev);
|
host = lib.concatStringsSep "." (builtins.tail rev);
|
||||||
in
|
in
|
||||||
"${name}@${host}";
|
"${name}@${host}";
|
||||||
|
|
||||||
# [{ path :: [String], value :: String }] for the keys we want to install
|
# [{ path :: [String], value :: String }] for the keys we want to install
|
||||||
globalKeys = sane-lib.flattenAttrs sane-data.keys;
|
globalKeys = sane-lib.flattenAttrs sane-data.keys;
|
||||||
|
localKeys = sane-lib.flattenAttrs sane-data.keys.org.uninsane.local;
|
||||||
keysForHost = hostCfg: sane-lib.mapToAttrs
|
in lib.mkMerge (builtins.map
|
||||||
(name: {
|
|
||||||
inherit name;
|
|
||||||
value = {
|
|
||||||
root = hostCfg.ssh.host_pubkey;
|
|
||||||
} // (lib.optionalAttrs hostCfg.ssh.authorized {
|
|
||||||
colin = hostCfg.ssh.user_pubkey;
|
|
||||||
});
|
|
||||||
})
|
|
||||||
hostCfg.names
|
|
||||||
;
|
|
||||||
domainKeys = sane-lib.flattenAttrs (
|
|
||||||
sane-lib.joinAttrsets (
|
|
||||||
map keysForHost (builtins.attrValues config.sane.hosts.by-name)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
in lib.mkMerge (map
|
|
||||||
({ path, value }: {
|
({ path, value }: {
|
||||||
"${keyNameForPath path}" = lib.mkIf (value != null) value;
|
"${keyNameForPath path}" = value;
|
||||||
})
|
})
|
||||||
(globalKeys ++ domainKeys)
|
(globalKeys ++ localKeys)
|
||||||
);
|
);
|
||||||
|
|
||||||
services.openssh = {
|
|
||||||
enable = true;
|
|
||||||
settings.PermitRootLogin = "no";
|
|
||||||
settings.PasswordAuthentication = false;
|
|
||||||
};
|
|
||||||
sane.ports.ports."22" = {
|
|
||||||
protocol = [ "tcp" ];
|
|
||||||
visibleTo.lan = true;
|
|
||||||
description = lib.mkDefault "colin-ssh";
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user