Compare commits
2 Commits
wip/sxmo-a
...
wip/sway3-
Author | SHA1 | Date | |
---|---|---|---|
cd9e81c632 | |||
64b517f8c0 |
@@ -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
|
||||||
|
108
README.md
108
README.md
@@ -1,108 +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
|
|
||||||
- `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 are referenced by other things in this repo.
|
|
||||||
- these aren't generally user-facing, but they're factored out so that they can
|
|
||||||
be invoked directly when i need to debug.
|
|
||||||
- `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).
|
|
77
TODO.md
77
TODO.md
@@ -1,77 +0,0 @@
|
|||||||
## BUGS
|
|
||||||
- why i need to manually restart `wireguard-wg-ovpns` on servo periodically
|
|
||||||
- else DNS fails
|
|
||||||
|
|
||||||
## 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 trust-dns module
|
|
||||||
- see: <https://github.com/NixOS/nixpkgs/pull/205866#issuecomment-1575753054>
|
|
||||||
- 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
|
|
||||||
- fix or abandon Whalebird
|
|
||||||
- FIX failed CI on bonsai PR: <https://github.com/NixOS/nixpkgs/pull/233892>
|
|
||||||
- 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.
|
|
||||||
- canaries for important services
|
|
||||||
- e.g. daily email checks; daily backup checks
|
|
||||||
|
|
||||||
### user experience
|
|
||||||
- firefox/librewolf: don't show browserpass/sponsorblock/metamask "first run" on every boot
|
|
||||||
- moby: improve gPodder launch time
|
|
||||||
- moby: replace jellyfin-desktop with jellyfin-vue?
|
|
||||||
- allows (maybe) to cache media for offline use
|
|
||||||
- "newer" jellyfin client
|
|
||||||
- not packaged for nix
|
|
||||||
- moby/sxmo: display numerical vol percentage in topbar
|
|
||||||
- moby/sxmo: include librewolf, jellyfin in `apps` menu
|
|
||||||
- find a nice desktop ActivityPub client
|
|
||||||
- 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)
|
|
||||||
- auto-mount servo
|
|
||||||
- have xdg-open parse `<repo:...> URIs (or adjust them so that it _can_ parse)
|
|
||||||
- `sane.programs`: auto-populate defaults with everything from `pkgs`
|
|
||||||
- zsh: disable "command not found" corrections
|
|
||||||
- sane-bt-search: show details like 5.1 vs stereo, h264 vs h265
|
|
||||||
|
|
||||||
### perf
|
|
||||||
- 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?
|
|
||||||
- fix OOM for large builds like webkitgtk
|
|
||||||
- these use significant /tmp space.
|
|
||||||
- either place /tmp on encrypted-cleared-at-boot storage
|
|
||||||
- which probably causes each CPU load for the encryption
|
|
||||||
- **or set up encrypted swap**
|
|
||||||
- encrypted swap could remove the need for my encrypted-cleared-at-boot stuff
|
|
||||||
|
|
||||||
|
|
||||||
## NEW FEATURES:
|
|
||||||
- add a FTP-accessible file share to servo
|
|
||||||
- just /var/www?
|
|
||||||
- migrate MAME cabinet to nix
|
|
||||||
- boot it from PXE from servo?
|
|
||||||
- enable IPv6
|
|
125
flake.lock
generated
125
flake.lock
generated
@@ -2,11 +2,11 @@
|
|||||||
"nodes": {
|
"nodes": {
|
||||||
"flake-utils": {
|
"flake-utils": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1678901627,
|
"lastModified": 1659877975,
|
||||||
"narHash": "sha256-U02riOqrKKzwjsxc/400XnElV+UtPUQWpANPlyazjH0=",
|
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "93a2b84fc4b70d9e089d029deacc3583435c2ed6",
|
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -15,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": 1683422260,
|
"lastModified": 1674779092,
|
||||||
"narHash": "sha256-79zaClbubRkBNlJ04OSADILuLQHH48N5fu296hEWYlw=",
|
"narHash": "sha256-mFBD0Dvjf8tuxWtJhsCQ+8VYqI4fQeWjd/vfWsZiRRo=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "mobile-nixos",
|
"repo": "mobile-nixos",
|
||||||
"rev": "ba4638836e94a8f16d1d1f9e8c0530b86078029c",
|
"rev": "80ece5a61738fbf3b96fdda402ab2dfc74ee5cee",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -31,62 +52,62 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nix-serve": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": "nixpkgs"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1684319086,
|
|
||||||
"narHash": "sha256-5wwlkWqP1cQUPXp/PJsi09FkgAule5yBghngRZZbUQg=",
|
|
||||||
"owner": "edolstra",
|
|
||||||
"repo": "nix-serve",
|
|
||||||
"rev": "e6e3d09438e803daa5374ad8edf1271289348456",
|
|
||||||
"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-5pNu9Ph1LIBj5q9RWLV3r7daANjmd4u5y+MVq8vlfS4=",
|
||||||
"owner": "NixOS",
|
"path": "/nix/store/bjzsgw8zn4av0dv4sqyj7vxhi43na16y-source/nixpatches",
|
||||||
"repo": "nixpkgs",
|
"type": "path"
|
||||||
"rev": "19db3e5ea2777daa874563b5986288151f502e27",
|
|
||||||
"type": "github"
|
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"id": "nixpkgs",
|
"path": "/nix/store/bjzsgw8zn4av0dv4sqyj7vxhi43na16y-source/nixpatches",
|
||||||
"ref": "nixos-20.09",
|
"type": "path"
|
||||||
"type": "indirect"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs-stable": {
|
"nixpkgs-stable": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1687031877,
|
"lastModified": 1674692158,
|
||||||
"narHash": "sha256-yMFcVeI+kZ6KD2QBrFPNsvBrLq2Gt//D0baHByMrjFY=",
|
"narHash": "sha256-oqGpwVg4D+eMSgF7Th5Ve1ysCiH3H3g85vGJ3nvJsZQ=",
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "def9e420d27c951026d57dc96ce0218c3131f412",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nixos",
|
||||||
|
"ref": "nixos-22.11",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs-stable_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1674352297,
|
||||||
|
"narHash": "sha256-OkAnJPrauEcUCrst4/3DKoQfUn2gXKuU6CFvhtMrLgg=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "e2e2059d19668dab1744301b8b0e821e3aae9c99",
|
"rev": "918b760070bb8f48cb511300fcd7e02e13058a2e",
|
||||||
"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": 1686960236,
|
"lastModified": 1674641431,
|
||||||
"narHash": "sha256-AYCC9rXNLpUWzD9hm+askOfpliLEC9kwAo7ITJc4HIw=",
|
"narHash": "sha256-qfo19qVZBP4qn5M5gXc/h1MDgAtPA5VxJm9s8RUAkVk=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "04af42f3b31dba0ef742d254456dc4c14eedac86",
|
"rev": "9b97ad7b4330aacda9b2343396eb3df8a853b4fc",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -98,8 +119,10 @@
|
|||||||
},
|
},
|
||||||
"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"
|
||||||
@@ -108,16 +131,16 @@
|
|||||||
"sops-nix": {
|
"sops-nix": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nixpkgs-unpatched"
|
"nixpkgs"
|
||||||
],
|
],
|
||||||
"nixpkgs-stable": "nixpkgs-stable"
|
"nixpkgs-stable": "nixpkgs-stable_2"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1687058111,
|
"lastModified": 1674546403,
|
||||||
"narHash": "sha256-xDSn/APfAdJinHV4reTfplX5XnLsJSGdVwHpmdgP9Mo=",
|
"narHash": "sha256-vkyNv0xzXuEnu9v52TUtRugNmQWIti8c2RhYnbLG71w=",
|
||||||
"owner": "Mic92",
|
"owner": "Mic92",
|
||||||
"repo": "sops-nix",
|
"repo": "sops-nix",
|
||||||
"rev": "1634d2da53f079e7f5924efa7a96511cd9596f81",
|
"rev": "b6ab3c61e2ca5e07d1f4eb1b67304e2670ea230c",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -130,15 +153,15 @@
|
|||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-utils": "flake-utils",
|
"flake-utils": "flake-utils",
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nixpkgs-unpatched"
|
"nixpkgs"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1686876043,
|
"lastModified": 1666870107,
|
||||||
"narHash": "sha256-71SNPU2aeeJx29JSeW4JCJb8HXAuZRvL7sbh+c3wgkk=",
|
"narHash": "sha256-b9eXZxSwhzdJI5uQgfrMhu4SY2POrPkinUg7F5gQVYo=",
|
||||||
"ref": "refs/heads/master",
|
"ref": "refs/heads/master",
|
||||||
"rev": "0e0aa12aca143639f158b3a5c0c00349fcc2166c",
|
"rev": "80c6ec95bd430e29d231cf745f19279bb76fb382",
|
||||||
"revCount": 199,
|
"revCount": 164,
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://git.uninsane.org/colin/uninsane"
|
"url": "https://git.uninsane.org/colin/uninsane"
|
||||||
},
|
},
|
||||||
|
250
flake.nix
250
flake.nix
@@ -12,11 +12,6 @@
|
|||||||
# - Flake RFC: <https://github.com/tweag/rfcs/blob/flakes/rfcs/0049-flakes.md>
|
# - Flake RFC: <https://github.com/tweag/rfcs/blob/flakes/rfcs/0049-flakes.md>
|
||||||
# - Discussion: <https://github.com/NixOS/rfcs/pull/49>
|
# - 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
|
# XXX: use the `github:` scheme instead of the more readable git+https: because it's *way* more efficient
|
||||||
@@ -24,77 +19,60 @@
|
|||||||
# but `inputs` is required to be a strict attrset: not an expression.
|
# but `inputs` is required to be a strict attrset: not an expression.
|
||||||
inputs = {
|
inputs = {
|
||||||
# <https://github.com/nixos/nixpkgs/tree/nixos-22.11>
|
# <https://github.com/nixos/nixpkgs/tree/nixos-22.11>
|
||||||
# nixpkgs-stable.url = "github:nixos/nixpkgs?ref=nixos-22.11";
|
nixpkgs-stable.url = "github:nixos/nixpkgs?ref=nixos-22.11";
|
||||||
|
|
||||||
# branch workflow:
|
|
||||||
# - daily:
|
|
||||||
# - nixos-unstable cut from master after enough packages have been built in caches.
|
|
||||||
# - every 6 hours:
|
|
||||||
# - master auto-merged into staging.
|
|
||||||
# - 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>
|
# <https://github.com/nixos/nixpkgs/tree/nixos-unstable>
|
||||||
nixpkgs-unpatched.url = "github:nixos/nixpkgs?ref=nixos-unstable";
|
nixpkgs-unpatched.url = "github:nixos/nixpkgs?ref=nixos-unstable";
|
||||||
# nixpkgs-unpatched.url = "github:nixos/nixpkgs?ref=staging-next";
|
nixpkgs = {
|
||||||
# nixpkgs-unpatched.url = "github:nixos/nixpkgs?ref=staging";
|
url = "./nixpatches";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs-unpatched";
|
||||||
|
};
|
||||||
mobile-nixos = {
|
mobile-nixos = {
|
||||||
# <https://github.com/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 = {
|
||||||
|
# <https://github.com/nix-community/home-manager/tree/release-22.05>
|
||||||
|
url = "github:nix-community/home-manager?ref=release-22.05";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
sops-nix = {
|
sops-nix = {
|
||||||
# <https://github.com/Mic92/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 target).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.
|
||||||
|
# XXX: patch using the target -- not local -- otherwise the target will
|
||||||
|
# need to emulate the host in order to rebuild!
|
||||||
|
nixosSystem = import ((nixpkgsCompiledBy target).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; })
|
(import ./hosts/instantiate.nix { localSystem = local; hostName = name; })
|
||||||
@@ -102,51 +80,25 @@
|
|||||||
self.nixosModules.passthru
|
self.nixosModules.passthru
|
||||||
{
|
{
|
||||||
nixpkgs.overlays = [
|
nixpkgs.overlays = [
|
||||||
|
self.overlays.default
|
||||||
self.overlays.passthru
|
self.overlays.passthru
|
||||||
self.overlays.sane-all
|
self.overlays.pins
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
({ lib, ... }: {
|
|
||||||
# TODO: does the earlier `system` arg to nixosSystem make its way here?
|
|
||||||
nixpkgs.hostPlatform.system = target;
|
|
||||||
# nixpkgs.buildPlatform = local; # set by instantiate.nix instead
|
|
||||||
# nixpkgs.config.replaceStdenv = { pkgs }: pkgs.ccacheStdenv;
|
|
||||||
})
|
|
||||||
];
|
];
|
||||||
};
|
});
|
||||||
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
|
||||||
@@ -163,44 +115,22 @@
|
|||||||
# - 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 ./overlays/pkgs.nix;
|
||||||
|
pins = import ./overlays/pins.nix; # TODO: move to `nixpatches/` input
|
||||||
overlays = {
|
passthru =
|
||||||
# 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;
|
|
||||||
optimizations = final: prev: import ./overlays/optimizations.nix final prev;
|
|
||||||
passthru = final: prev:
|
|
||||||
let
|
let
|
||||||
stable =
|
stable = next: prev: {
|
||||||
if inputs ? "nixpkgs-stable" then (
|
stable = nixpkgs-stable.legacyPackages."${prev.stdenv.hostPlatform.system}";
|
||||||
final': prev': {
|
};
|
||||||
stable = inputs.nixpkgs-stable.legacyPackages."${prev'.stdenv.hostPlatform.system}";
|
|
||||||
}
|
|
||||||
) else (final': prev': {});
|
|
||||||
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
|
||||||
(stable final prev)
|
next: prev:
|
||||||
// (mobile final prev)
|
(stable next prev) // (mobile next prev) // (uninsane next prev);
|
||||||
// (uninsane final prev)
|
|
||||||
// (nix-serve' final prev)
|
|
||||||
;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
nixosModules = rec {
|
nixosModules = rec {
|
||||||
@@ -208,6 +138,7 @@
|
|||||||
sane = import ./modules;
|
sane = import ./modules;
|
||||||
passthru = { ... }: {
|
passthru = { ... }: {
|
||||||
imports = [
|
imports = [
|
||||||
|
home-manager.nixosModule
|
||||||
sops-nix.nixosModules.sops
|
sops-nix.nixosModules.sops
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
@@ -224,87 +155,36 @@
|
|||||||
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 = action: pkgs.writeShellScript "deploy-moby" ''
|
|
||||||
nixos-rebuild --flake '.#moby' build $@
|
|
||||||
sudo nix sign-paths -r -k /run/secrets/nix_serve_privkey $(readlink ./result)
|
|
||||||
nixos-rebuild --flake '.#moby' ${action} --target-host colin@moby --use-remote-sudo $@
|
|
||||||
'';
|
|
||||||
in {
|
in {
|
||||||
update-feeds = {
|
update-feeds = {
|
||||||
type = "app";
|
type = "app";
|
||||||
program = "${pkgs.feeds.updateScript}";
|
program = "${pkgs.feeds.passthru.updateScript}";
|
||||||
};
|
};
|
||||||
|
|
||||||
init-feed = {
|
init-feed = {
|
||||||
# use like `nix run '.#init-feed' uninsane.org`
|
# use like `nix run '.#init-feed' uninsane.org`
|
||||||
type = "app";
|
type = "app";
|
||||||
program = "${pkgs.feeds.initFeedScript}";
|
program = "${pkgs.feeds.passthru.initFeedScript}";
|
||||||
};
|
|
||||||
|
|
||||||
deploy-moby-test = {
|
|
||||||
# `nix run '.#deploy-moby-test'`
|
|
||||||
type = "app";
|
|
||||||
program = ''${deployScript "test"}'';
|
|
||||||
};
|
|
||||||
deploy-moby = {
|
|
||||||
# `nix run '.#deploy-moby-switch'`
|
|
||||||
type = "app";
|
|
||||||
program = ''${deployScript "switch"}'';
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
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"
|
|
@@ -4,22 +4,17 @@
|
|||||||
./fs.nix
|
./fs.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
sops.secrets.colin-passwd.neededForUsers = true;
|
# sane.packages.enableDevPkgs = true;
|
||||||
|
|
||||||
sane.roles.build-machine.enable = true;
|
|
||||||
sane.roles.ac = true;
|
|
||||||
sane.roles.client = true;
|
sane.roles.client = true;
|
||||||
sane.roles.dev-machine = true;
|
|
||||||
sane.services.wg-home.enable = true;
|
sane.services.wg-home.enable = true;
|
||||||
sane.services.wg-home.ip = config.sane.hosts.by-name."desko".wg-home.ip;
|
sane.services.wg-home.ip = config.sane.hosts.by-name."desko".wg-home.ip;
|
||||||
sane.services.duplicity.enable = true;
|
sane.services.duplicity.enable = true;
|
||||||
sane.services.nixserve.secretKeyFile = config.sops.secrets.nix_serve_privkey.path;
|
sane.services.nixserve.enable = true;
|
||||||
|
sane.services.nixserve.sopsFile = ../../../secrets/desko.yaml;
|
||||||
|
sane.persist.enable = true;
|
||||||
|
|
||||||
sane.gui.sway.enable = true;
|
sane.gui.sway.enable = true;
|
||||||
sane.programs.iphoneUtils.enableFor.user.colin = true;
|
|
||||||
|
|
||||||
sane.programs.guiApps.suggestedPrograms = [ "desktopGuiApps" ];
|
|
||||||
sane.programs.consoleUtils.suggestedPrograms = [ "consoleMediaUtils" ];
|
|
||||||
|
|
||||||
boot.loader.efi.canTouchEfiVariables = false;
|
boot.loader.efi.canTouchEfiVariables = false;
|
||||||
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
||||||
@@ -27,6 +22,11 @@
|
|||||||
# needed to use libimobiledevice/ifuse, for iphone sync
|
# needed to use libimobiledevice/ifuse, for iphone sync
|
||||||
services.usbmuxd.enable = true;
|
services.usbmuxd.enable = true;
|
||||||
|
|
||||||
|
sops.secrets.colin-passwd = {
|
||||||
|
sopsFile = ../../../secrets/desko.yaml;
|
||||||
|
neededForUsers = true;
|
||||||
|
};
|
||||||
|
|
||||||
# don't enable wifi by default: it messes with connectivity.
|
# don't enable wifi by default: it messes with connectivity.
|
||||||
systemd.services.iwd.enable = false;
|
systemd.services.iwd.enable = false;
|
||||||
|
|
||||||
@@ -37,9 +37,15 @@
|
|||||||
services.snapper.configs.nix = {
|
services.snapper.configs.nix = {
|
||||||
# TODO: for the impermanent setup, we'd prefer to just do /nix/persist,
|
# TODO: for the impermanent setup, we'd prefer to just do /nix/persist,
|
||||||
# but that also requires setting up the persist dir as a subvol
|
# but that also requires setting up the persist dir as a subvol
|
||||||
SUBVOLUME = "/nix";
|
subvolume = "/nix";
|
||||||
# TODO: ALLOW_USERS doesn't seem to work. still need `sudo snapper -c nix list`
|
# TODO: ALLOW_USERS doesn't seem to work. still need `sudo snapper -c nix list`
|
||||||
ALLOW_USERS = [ "colin" ];
|
extraConfig = ''
|
||||||
|
ALLOW_USERS = "colin";
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
sops.secrets.duplicity_passphrase = {
|
||||||
|
sopsFile = ../../../secrets/desko.yaml;
|
||||||
};
|
};
|
||||||
|
|
||||||
programs.steam = {
|
programs.steam = {
|
||||||
@@ -48,7 +54,7 @@
|
|||||||
remotePlay.openFirewall = true; # Open ports in the firewall for Steam Remote Play
|
remotePlay.openFirewall = true; # Open ports in the firewall for Steam Remote Play
|
||||||
dedicatedServer.openFirewall = true; # Open ports in the firewall for Source Dedicated Server
|
dedicatedServer.openFirewall = true; # Open ports in the firewall for Source Dedicated Server
|
||||||
};
|
};
|
||||||
sane.user.persist.plaintext = [
|
sane.persist.home.plaintext = [
|
||||||
".steam"
|
".steam"
|
||||||
".local/share/Steam"
|
".local/share/Steam"
|
||||||
];
|
];
|
||||||
|
@@ -2,26 +2,25 @@
|
|||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./fs.nix
|
./fs.nix
|
||||||
./polyfill.nix
|
|
||||||
];
|
];
|
||||||
|
|
||||||
sane.roles.client = true;
|
sane.roles.client = true;
|
||||||
sane.roles.dev-machine = true;
|
|
||||||
sane.services.wg-home.enable = true;
|
sane.services.wg-home.enable = true;
|
||||||
sane.services.wg-home.ip = config.sane.hosts.by-name."lappy".wg-home.ip;
|
sane.services.wg-home.ip = config.sane.hosts.by-name."lappy".wg-home.ip;
|
||||||
|
|
||||||
# sane.guest.enable = true;
|
# sane.packages.enableDevPkgs = true;
|
||||||
|
|
||||||
|
# sane.users.guest.enable = true;
|
||||||
sane.gui.sway.enable = true;
|
sane.gui.sway.enable = true;
|
||||||
|
sane.persist.enable = true;
|
||||||
|
sane.nixcache.enable = true;
|
||||||
boot.loader.efi.canTouchEfiVariables = false;
|
boot.loader.efi.canTouchEfiVariables = false;
|
||||||
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
||||||
|
|
||||||
sane.programs.guiApps.suggestedPrograms = [
|
sops.secrets.colin-passwd = {
|
||||||
"desktopGuiApps"
|
sopsFile = ../../../secrets/lappy.yaml;
|
||||||
"stepmania"
|
neededForUsers = true;
|
||||||
];
|
};
|
||||||
sane.programs.consoleUtils.suggestedPrograms = [ "consoleMediaUtils" ];
|
|
||||||
|
|
||||||
sops.secrets.colin-passwd.neededForUsers = true;
|
|
||||||
|
|
||||||
# default config: https://man.archlinux.org/man/snapper-configs.5
|
# default config: https://man.archlinux.org/man/snapper-configs.5
|
||||||
# defaults to something like:
|
# defaults to something like:
|
||||||
@@ -30,8 +29,7 @@
|
|||||||
services.snapper.configs.nix = {
|
services.snapper.configs.nix = {
|
||||||
# TODO: for the impermanent setup, we'd prefer to just do /nix/persist,
|
# TODO: for the impermanent setup, we'd prefer to just do /nix/persist,
|
||||||
# but that also requires setting up the persist dir as a subvol
|
# but that also requires setting up the persist dir as a subvol
|
||||||
SUBVOLUME = "/nix";
|
subvolume = "/nix";
|
||||||
ALLOW_USERS = [ "colin" ];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
# TODO: only here for debugging
|
# TODO: only here for debugging
|
||||||
|
@@ -1,32 +0,0 @@
|
|||||||
# doesn't actually *enable* anything,
|
|
||||||
# but sets up any modules such that if they *were* enabled, they'll act as expected.
|
|
||||||
{ ... }:
|
|
||||||
{
|
|
||||||
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";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
@@ -4,21 +4,30 @@
|
|||||||
./firmware.nix
|
./firmware.nix
|
||||||
./fs.nix
|
./fs.nix
|
||||||
./kernel.nix
|
./kernel.nix
|
||||||
./polyfill.nix
|
|
||||||
];
|
];
|
||||||
|
|
||||||
sane.roles.client = true;
|
sane.roles.client = true;
|
||||||
sane.services.wg-home.enable = true;
|
sane.services.wg-home.enable = true;
|
||||||
sane.services.wg-home.ip = config.sane.hosts.by-name."moby".wg-home.ip;
|
sane.services.wg-home.ip = config.sane.hosts.by-name."moby".wg-home.ip;
|
||||||
|
|
||||||
|
# cross-compiled documentation is *slow*.
|
||||||
|
# no obvious way to natively compile docs (2022/09/29).
|
||||||
|
# entrypoint is nixos/modules/misc/documentation.nix
|
||||||
|
# doc building happens in nixos/doc/manual/default.nix
|
||||||
|
# TODO: we could *maybe* inject pkgs.buildPackages.xyz = cross.buildPackages.xyz?
|
||||||
|
documentation.nixos.enable = false;
|
||||||
|
|
||||||
# XXX colin: phosh doesn't work well with passwordless login,
|
# XXX colin: phosh doesn't work well with passwordless login,
|
||||||
# so set this more reliable default password should anything go wrong
|
# so set this more reliable default password should anything go wrong
|
||||||
users.users.colin.initialPassword = "147147";
|
users.users.colin.initialPassword = "147147";
|
||||||
services.getty.autologinUser = "root"; # allows for emergency maintenance?
|
services.getty.autologinUser = "root"; # allows for emergency maintenance?
|
||||||
|
|
||||||
sops.secrets.colin-passwd.neededForUsers = true;
|
sops.secrets.colin-passwd = {
|
||||||
|
sopsFile = ../../../secrets/moby.yaml;
|
||||||
|
neededForUsers = true;
|
||||||
|
};
|
||||||
|
|
||||||
sane.programs.web-browser.config = {
|
sane.web-browser = {
|
||||||
# compromise impermanence for the sake of usability
|
# compromise impermanence for the sake of usability
|
||||||
persistCache = "private";
|
persistCache = "private";
|
||||||
persistData = "private";
|
persistData = "private";
|
||||||
@@ -28,21 +37,18 @@
|
|||||||
# addons.sideberry.enable = false;
|
# addons.sideberry.enable = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
sane.user.persist.plaintext = [
|
sane.persist.home.plaintext = [
|
||||||
# TODO: make this just generally conditional upon pulse being enabled?
|
|
||||||
".config/pulse" # persist pulseaudio volume
|
".config/pulse" # persist pulseaudio volume
|
||||||
];
|
];
|
||||||
|
|
||||||
sane.gui.sxmo.enable = true;
|
# sane.packages.enableGuiPkgs = false; # XXX faster builds/imaging for debugging
|
||||||
# sane.programs.consoleUtils.enableFor.user.colin = false;
|
sane.packages.extraUserPkgs = [
|
||||||
# sane.programs.guiApps.enableFor.user.colin = false;
|
pkgs.plasma5Packages.konsole # terminal
|
||||||
sane.programs.sequoia.enableFor.user.colin = false;
|
];
|
||||||
sane.programs.tuiApps.enableFor.user.colin = false; # visidata, others, don't compile well
|
|
||||||
# disabled for faster deploys (gthumb depends on webkitgtk, particularly)
|
sane.nixcache.enable = true;
|
||||||
sane.programs.soundconverter.enableFor.user.colin = false;
|
sane.persist.enable = true;
|
||||||
sane.programs.gthumb.enableFor.user.colin = false;
|
sane.gui.phosh.enable = true;
|
||||||
sane.programs.jellyfin-media-player.enableFor.user.colin = false;
|
|
||||||
# sane.programs.mpv.enableFor.user.colin = true;
|
|
||||||
|
|
||||||
boot.loader.efi.canTouchEfiVariables = false;
|
boot.loader.efi.canTouchEfiVariables = false;
|
||||||
# /boot space is at a premium. default was 20.
|
# /boot space is at a premium. default was 20.
|
||||||
@@ -82,30 +88,14 @@
|
|||||||
# enable rotation sensor
|
# enable rotation sensor
|
||||||
hardware.sensor.iio.enable = true;
|
hardware.sensor.iio.enable = true;
|
||||||
|
|
||||||
# inject specialized alsa configs via the environment.
|
# from https://gitlab.manjaro.org/manjaro-arm/packages/community/phosh/alsa-ucm-pinephone
|
||||||
# specifically, this gets the pinephone headphones & internal earpiece working.
|
# mobile-nixos does this same thing, with *slightly different settings*.
|
||||||
# see pkgs/patched/alsa-ucm-conf for more info.
|
# i trust manjaro more because the guy maintaining that is actively trying to upstream into alsa-ucm-conf.
|
||||||
environment.variables.ALSA_CONFIG_UCM2 = "/run/current-system/sw/share/alsa/ucm2";
|
# an alternative may be to build a custom alsa with the PinePhone config patch applied:
|
||||||
environment.pathsToLink = [ "/share/alsa/ucm2" ];
|
# - <https://github.com/alsa-project/alsa-ucm-conf/pull/134>
|
||||||
environment.systemPackages = [ pkgs.alsa-ucm-conf-sane ];
|
# that would make this be not device-specific
|
||||||
systemd =
|
environment.variables.ALSA_CONFIG_UCM2 = "${./ucm2}";
|
||||||
let ucm-env = config.environment.variables.ALSA_CONFIG_UCM2;
|
systemd.services.pulseaudio.environment.ALSA_CONFIG_UCM2 = "${./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;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
hardware.opengl.driSupport = true;
|
hardware.opengl.driSupport = true;
|
||||||
}
|
}
|
||||||
|
@@ -44,6 +44,68 @@ let
|
|||||||
"sha256-6ywm3dQQ5JYl60CLKarxlSUukwi4QzqctCj3tVgzFbo="
|
"sha256-6ywm3dQQ5JYl60CLKarxlSUukwi4QzqctCj3tVgzFbo="
|
||||||
)
|
)
|
||||||
];
|
];
|
||||||
|
|
||||||
|
# pinephone uses the linux dtb at arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||||
|
# - this includes sun50i-a64.dtsi
|
||||||
|
# - and sun50i-a64-cpu-opp.dtsi
|
||||||
|
# - no need to touch the allwinner-h6 stuff: that's the SBC pine product
|
||||||
|
# - i think it's safe to ignore sun9i stuff, but i don't know what it is
|
||||||
|
kernelConfig = with lib.kernel; {
|
||||||
|
# NB: nix adds the CONFIG_ prefix to each of these.
|
||||||
|
# if you add the prefix yourself nix will IGNORE YOUR CONFIG.
|
||||||
|
RTL8723CS = module;
|
||||||
|
BT_HCIUART_3WIRE = yes;
|
||||||
|
BT_HCIUART_RTL = yes;
|
||||||
|
RTL8XXXU_UNTESTED = yes;
|
||||||
|
BT_BNEP_MC_FILTER = yes;
|
||||||
|
BT_BNEP_PROTO_FILTER = yes;
|
||||||
|
BT_HS = yes;
|
||||||
|
BT_LE = yes;
|
||||||
|
# relevant configs inherited from nixos defaults (or above additions):
|
||||||
|
# CONFIG_BT=m
|
||||||
|
# CONFIG_BT_BREDR=y
|
||||||
|
# CONFIG_BT_RFCOMM=m
|
||||||
|
# CONFIG_BT_RFCOMM_TTY=y
|
||||||
|
# CONFIG_BT_BNEP=m
|
||||||
|
# CONFIG_BT_HIDP=m
|
||||||
|
# CONFIG_BT_RTL=m
|
||||||
|
# CONFIG_BT_HCIBTUSB=m
|
||||||
|
# CONFIG_BT_HCIBTUSB_BCM=y
|
||||||
|
# CONFIG_BT_HCIBTUSB_RTL=y
|
||||||
|
# CONFIG_BT_HCIUART=m
|
||||||
|
# CONFIG_BT_HCIUART_SERDEV=y
|
||||||
|
# CONFIG_BT_HCIUART_H4=y
|
||||||
|
# CONFIG_BT_HCIUART_LL=y
|
||||||
|
# CONFIG_RTL_CARDS=m
|
||||||
|
# CONFIG_RTLWIFI=m
|
||||||
|
# CONFIG_RTLWIFI_PCI=m
|
||||||
|
# CONFIG_RTLWIFI_USB=m
|
||||||
|
# CONFIG_RTLWIFI_DEBUG=y
|
||||||
|
# CONFIG_RTL8723_COMMON=m
|
||||||
|
# CONFIG_RTLBTCOEXIST=m
|
||||||
|
# CONFIG_RTL8XXXU=m
|
||||||
|
# CONFIG_RTLLIB=m
|
||||||
|
# consider adding (from mobile-nixos):
|
||||||
|
# maybe: CONFIG_BT_HCIUART_3WIRE=y
|
||||||
|
# maybe: CONFIG_BT_HCIUART_RTL=y
|
||||||
|
# maybe: CONFIG_RTL8XXXU_UNTESTED=y
|
||||||
|
# consider adding (from manjaro):
|
||||||
|
# CONFIG_BT_6LOWPAN=m (not listed as option in nixos kernel)
|
||||||
|
# these are referenced in the rtl8723 source, but not known to config (and not in mobile-nixos config
|
||||||
|
# maybe: CONFIG_RTL_ODM_WLAN_DRIVER
|
||||||
|
# maybe: CONFIG_RTL_TRIBAND_SUPPORT
|
||||||
|
# maybe: CONFIG_SDIO_HCI
|
||||||
|
# maybe: CONFIG_USB_HCI
|
||||||
|
};
|
||||||
|
|
||||||
|
# create a kernelPatch which overrides nixos' defconfig with extra options
|
||||||
|
patchDefconfig = config: {
|
||||||
|
# defconfig options. this method comes from here:
|
||||||
|
# - https://discourse.nixos.org/t/the-correct-way-to-override-the-latest-kernel-config/533/9
|
||||||
|
name = "sane-moby-defconfig";
|
||||||
|
patch = null;
|
||||||
|
extraStructuredConfig = config;
|
||||||
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
# use Megi's kernel:
|
# use Megi's kernel:
|
||||||
@@ -52,7 +114,23 @@ in
|
|||||||
# - phone rotation sensor is off by 90 degrees
|
# - phone rotation sensor is off by 90 degrees
|
||||||
# - ambient light sensor causes screen brightness to be shakey
|
# - ambient light sensor causes screen brightness to be shakey
|
||||||
# - phosh greeter may not appear after wake from sleep
|
# - phosh greeter may not appear after wake from sleep
|
||||||
boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux-megous;
|
boot.kernelPackages = pkgs.cross.linuxPackagesFor pkgs.cross.linux-megous;
|
||||||
|
|
||||||
|
boot.kernelPatches = [
|
||||||
|
(patchDefconfig (kernelConfig //
|
||||||
|
(with lib.kernel; {
|
||||||
|
# disabling the sun5i_eink driver avoids this compilation error:
|
||||||
|
# CC [M] drivers/video/fbdev/sun5i-eink-neon.o
|
||||||
|
# aarch64-unknown-linux-gnu-gcc: error: unrecognized command line option '-mfloat-abi=softfp'
|
||||||
|
# aarch64-unknown-linux-gnu-gcc: error: unrecognized command line option '-mfpu=neon'
|
||||||
|
# make[3]: *** [../scripts/Makefile.build:289: drivers/video/fbdev/sun5i-eink-neon.o] Error 1
|
||||||
|
FB_SUN5I_EINK = no;
|
||||||
|
# used by the pinephone pro, but fails to compile with:
|
||||||
|
# ../drivers/media/i2c/ov8858.c:1834:27: error: implicit declaration of function 'compat_ptr'
|
||||||
|
VIDEO_OV8858 = no;
|
||||||
|
})
|
||||||
|
))
|
||||||
|
];
|
||||||
|
|
||||||
# alternatively, use nixos' kernel and add the stuff we want:
|
# alternatively, use nixos' kernel and add the stuff we want:
|
||||||
# # cross-compilation optimization:
|
# # cross-compilation optimization:
|
||||||
@@ -65,19 +143,4 @@ in
|
|||||||
# boot.kernelPatches = manjaroPatches ++ [
|
# boot.kernelPatches = manjaroPatches ++ [
|
||||||
# (patchDefconfig kernelConfig)
|
# (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 :-(
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
@@ -1,17 +0,0 @@
|
|||||||
{ sane-lib, ... }:
|
|
||||||
{
|
|
||||||
sane.gui.sxmo = {
|
|
||||||
settings = {
|
|
||||||
# touch screen
|
|
||||||
SXMO_LISGD_INPUT_DEVICE = "/dev/input/by-path/platform-1c2ac00.i2c-event";
|
|
||||||
# vol and power are detected correctly by upstream
|
|
||||||
|
|
||||||
# preferences
|
|
||||||
# N.B. some deviceprofiles explicitly set SXMO_SWAY_SCALE, overwriting what we put here.
|
|
||||||
SXMO_SWAY_SCALE = "1.5";
|
|
||||||
SXMO_ROTATION_GRAVITY = "12800";
|
|
||||||
DEFAULT_COUNTRY = "US";
|
|
||||||
BROWSWER = "librewolf";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,4 +1,4 @@
|
|||||||
{ pkgs, ... }:
|
{ config, pkgs, ... }:
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./fs.nix
|
./fs.nix
|
||||||
@@ -7,8 +7,6 @@
|
|||||||
boot.loader.generic-extlinux-compatible.enable = true;
|
boot.loader.generic-extlinux-compatible.enable = true;
|
||||||
boot.loader.efi.canTouchEfiVariables = false;
|
boot.loader.efi.canTouchEfiVariables = false;
|
||||||
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
||||||
# sane.persist.enable = false; # TODO: disable (but run `nix flake check` to ensure it works!)
|
|
||||||
sane.nixcache.enable = false; # don't want to be calling out to dead machines that we're *trying* to rescue
|
|
||||||
|
|
||||||
# docs: https://nixos.org/manual/nixos/stable/options.html#opt-system.stateVersion
|
# docs: https://nixos.org/manual/nixos/stable/options.html#opt-system.stateVersion
|
||||||
system.stateVersion = "21.05";
|
system.stateVersion = "21.05";
|
||||||
|
@@ -4,23 +4,19 @@
|
|||||||
imports = [
|
imports = [
|
||||||
./fs.nix
|
./fs.nix
|
||||||
./net.nix
|
./net.nix
|
||||||
|
./secrets.nix
|
||||||
./services
|
./services
|
||||||
];
|
];
|
||||||
|
|
||||||
sane.programs = {
|
sane.packages.extraUserPkgs = with pkgs; [
|
||||||
# for administering services
|
# for administering services
|
||||||
freshrss.enableFor.user.colin = true;
|
freshrss
|
||||||
matrix-synapse.enableFor.user.colin = true;
|
matrix-synapse
|
||||||
signaldctl.enableFor.user.colin = true;
|
signaldctl
|
||||||
};
|
];
|
||||||
|
sane.persist.enable = true;
|
||||||
sane.roles.ac = true;
|
|
||||||
sane.roles.build-machine.enable = true;
|
|
||||||
sane.roles.build-machine.emulation = false;
|
|
||||||
sane.zsh.showDeadlines = false; # ~/knowledge doesn't always exist
|
|
||||||
sane.services.dyn-dns.enable = true;
|
sane.services.dyn-dns.enable = true;
|
||||||
sane.services.wg-home.enable = true;
|
sane.services.wg-home.enable = true;
|
||||||
sane.services.wg-home.enableWan = true;
|
|
||||||
sane.services.wg-home.ip = config.sane.hosts.by-name."servo".wg-home.ip;
|
sane.services.wg-home.ip = config.sane.hosts.by-name."servo".wg-home.ip;
|
||||||
# sane.services.duplicity.enable = true; # TODO: re-enable after HW upgrade
|
# sane.services.duplicity.enable = true; # TODO: re-enable after HW upgrade
|
||||||
|
|
||||||
|
@@ -3,12 +3,6 @@
|
|||||||
{
|
{
|
||||||
networking.domain = "uninsane.org";
|
networking.domain = "uninsane.org";
|
||||||
|
|
||||||
sane.ports.openFirewall = true;
|
|
||||||
sane.ports.openUpnp = true;
|
|
||||||
|
|
||||||
# view refused packets with: `sudo journalctl -k`
|
|
||||||
# networking.firewall.logRefusedPackets = true;
|
|
||||||
|
|
||||||
# The global useDHCP flag is deprecated, therefore explicitly set to false here.
|
# The global useDHCP flag is deprecated, therefore explicitly set to false here.
|
||||||
# Per-interface useDHCP will be mandatory in the future, so this generated config
|
# Per-interface useDHCP will be mandatory in the future, so this generated config
|
||||||
# replicates the default behaviour.
|
# replicates the default behaviour.
|
||||||
@@ -17,6 +11,9 @@
|
|||||||
# XXX colin: probably don't need this. wlan0 won't be populated unless i touch a value in networking.interfaces.wlan0
|
# XXX colin: probably don't need this. wlan0 won't be populated unless i touch a value in networking.interfaces.wlan0
|
||||||
networking.wireless.enable = false;
|
networking.wireless.enable = false;
|
||||||
|
|
||||||
|
# networking.firewall.enable = false;
|
||||||
|
networking.firewall.enable = true;
|
||||||
|
|
||||||
# this is needed to forward packets from the VPN to the host
|
# this is needed to forward packets from the VPN to the host
|
||||||
boot.kernel.sysctl."net.ipv4.ip_forward" = 1;
|
boot.kernel.sysctl."net.ipv4.ip_forward" = 1;
|
||||||
|
|
||||||
@@ -36,14 +33,6 @@
|
|||||||
# - getent ahostsv4 www.google.com
|
# - getent ahostsv4 www.google.com
|
||||||
# - try fix: <https://serverfault.com/questions/765989/connect-to-3rd-party-vpn-server-but-dont-use-it-as-the-default-route/766290#766290>
|
# - try fix: <https://serverfault.com/questions/765989/connect-to-3rd-party-vpn-server-but-dont-use-it-as-the-default-route/766290#766290>
|
||||||
services.resolved.enable = true;
|
services.resolved.enable = true;
|
||||||
# without DNSSEC:
|
|
||||||
# - dig matrix.org => works
|
|
||||||
# - curl https://matrix.org => works
|
|
||||||
# with default DNSSEC:
|
|
||||||
# - dig matrix.org => works
|
|
||||||
# - curl https://matrix.org => fails
|
|
||||||
# i don't know why. this might somehow be interfering with the DNS run on this device (trust-dns)
|
|
||||||
services.resolved.dnssec = "false";
|
|
||||||
networking.nameservers = [
|
networking.nameservers = [
|
||||||
# use systemd-resolved resolver
|
# use systemd-resolved resolver
|
||||||
# full resolver (which understands /etc/hosts) lives on 127.0.0.53
|
# full resolver (which understands /etc/hosts) lives on 127.0.0.53
|
||||||
@@ -156,9 +145,9 @@
|
|||||||
|
|
||||||
# we also bridge DNS traffic
|
# we also bridge DNS traffic
|
||||||
${in-ns} ${iptables} -A PREROUTING -t nat -p udp --dport 53 -m iprange --dst-range ${vpn-ip} \
|
${in-ns} ${iptables} -A PREROUTING -t nat -p udp --dport 53 -m iprange --dst-range ${vpn-ip} \
|
||||||
-j DNAT --to-destination ${veth-host-ip}
|
-j DNAT --to-destination ${veth-host-ip}:53
|
||||||
${in-ns} ${iptables} -A PREROUTING -t nat -p tcp --dport 53 -m iprange --dst-range ${vpn-ip} \
|
${in-ns} ${iptables} -A PREROUTING -t nat -p tcp --dport 53 -m iprange --dst-range ${vpn-ip} \
|
||||||
-j DNAT --to-destination ${veth-host-ip}
|
-j DNAT --to-destination ${veth-host-ip}:53
|
||||||
|
|
||||||
# in order to access DNS in this netns, we need to route it to the VPN's nameservers
|
# in order to access DNS in this netns, we need to route it to the VPN's nameservers
|
||||||
# - alternatively, we could fix DNS servers like 1.1.1.1.
|
# - alternatively, we could fix DNS servers like 1.1.1.1.
|
||||||
|
41
hosts/by-name/servo/secrets.nix
Normal file
41
hosts/by-name/servo/secrets.nix
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
{ ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
sops.secrets."ddns_afraid" = {
|
||||||
|
sopsFile = ../../../secrets/servo.yaml;
|
||||||
|
};
|
||||||
|
sops.secrets."ddns_he" = {
|
||||||
|
sopsFile = ../../../secrets/servo.yaml;
|
||||||
|
};
|
||||||
|
|
||||||
|
sops.secrets."dovecot_passwd" = {
|
||||||
|
sopsFile = ../../../secrets/servo.yaml;
|
||||||
|
};
|
||||||
|
|
||||||
|
sops.secrets."duplicity_passphrase" = {
|
||||||
|
sopsFile = ../../../secrets/servo.yaml;
|
||||||
|
};
|
||||||
|
|
||||||
|
sops.secrets."freshrss_passwd" = {
|
||||||
|
sopsFile = ../../../secrets/servo.yaml;
|
||||||
|
};
|
||||||
|
|
||||||
|
sops.secrets."matrix_synapse_secrets" = {
|
||||||
|
sopsFile = ../../../secrets/servo.yaml;
|
||||||
|
};
|
||||||
|
sops.secrets."mautrix_signal_env" = {
|
||||||
|
sopsFile = ../../../secrets/servo/mautrix_signal_env.bin;
|
||||||
|
};
|
||||||
|
|
||||||
|
sops.secrets."mediawiki_pw" = {
|
||||||
|
sopsFile = ../../../secrets/servo.yaml;
|
||||||
|
};
|
||||||
|
|
||||||
|
sops.secrets."pleroma_secrets" = {
|
||||||
|
sopsFile = ../../../secrets/servo.yaml;
|
||||||
|
};
|
||||||
|
|
||||||
|
sops.secrets."wg_ovpns_privkey" = {
|
||||||
|
sopsFile = ../../../secrets/servo.yaml;
|
||||||
|
};
|
||||||
|
}
|
@@ -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"; directory = 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";
|
|
||||||
}
|
|
@@ -6,7 +6,7 @@ lib.mkIf false
|
|||||||
systemd.services.ddns-afraid = {
|
systemd.services.ddns-afraid = {
|
||||||
description = "update dynamic DNS entries for freedns.afraid.org";
|
description = "update dynamic DNS entries for freedns.afraid.org";
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
EnvironmentFile = config.sops.secrets."ddns_afraid.env".path;
|
EnvironmentFile = config.sops.secrets.ddns_afraid.path;
|
||||||
# TODO: ProtectSystem = "strict";
|
# TODO: ProtectSystem = "strict";
|
||||||
# TODO: ProtectHome = "full";
|
# TODO: ProtectHome = "full";
|
||||||
# TODO: PrivateTmp = true;
|
# TODO: PrivateTmp = true;
|
||||||
|
@@ -6,7 +6,7 @@ lib.mkIf false
|
|||||||
systemd.services.ddns-he = {
|
systemd.services.ddns-he = {
|
||||||
description = "update dynamic DNS entries for HurricaneElectric";
|
description = "update dynamic DNS entries for HurricaneElectric";
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
EnvironmentFile = config.sops.secrets."ddns_he.env".path;
|
EnvironmentFile = config.sops.secrets.ddns_he.path;
|
||||||
# TODO: ProtectSystem = "strict";
|
# TODO: ProtectSystem = "strict";
|
||||||
# TODO: ProtectHome = "full";
|
# TODO: ProtectHome = "full";
|
||||||
# TODO: PrivateTmp = true;
|
# TODO: PrivateTmp = true;
|
||||||
|
@@ -1,28 +1,22 @@
|
|||||||
{ ... }:
|
{ ... }:
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./calibre.nix
|
|
||||||
./ddns-afraid.nix
|
./ddns-afraid.nix
|
||||||
./ddns-he.nix
|
./ddns-he.nix
|
||||||
./email
|
|
||||||
./ejabberd.nix
|
./ejabberd.nix
|
||||||
./freshrss.nix
|
./freshrss.nix
|
||||||
./ftp
|
|
||||||
./gitea.nix
|
./gitea.nix
|
||||||
./goaccess.nix
|
./goaccess.nix
|
||||||
./ipfs.nix
|
./ipfs.nix
|
||||||
./jackett.nix
|
./jackett.nix
|
||||||
./jellyfin.nix
|
./jellyfin.nix
|
||||||
./kiwix-serve.nix
|
./kiwix-serve.nix
|
||||||
./komga.nix
|
|
||||||
./lemmy.nix
|
|
||||||
./matrix
|
./matrix
|
||||||
./navidrome.nix
|
./navidrome.nix
|
||||||
./nfs.nix
|
|
||||||
./nixserve.nix
|
./nixserve.nix
|
||||||
./nginx.nix
|
./nginx.nix
|
||||||
./pict-rs.nix
|
|
||||||
./pleroma.nix
|
./pleroma.nix
|
||||||
|
./postfix.nix
|
||||||
./postgres.nix
|
./postgres.nix
|
||||||
./prosody.nix
|
./prosody.nix
|
||||||
./transmission.nix
|
./transmission.nix
|
||||||
|
@@ -22,67 +22,27 @@
|
|||||||
sane.persist.sys.plaintext = [
|
sane.persist.sys.plaintext = [
|
||||||
{ user = "ejabberd"; group = "ejabberd"; directory = "/var/lib/ejabberd"; }
|
{ user = "ejabberd"; group = "ejabberd"; directory = "/var/lib/ejabberd"; }
|
||||||
];
|
];
|
||||||
sane.ports.ports."3478" = {
|
networking.firewall.allowedTCPPorts = [
|
||||||
protocol = [ "tcp" "udp" ];
|
3478 # STUN/TURN
|
||||||
visibleTo.lan = true;
|
5222 # XMPP client -> server
|
||||||
visibleTo.wan = true;
|
5223 # XMPPS client -> server (XMPP over TLS)
|
||||||
description = "colin-xmpp-stun-turn";
|
5269 # XMPP server -> server
|
||||||
};
|
5270 # XMPPS server -> server (XMPP over TLS)
|
||||||
sane.ports.ports."5222" = {
|
5280 # bosh
|
||||||
protocol = [ "tcp" ];
|
5281 # bosh (https) ??
|
||||||
visibleTo.lan = true;
|
5349 # STUN/TURN (TLS)
|
||||||
visibleTo.wan = true;
|
5443 # web services (file uploads, websockets, admin)
|
||||||
description = "colin-xmpp-client-to-server";
|
];
|
||||||
};
|
networking.firewall.allowedUDPPorts = [
|
||||||
sane.ports.ports."5223" = {
|
3478 # STUN/TURN
|
||||||
protocol = [ "tcp" ];
|
];
|
||||||
visibleTo.lan = true;
|
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-xmpps-client-to-server"; # XMPP over TLS
|
|
||||||
};
|
|
||||||
sane.ports.ports."5269" = {
|
|
||||||
protocol = [ "tcp" ];
|
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-xmpp-server-to-server";
|
|
||||||
};
|
|
||||||
sane.ports.ports."5270" = {
|
|
||||||
protocol = [ "tcp" ];
|
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-xmpps-server-to-server"; # XMPP over TLS
|
|
||||||
};
|
|
||||||
sane.ports.ports."5280" = {
|
|
||||||
protocol = [ "tcp" ];
|
|
||||||
visibleTo.lan = true;
|
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-xmpp-bosh";
|
|
||||||
};
|
|
||||||
sane.ports.ports."5281" = {
|
|
||||||
protocol = [ "tcp" ];
|
|
||||||
visibleTo.lan = true;
|
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-xmpp-bosh-https";
|
|
||||||
};
|
|
||||||
sane.ports.ports."5349" = {
|
|
||||||
protocol = [ "tcp" ];
|
|
||||||
visibleTo.lan = true;
|
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-xmpp-stun-turn-over-tls";
|
|
||||||
};
|
|
||||||
sane.ports.ports."5443" = {
|
|
||||||
protocol = [ "tcp" ];
|
|
||||||
visibleTo.lan = true;
|
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-xmpp-web-services"; # file uploads, websockets, admin
|
|
||||||
};
|
|
||||||
|
|
||||||
# TODO: forward these TURN ports!
|
|
||||||
networking.firewall.allowedTCPPortRanges = [{
|
networking.firewall.allowedTCPPortRanges = [{
|
||||||
from = 49152; # TURN
|
from = 49152; # TURN
|
||||||
to = 49408;
|
to = 65535;
|
||||||
}];
|
}];
|
||||||
networking.firewall.allowedUDPPortRanges = [{
|
networking.firewall.allowedUDPPortRanges = [{
|
||||||
from = 49152; # TURN
|
from = 49152; # TURN
|
||||||
to = 49408;
|
to = 65535;
|
||||||
}];
|
}];
|
||||||
|
|
||||||
# provide access to certs
|
# provide access to certs
|
||||||
@@ -115,9 +75,9 @@
|
|||||||
useACMEHost = "uninsane.org";
|
useACMEHost = "uninsane.org";
|
||||||
};
|
};
|
||||||
|
|
||||||
sane.dns.zones."uninsane.org".inet = {
|
sane.services.trust-dns.zones."uninsane.org".inet = {
|
||||||
# XXX: SRV records have to point to something with a A/AAAA record; no CNAMEs
|
# XXX: SRV records have to point to something with a A/AAAA record; no CNAMEs
|
||||||
A."xmpp" = "%ANATIVE%";
|
A."xmpp" = "%NATIVE%";
|
||||||
CNAME."muc.xmpp" = "xmpp";
|
CNAME."muc.xmpp" = "xmpp";
|
||||||
CNAME."pubsub.xmpp" = "xmpp";
|
CNAME."pubsub.xmpp" = "xmpp";
|
||||||
CNAME."upload.xmpp" = "xmpp";
|
CNAME."upload.xmpp" = "xmpp";
|
||||||
@@ -274,7 +234,7 @@
|
|||||||
use_turn: true
|
use_turn: true
|
||||||
turn_min_port: 49152
|
turn_min_port: 49152
|
||||||
turn_max_port: 65535
|
turn_max_port: 65535
|
||||||
turn_ipv4_address: %ANATIVE%
|
turn_ipv4_address: %NATIVE%
|
||||||
-
|
-
|
||||||
# STUN+TURN UDP
|
# STUN+TURN UDP
|
||||||
port: 3478
|
port: 3478
|
||||||
@@ -283,7 +243,7 @@
|
|||||||
use_turn: true
|
use_turn: true
|
||||||
turn_min_port: 49152
|
turn_min_port: 49152
|
||||||
turn_max_port: 65535
|
turn_max_port: 65535
|
||||||
turn_ipv4_address: %ANATIVE%
|
turn_ipv4_address: %NATIVE%
|
||||||
-
|
-
|
||||||
# STUN+TURN TLS over TCP
|
# STUN+TURN TLS over TCP
|
||||||
port: 5349
|
port: 5349
|
||||||
@@ -294,7 +254,7 @@
|
|||||||
use_turn: true
|
use_turn: true
|
||||||
turn_min_port: 49152
|
turn_min_port: 49152
|
||||||
turn_max_port: 65535
|
turn_max_port: 65535
|
||||||
turn_ipv4_address: %ANATIVE%
|
turn_ipv4_address: %NATIVE%
|
||||||
|
|
||||||
# TODO: enable mod_fail2ban
|
# TODO: enable mod_fail2ban
|
||||||
# TODO(low): look into mod_http_fileserver for serving macros?
|
# TODO(low): look into mod_http_fileserver for serving macros?
|
||||||
@@ -427,7 +387,7 @@
|
|||||||
# config is 444 (not 644), so we want to write out-of-place and then atomically move
|
# config is 444 (not 644), so we want to write out-of-place and then atomically move
|
||||||
# TODO: factor this out into `sane-woop` helper?
|
# TODO: factor this out into `sane-woop` helper?
|
||||||
rm -f /var/lib/ejabberd/ejabberd.yaml.new
|
rm -f /var/lib/ejabberd/ejabberd.yaml.new
|
||||||
${sed} "s/%ANATIVE%/$ip/" ${config-in} > /var/lib/ejabberd/ejabberd.yaml.new
|
${sed} "s/%NATIVE%/$ip/" ${config-in} > /var/lib/ejabberd/ejabberd.yaml.new
|
||||||
mv /var/lib/ejabberd/ejabberd.yaml{.new,}
|
mv /var/lib/ejabberd/ejabberd.yaml{.new,}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
@@ -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;
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
@@ -59,5 +59,5 @@
|
|||||||
# the routing is handled by services.freshrss.virtualHost
|
# the routing is handled by services.freshrss.virtualHost
|
||||||
};
|
};
|
||||||
|
|
||||||
sane.dns.zones."uninsane.org".inet.CNAME."rss" = "native";
|
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."rss" = "native";
|
||||||
}
|
}
|
||||||
|
@@ -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,4 +1,3 @@
|
|||||||
# config options: <https://docs.gitea.io/en-us/administration/config-cheat-sheet/>
|
|
||||||
{ config, pkgs, lib, ... }:
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -11,6 +10,9 @@
|
|||||||
services.gitea.database.type = "postgres";
|
services.gitea.database.type = "postgres";
|
||||||
services.gitea.database.user = "git";
|
services.gitea.database.user = "git";
|
||||||
services.gitea.appName = "Perfectly Sane Git";
|
services.gitea.appName = "Perfectly Sane Git";
|
||||||
|
services.gitea.domain = "git.uninsane.org";
|
||||||
|
services.gitea.rootUrl = "https://git.uninsane.org/";
|
||||||
|
services.gitea.settings.session.COOKIE_SECURE = true;
|
||||||
# services.gitea.disableRegistration = true;
|
# services.gitea.disableRegistration = true;
|
||||||
|
|
||||||
# gitea doesn't create the git user
|
# gitea doesn't create the git user
|
||||||
@@ -25,13 +27,9 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
services.gitea.settings = {
|
services.gitea.settings = {
|
||||||
# options: "Trace", "Debug", "Info", "Warn", "Error", "Critical"
|
|
||||||
log.LEVEL = "Warn";
|
|
||||||
server = {
|
server = {
|
||||||
# options: "home", "explore", "organizations", "login" or URL fragment (or full URL)
|
# options: "home", "explore", "organizations", "login" or URL fragment (or full URL)
|
||||||
LANDING_PAGE = "explore";
|
LANDING_PAGE = "explore";
|
||||||
DOMAIN = "git.uninsane.org";
|
|
||||||
ROOT_URL = "https://git.uninsane.org/";
|
|
||||||
};
|
};
|
||||||
service = {
|
service = {
|
||||||
# timeout for email approval. 5760 = 4 days
|
# timeout for email approval. 5760 = 4 days
|
||||||
@@ -46,7 +44,6 @@
|
|||||||
ENABLE_CAPTCHA = true;
|
ENABLE_CAPTCHA = true;
|
||||||
NOREPLY_ADDRESS = "noreply.anonymous.git@uninsane.org";
|
NOREPLY_ADDRESS = "noreply.anonymous.git@uninsane.org";
|
||||||
};
|
};
|
||||||
session.COOKIE_SECURE = true;
|
|
||||||
repository = {
|
repository = {
|
||||||
DEFAULT_BRANCH = "master";
|
DEFAULT_BRANCH = "master";
|
||||||
};
|
};
|
||||||
@@ -61,8 +58,6 @@
|
|||||||
};
|
};
|
||||||
#"ui.meta" = ... to customize html author/description/etc
|
#"ui.meta" = ... to customize html author/description/etc
|
||||||
mailer = {
|
mailer = {
|
||||||
# alternative is to use nixos-level config:
|
|
||||||
# services.gitea.mailerPasswordFile = ...
|
|
||||||
ENABLED = true;
|
ENABLED = true;
|
||||||
MAILER_TYPE = "sendmail";
|
MAILER_TYPE = "sendmail";
|
||||||
FROM = "notify.git@uninsane.org";
|
FROM = "notify.git@uninsane.org";
|
||||||
@@ -74,6 +69,8 @@
|
|||||||
FORMAT = "RFC3339";
|
FORMAT = "RFC3339";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
# options: "Trace", "Debug", "Info", "Warn", "Error", "Critical"
|
||||||
|
services.gitea.settings.log.LEVEL = "Warn";
|
||||||
|
|
||||||
systemd.services.gitea.serviceConfig = {
|
systemd.services.gitea.serviceConfig = {
|
||||||
# nix default is AF_UNIX AF_INET AF_INET6.
|
# nix default is AF_UNIX AF_INET AF_INET6.
|
||||||
@@ -98,12 +95,5 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
sane.dns.zones."uninsane.org".inet.CNAME."git" = "native";
|
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."git" = "native";
|
||||||
|
|
||||||
sane.ports.ports."22" = {
|
|
||||||
protocol = [ "tcp" ];
|
|
||||||
visibleTo.lan = true;
|
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-git@git.uninsane.org";
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
@@ -64,5 +64,5 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
sane.dns.zones."uninsane.org".inet.CNAME."sink" = "native";
|
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."sink" = "native";
|
||||||
}
|
}
|
||||||
|
@@ -34,7 +34,7 @@ lib.mkIf false # i don't actively use ipfs anymore
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
sane.dns.zones."uninsane.org".inet.CNAME."ipfs" = "native";
|
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."ipfs" = "native";
|
||||||
|
|
||||||
# services.ipfs.enable = true;
|
# services.ipfs.enable = true;
|
||||||
services.kubo.localDiscovery = true;
|
services.kubo.localDiscovery = true;
|
||||||
|
@@ -24,10 +24,9 @@
|
|||||||
locations."/" = {
|
locations."/" = {
|
||||||
# proxyPass = "http://ovpns.uninsane.org:9117";
|
# proxyPass = "http://ovpns.uninsane.org:9117";
|
||||||
proxyPass = "http://10.0.1.6:9117";
|
proxyPass = "http://10.0.1.6:9117";
|
||||||
recommendedProxySettings = true;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
sane.dns.zones."uninsane.org".inet.CNAME."jackett" = "native";
|
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."jackett" = "native";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,76 +1,16 @@
|
|||||||
# 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, ... }:
|
{ config, lib, ... }:
|
||||||
|
|
||||||
|
# TODO: re-enable after migrating media dir to /var/lib/uninsane/media
|
||||||
|
# else it's too spammy
|
||||||
|
lib.mkIf false
|
||||||
{
|
{
|
||||||
# https://jellyfin.org/docs/general/networking/index.html
|
networking.firewall.allowedUDPPorts = [
|
||||||
sane.ports.ports."1900" = {
|
1900 7359 # DLNA: https://jellyfin.org/docs/general/networking/index.html
|
||||||
protocol = [ "udp" ];
|
];
|
||||||
visibleTo.lan = true;
|
sane.persist.sys.plaintext = [
|
||||||
description = "colin-upnp-for-jellyfin";
|
# TODO: mode? could be more granular
|
||||||
};
|
{ user = "jellyfin"; group = "jellyfin"; directory = "/var/lib/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"; directory = "/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
|
# Jellyfin multimedia server
|
||||||
# this is mostly taken from the official jellfin.org docs
|
# this is mostly taken from the official jellfin.org docs
|
||||||
@@ -121,7 +61,7 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
sane.dns.zones."uninsane.org".inet.CNAME."jelly" = "native";
|
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."jelly" = "native";
|
||||||
|
|
||||||
services.jellyfin.enable = true;
|
services.jellyfin.enable = true;
|
||||||
}
|
}
|
||||||
|
@@ -13,5 +13,5 @@
|
|||||||
locations."/".proxyPass = "http://127.0.0.1:8013";
|
locations."/".proxyPass = "http://127.0.0.1:8013";
|
||||||
};
|
};
|
||||||
|
|
||||||
sane.dns.zones."uninsane.org".inet.CNAME."w" = "native";
|
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."w" = "native";
|
||||||
}
|
}
|
||||||
|
@@ -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"; directory = 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,15 +1,17 @@
|
|||||||
# docs: <https://nixos.wiki/wiki/Matrix>
|
# docs: https://nixos.wiki/wiki/Matrix
|
||||||
# docs: <https://nixos.org/manual/nixos/stable/index.html#module-services-matrix-synapse>
|
# docs: https://nixos.org/manual/nixos/stable/index.html#module-services-matrix-synapse
|
||||||
# example config: <https://github.com/matrix-org/synapse/blob/develop/docs/sample_config.yaml>
|
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./discord-puppet.nix
|
./discord-puppet.nix
|
||||||
./irc.nix
|
# ./irc.nix
|
||||||
./signal.nix
|
./signal.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
|
# allow synapse to read the registration files of its appservices
|
||||||
|
users.users.matrix-synapse.extraGroups = [ "mautrix-signal" ];
|
||||||
|
|
||||||
sane.persist.sys.plaintext = [
|
sane.persist.sys.plaintext = [
|
||||||
{ user = "matrix-synapse"; group = "matrix-synapse"; directory = "/var/lib/matrix-synapse"; }
|
{ user = "matrix-synapse"; group = "matrix-synapse"; directory = "/var/lib/matrix-synapse"; }
|
||||||
];
|
];
|
||||||
@@ -42,14 +44,11 @@
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
services.matrix-synapse.settings.x_forwarded = true; # because we proxy matrix behind nginx
|
|
||||||
services.matrix-synapse.settings.max_upload_size = "100M"; # default is "50M"
|
|
||||||
|
|
||||||
services.matrix-synapse.settings.admin_contact = "admin.matrix@uninsane.org";
|
services.matrix-synapse.settings.admin_contact = "admin.matrix@uninsane.org";
|
||||||
services.matrix-synapse.settings.registrations_require_3pid = [ "email" ];
|
services.matrix-synapse.settings.registrations_require_3pid = [ "email" ];
|
||||||
|
|
||||||
services.matrix-synapse.extraConfigFiles = [
|
services.matrix-synapse.extraConfigFiles = [
|
||||||
config.sops.secrets."matrix_synapse_secrets.yaml".path
|
config.sops.secrets.matrix_synapse_secrets.path
|
||||||
];
|
];
|
||||||
|
|
||||||
# services.matrix-synapse.extraConfigFiles = [builtins.toFile "matrix-synapse-extra-config" ''
|
# services.matrix-synapse.extraConfigFiles = [builtins.toFile "matrix-synapse-extra-config" ''
|
||||||
@@ -98,10 +97,6 @@
|
|||||||
|
|
||||||
locations."/" = {
|
locations."/" = {
|
||||||
proxyPass = "http://127.0.0.1:8008";
|
proxyPass = "http://127.0.0.1:8008";
|
||||||
extraConfig = ''
|
|
||||||
# allow uploading large files (matrix enforces a separate limit, downstream)
|
|
||||||
client_max_body_size 512m;
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
# redirect browsers to the web client.
|
# redirect browsers to the web client.
|
||||||
# i don't think native matrix clients ever fetch the root.
|
# i don't think native matrix clients ever fetch the root.
|
||||||
@@ -132,13 +127,13 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
sane.dns.zones."uninsane.org".inet = {
|
sane.services.trust-dns.zones."uninsane.org".inet = {
|
||||||
CNAME."matrix" = "native";
|
CNAME."matrix" = "native";
|
||||||
CNAME."web.matrix" = "native";
|
CNAME."web.matrix" = "native";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
sops.secrets."matrix_synapse_secrets.yaml" = {
|
sops.secrets."matrix_synapse_secrets" = {
|
||||||
owner = config.users.users.matrix-synapse.name;
|
owner = config.users.users.matrix-synapse.name;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,4 @@
|
|||||||
{ lib, ... }:
|
{ lib, ... }:
|
||||||
|
|
||||||
# XXX mx-discord-puppet uses nodejs_14 which is EOL
|
|
||||||
# - mx-discord-puppet is abandoned upstream _and_ in nixpkgs
|
|
||||||
# - recommended to use mautrix-discord: <https://github.com/NixOS/nixpkgs/pull/200462>
|
|
||||||
lib.mkIf false
|
|
||||||
{
|
{
|
||||||
sane.persist.sys.plaintext = [
|
sane.persist.sys.plaintext = [
|
||||||
{ user = "matrix-synapse"; group = "matrix-synapse"; directory = "/var/lib/mx-puppet-discord"; }
|
{ user = "matrix-synapse"; group = "matrix-synapse"; directory = "/var/lib/mx-puppet-discord"; }
|
||||||
|
@@ -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,58 +1,56 @@
|
|||||||
# config docs:
|
|
||||||
# - <https://github.com/matrix-org/matrix-appservice-irc/blob/develop/config.sample.yaml>
|
|
||||||
# TODO: /quit message for bridged users reveals to IRC users that i'm using a bridge;
|
|
||||||
# probably want to remove that.
|
|
||||||
{ config, lib, ... }:
|
{ config, lib, ... }:
|
||||||
|
|
||||||
let
|
{
|
||||||
ircServer = { name, additionalAddresses ? [], sasl ? true }: let
|
sane.persist.sys.plaintext = [
|
||||||
lowerName = lib.toLower name;
|
# TODO: mode?
|
||||||
in {
|
# user and group are both "matrix-appservice-irc"
|
||||||
# XXX sasl: appservice doesn't support NickServ identification (only SASL, or PASS if sasl = false)
|
{ user = "993"; group = "992"; directory = "/var/lib/matrix-appservice-irc"; }
|
||||||
inherit name additionalAddresses sasl;
|
];
|
||||||
port = 6697;
|
|
||||||
|
services.matrix-synapse.settings.app_service_config_files = [
|
||||||
|
"/var/lib/matrix-appservice-irc/registration.yml" # auto-created by irc appservice
|
||||||
|
];
|
||||||
|
|
||||||
|
# note: Rizon allows only FOUR simultaneous IRC connections per IP: https://wiki.rizon.net/index.php?title=Connection/Session_Limit_Exemptions
|
||||||
|
# Rizon supports CertFP for auth: https://wiki.rizon.net/index.php?title=CertFP
|
||||||
|
services.matrix-appservice-irc.enable = true;
|
||||||
|
services.matrix-appservice-irc.registrationUrl = "http://127.0.0.1:8009";
|
||||||
|
# settings documented here: https://github.com/matrix-org/matrix-appservice-irc/blob/develop/config.sample.yaml
|
||||||
|
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.rizon.net" = {
|
||||||
|
name = "Rizon";
|
||||||
|
port = 6697; # SSL port
|
||||||
ssl = true;
|
ssl = true;
|
||||||
|
sasl = true; # appservice doesn't support NickServ identification
|
||||||
botConfig = {
|
botConfig = {
|
||||||
# bot has no presence in IRC channel; only real Matrix users
|
# bot has no presence in IRC channel; only real Matrix users
|
||||||
enabled = false;
|
enabled = false;
|
||||||
# this is the IRC username/nickname *of the bot* (not visible in channels): not of the end-user.
|
# nick = "UninsaneDotOrg";
|
||||||
# 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";
|
nick = "uninsane";
|
||||||
username = "uninsane";
|
username = "uninsane";
|
||||||
joinChannelsIfNoUsers = false;
|
|
||||||
};
|
};
|
||||||
dynamicChannels = {
|
dynamicChannels = {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
aliasTemplate = "#irc_${lowerName}_$CHANNEL";
|
aliasTemplate = "#irc_rizon_$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 = {
|
ircClients = {
|
||||||
nickTemplate = "$LOCALPARTsane"; # @colin:uninsane.org (Matrix) -> colinsane (IRC)
|
nickTemplate = "$LOCALPARTsane";
|
||||||
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.
|
# by default, Matrix will convert messages greater than (3) lines into a pastebin-like URL to send to IRC.
|
||||||
lineLimit = 20;
|
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 = {
|
matrixClients = {
|
||||||
userTemplate = "@irc_${lowerName}_$NICK"; # the :uninsane.org part is appended automatically
|
userTemplate = "@irc_rizon_$NICK"; # the :uninsane.org part is appended automatically
|
||||||
};
|
};
|
||||||
|
|
||||||
# this will let this user message the appservice with `!join #<IRCChannel>` and the rest "Just Works"
|
# this will let this user message the appservice with `!join #<IRCChannel>` and the rest "Just Works"
|
||||||
@@ -71,9 +69,6 @@ let
|
|||||||
incremental = true;
|
incremental = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
ignoreIdleUsersOnStartup = {
|
|
||||||
enabled = false; # false => always bridge users, even if idle
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
# sync room description?
|
# sync room description?
|
||||||
bridgeInfoState = {
|
bridgeInfoState = {
|
||||||
@@ -81,88 +76,22 @@ let
|
|||||||
initial = true;
|
initial = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# hardcoded mappings, for when dynamicChannels fails us. TODO: probably safe to remove these.
|
||||||
|
# mappings = {
|
||||||
|
# "#chat" = {
|
||||||
|
# roomIds = [ "!GXJSOTdbtxRboGtDep:uninsane.org" ];
|
||||||
|
# };
|
||||||
|
# # BakaBT requires account registration, which i think means my user needs to be added before the appservice user
|
||||||
|
# "#BakaBT" = {
|
||||||
|
# roomIds = [ "!feZKttuYuHilqPFSkD:uninsane.org" ];
|
||||||
|
# };
|
||||||
|
# };
|
||||||
# for per-user IRC password:
|
# for per-user IRC password:
|
||||||
# - invite @irc_${lowerName}_NickServ:uninsane.org to a DM and type `help` => register
|
# invite @irc_rizon_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
|
# 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
|
# 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"; directory = "/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";
|
|
||||||
# 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";
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
@@ -7,9 +7,6 @@
|
|||||||
{ user = "signald"; group = "signald"; directory = "/var/lib/signald"; }
|
{ user = "signald"; group = "signald"; directory = "/var/lib/signald"; }
|
||||||
];
|
];
|
||||||
|
|
||||||
# allow synapse to read the registration file
|
|
||||||
users.users.matrix-synapse.extraGroups = [ "mautrix-signal" ];
|
|
||||||
|
|
||||||
services.signald.enable = true;
|
services.signald.enable = true;
|
||||||
services.mautrix-signal.enable = true;
|
services.mautrix-signal.enable = true;
|
||||||
services.mautrix-signal.environmentFile =
|
services.mautrix-signal.environmentFile =
|
||||||
@@ -30,6 +27,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
sops.secrets."mautrix_signal_env" = {
|
sops.secrets."mautrix_signal_env" = {
|
||||||
|
format = "binary";
|
||||||
mode = "0440";
|
mode = "0440";
|
||||||
owner = config.users.users.mautrix-signal.name;
|
owner = config.users.users.mautrix-signal.name;
|
||||||
group = config.users.users.matrix-synapse.name;
|
group = config.users.users.matrix-synapse.name;
|
||||||
|
@@ -36,5 +36,5 @@
|
|||||||
locations."/".proxyPass = "http://127.0.0.1:4533";
|
locations."/".proxyPass = "http://127.0.0.1:4533";
|
||||||
};
|
};
|
||||||
|
|
||||||
sane.dns.zones."uninsane.org".inet.CNAME."music" = "native";
|
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."music" = "native";
|
||||||
}
|
}
|
||||||
|
@@ -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" ];
|
|
||||||
};
|
|
||||||
}
|
|
@@ -13,19 +13,7 @@ let
|
|||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
|
||||||
sane.ports.ports."80" = {
|
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||||
protocol = [ "tcp" ];
|
|
||||||
visibleTo.lan = true;
|
|
||||||
visibleTo.wan = true;
|
|
||||||
visibleTo.ovpn = true; # so that letsencrypt can procure a cert for the mx record
|
|
||||||
description = "colin-http-uninsane.org";
|
|
||||||
};
|
|
||||||
sane.ports.ports."443" = {
|
|
||||||
protocol = [ "tcp" ];
|
|
||||||
visibleTo.lan = true;
|
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-https-uninsane.org";
|
|
||||||
};
|
|
||||||
|
|
||||||
services.nginx.enable = true;
|
services.nginx.enable = true;
|
||||||
services.nginx.appendConfig = ''
|
services.nginx.appendConfig = ''
|
||||||
|
@@ -14,8 +14,8 @@
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
sane.dns.zones."uninsane.org".inet.CNAME."nixcache" = "native";
|
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."nixcache" = "native";
|
||||||
|
|
||||||
sane.services.nixserve.enable = true;
|
sane.services.nixserve.enable = true;
|
||||||
sane.services.nixserve.secretKeyFile = config.sops.secrets.nix_serve_privkey.path;
|
sane.services.nixserve.sopsFile = ../../../../secrets/servo.yaml;
|
||||||
}
|
}
|
||||||
|
@@ -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"; directory = 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;
|
|
||||||
};
|
|
||||||
}
|
|
@@ -182,7 +182,7 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
sane.dns.zones."uninsane.org".inet.CNAME."fed" = "native";
|
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."fed" = "native";
|
||||||
|
|
||||||
sops.secrets."pleroma_secrets" = {
|
sops.secrets."pleroma_secrets" = {
|
||||||
owner = config.users.users.pleroma.name;
|
owner = config.users.users.pleroma.name;
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
# postfix config options: <https://www.postfix.org/postconf.5.html>
|
{ config, lib, ... }:
|
||||||
|
|
||||||
{ lib, pkgs, ... }:
|
|
||||||
|
|
||||||
let
|
let
|
||||||
submissionOptions = {
|
submissionOptions = {
|
||||||
@@ -28,32 +26,29 @@ in
|
|||||||
# "/var/lib/dovecot"
|
# "/var/lib/dovecot"
|
||||||
];
|
];
|
||||||
|
|
||||||
sane.ports.ports."25" = {
|
networking.firewall.allowedTCPPorts = [
|
||||||
protocol = [ "tcp" ];
|
25 # SMTP
|
||||||
visibleTo.ovpn = true;
|
143 # IMAP
|
||||||
description = "colin-smtp-mx.uninsane.org";
|
465 # SMTPS
|
||||||
};
|
587 # SMTPS/submission
|
||||||
sane.ports.ports."465" = {
|
993 # IMAPS
|
||||||
protocol = [ "tcp" ];
|
];
|
||||||
visibleTo.ovpn = true;
|
|
||||||
description = "colin-smtps-mx.uninsane.org";
|
|
||||||
};
|
|
||||||
sane.ports.ports."587" = {
|
|
||||||
protocol = [ "tcp" ];
|
|
||||||
visibleTo.ovpn = true;
|
|
||||||
description = "colin-smtps-submission-mx.uninsane.org";
|
|
||||||
};
|
|
||||||
|
|
||||||
|
# exists only to manage certs for dovecot
|
||||||
|
services.nginx.virtualHosts."imap.uninsane.org" = {
|
||||||
|
enableACME = true;
|
||||||
|
};
|
||||||
# exists only to manage certs for Postfix
|
# exists only to manage certs for Postfix
|
||||||
services.nginx.virtualHosts."mx.uninsane.org" = {
|
services.nginx.virtualHosts."mx.uninsane.org" = {
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
sane.dns.zones."uninsane.org".inet = {
|
sane.services.trust-dns.zones."uninsane.org".inet = {
|
||||||
MX."@" = "10 mx.uninsane.org.";
|
MX."@" = "10 mx.uninsane.org.";
|
||||||
# XXX: RFC's specify that the MX record CANNOT BE A CNAME
|
# XXX: RFC's specify that the MX record CANNOT BE A CNAME
|
||||||
A."mx" = "185.157.162.178";
|
A."mx" = "185.157.162.178";
|
||||||
|
CNAME."imap" = "native";
|
||||||
|
|
||||||
# Sender Policy Framework:
|
# Sender Policy Framework:
|
||||||
# +mx => mail passes if it originated from the MX
|
# +mx => mail passes if it originated from the MX
|
||||||
@@ -64,7 +59,7 @@ in
|
|||||||
|
|
||||||
# DKIM public key:
|
# DKIM public key:
|
||||||
TXT."mx._domainkey" =
|
TXT."mx._domainkey" =
|
||||||
"v=DKIM1;k=rsa;p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkSyMufc2KrRx3j17e/LyB+3eYSBRuEFT8PUka8EDX04QzCwDPdkwgnj3GNDvnB5Ktb05Cf2SJ/S1OLqNsINxJRWtkVfZd/C339KNh9wrukMKRKNELL9HLUw0bczOI4gKKFqyrRE9qm+4csCMAR79Te9FCjGV/jVnrkLdPT0GtFwIDAQAB"
|
"v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkSyMufc2KrRx3j17e/LyB+3eYSBRuEFT8PUka8EDX04QzCwDPdkwgnj3GNDvnB5Ktb05Cf2SJ/S1OLqNsINxJRWtkVfZd/C339KNh9wrukMKRKNELL9HLUw0bczOI4gKKFqyrRE9qm+4csCMAR79Te9FCjGV/jVnrkLdPT0GtFwIDAQAB"
|
||||||
;
|
;
|
||||||
|
|
||||||
# DMARC fields <https://datatracker.ietf.org/doc/html/rfc7489>:
|
# DMARC fields <https://datatracker.ietf.org/doc/html/rfc7489>:
|
||||||
@@ -97,40 +92,18 @@ in
|
|||||||
@uninsane.org colin
|
@uninsane.org colin
|
||||||
'';
|
'';
|
||||||
|
|
||||||
services.postfix.config = {
|
services.postfix.extraConfig = ''
|
||||||
# smtpd_milters = local:/run/opendkim/opendkim.sock
|
# smtpd_milters = local:/run/opendkim/opendkim.sock
|
||||||
# milter docs: http://www.postfix.org/MILTER_README.html
|
# milter docs: http://www.postfix.org/MILTER_README.html
|
||||||
# mail filters for receiving email and from authorized SMTP clients (i.e. via submission)
|
# mail filters for receiving email and authorized SMTP clients
|
||||||
# smtpd_milters = inet:185.157.162.190:8891
|
# smtpd_milters = inet:185.157.162.190:8891
|
||||||
# opendkim.sock will add a Authentication-Results header, with `dkim=pass|fail|...` value to received messages
|
smtpd_milters = unix:/run/opendkim/opendkim.sock
|
||||||
smtpd_milters = "unix:/run/opendkim/opendkim.sock";
|
|
||||||
# mail filters for sendmail
|
# mail filters for sendmail
|
||||||
non_smtpd_milters = "$smtpd_milters";
|
non_smtpd_milters = $smtpd_milters
|
||||||
|
milter_default_action = accept
|
||||||
# what to do when a milter exits unexpectedly:
|
inet_protocols = ipv4
|
||||||
milter_default_action = "accept";
|
smtp_tls_security_level = may
|
||||||
|
'';
|
||||||
inet_protocols = "ipv4";
|
|
||||||
smtp_tls_security_level = "may";
|
|
||||||
|
|
||||||
# hand received mail over to dovecot so that it can run sieves & such
|
|
||||||
mailbox_command = ''${pkgs.dovecot}/libexec/dovecot/dovecot-lda -f "$SENDER" -a "$RECIPIENT"'';
|
|
||||||
|
|
||||||
# hand received mail over to dovecot
|
|
||||||
# virtual_alias_maps = [
|
|
||||||
# "hash:/etc/postfix/virtual"
|
|
||||||
# ];
|
|
||||||
# mydestination = "";
|
|
||||||
# virtual_mailbox_domains = [ "localhost" "uninsane.org" ];
|
|
||||||
# # virtual_mailbox_maps = "hash:/etc/postfix/virtual";
|
|
||||||
# virtual_transport = "lmtp:unix:/run/dovecot2/dovecot-lmtp";
|
|
||||||
|
|
||||||
# anti-spam options: <https://www.postfix.org/SMTPD_ACCESS_README.html>
|
|
||||||
# reject_unknown_sender_domain: causes postfix to `dig <sender> MX` and make sure that exists.
|
|
||||||
# but may cause problems receiving mail from google & others who load-balance?
|
|
||||||
# - <https://unix.stackexchange.com/questions/592131/how-to-reject-email-from-unknown-domains-with-postfix-on-centos>
|
|
||||||
# smtpd_sender_restrictions = reject_unknown_sender_domain
|
|
||||||
};
|
|
||||||
|
|
||||||
services.postfix.enableSubmission = true;
|
services.postfix.enableSubmission = true;
|
||||||
services.postfix.submissionOptions = submissionOptions;
|
services.postfix.submissionOptions = submissionOptions;
|
||||||
@@ -145,8 +118,6 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#### OPENDKIM
|
|
||||||
|
|
||||||
services.opendkim.enable = true;
|
services.opendkim.enable = true;
|
||||||
# services.opendkim.domains = "csl:uninsane.org";
|
# services.opendkim.domains = "csl:uninsane.org";
|
||||||
services.opendkim.domains = "uninsane.org";
|
services.opendkim.domains = "uninsane.org";
|
||||||
@@ -170,6 +141,40 @@ in
|
|||||||
UMask = lib.mkForce "0011";
|
UMask = lib.mkForce "0011";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# inspired by https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/
|
||||||
|
services.dovecot2.enable = 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;
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
mail_debug = yes
|
||||||
|
auth_debug = yes
|
||||||
|
# verbose_ssl = yes
|
||||||
|
'';
|
||||||
|
|
||||||
#### OUTGOING MESSAGE REWRITING:
|
#### OUTGOING MESSAGE REWRITING:
|
||||||
services.postfix.enableHeaderChecks = true;
|
services.postfix.enableHeaderChecks = true;
|
||||||
@@ -191,4 +196,10 @@ in
|
|||||||
# pattern = "/^Subject:.*activate your account/";
|
# pattern = "/^Subject:.*activate your account/";
|
||||||
# }
|
# }
|
||||||
];
|
];
|
||||||
|
|
||||||
|
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";
|
||||||
|
};
|
||||||
}
|
}
|
@@ -12,29 +12,12 @@ lib.mkIf false
|
|||||||
sane.persist.sys.plaintext = [
|
sane.persist.sys.plaintext = [
|
||||||
{ user = "prosody"; group = "prosody"; directory = "/var/lib/prosody"; }
|
{ user = "prosody"; group = "prosody"; directory = "/var/lib/prosody"; }
|
||||||
];
|
];
|
||||||
sane.ports.ports."5222" = {
|
networking.firewall.allowedTCPPorts = [
|
||||||
protocol = [ "tcp" ];
|
5222 # XMPP client -> server
|
||||||
visibleTo.lan = true;
|
5269 # XMPP server -> server
|
||||||
visibleTo.wan = true;
|
5280 # bosh
|
||||||
description = "colin-xmpp-client-to-server";
|
5281 # Prosody HTTPS port (necessary?)
|
||||||
};
|
];
|
||||||
sane.ports.ports."5269" = {
|
|
||||||
protocol = [ "tcp" ];
|
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-xmpp-server-to-server";
|
|
||||||
};
|
|
||||||
sane.ports.ports."5280" = {
|
|
||||||
protocol = [ "tcp" ];
|
|
||||||
visibleTo.lan = true;
|
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-xmpp-bosh";
|
|
||||||
};
|
|
||||||
sane.ports.ports."5281" = {
|
|
||||||
protocol = [ "tcp" ];
|
|
||||||
visibleTo.lan = true;
|
|
||||||
visibleTo.wan = true;
|
|
||||||
description = "colin-xmpp-prosody-https"; # necessary?
|
|
||||||
};
|
|
||||||
|
|
||||||
# provide access to certs
|
# provide access to certs
|
||||||
users.users.prosody.extraGroups = [ "nginx" ];
|
users.users.prosody.extraGroups = [ "nginx" ];
|
||||||
|
@@ -27,7 +27,7 @@
|
|||||||
# units in kBps
|
# units in kBps
|
||||||
speed-limit-down = 3000;
|
speed-limit-down = 3000;
|
||||||
speed-limit-down-enabled = true;
|
speed-limit-down-enabled = true;
|
||||||
speed-limit-up = 600;
|
speed-limit-up = 300;
|
||||||
speed-limit-up-enabled = true;
|
speed-limit-up-enabled = true;
|
||||||
|
|
||||||
# see: https://git.zknt.org/mirror/transmission/commit/cfce6e2e3a9b9d31a9dafedd0bdc8bf2cdb6e876?lang=bg-BG
|
# see: https://git.zknt.org/mirror/transmission/commit/cfce6e2e3a9b9d31a9dafedd0bdc8bf2cdb6e876?lang=bg-BG
|
||||||
@@ -75,6 +75,6 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
sane.dns.zones."uninsane.org".inet.CNAME."bt" = "native";
|
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."bt" = "native";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
{ config, lib, pkgs, ... }:
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
sane.services.trust-dns.enable = true;
|
sane.services.trust-dns.enable = true;
|
||||||
@@ -6,12 +6,12 @@
|
|||||||
sane.services.trust-dns.listenAddrsIPv4 = [
|
sane.services.trust-dns.listenAddrsIPv4 = [
|
||||||
# specify each address explicitly, instead of using "*".
|
# specify each address explicitly, instead of using "*".
|
||||||
# this ensures responses are sent from the address at which the request was received.
|
# this ensures responses are sent from the address at which the request was received.
|
||||||
config.sane.hosts.by-name."servo".lan-ip
|
"192.168.0.5"
|
||||||
"10.0.1.5"
|
"10.0.1.5"
|
||||||
];
|
];
|
||||||
sane.services.trust-dns.quiet = true;
|
sane.services.trust-dns.quiet = true;
|
||||||
|
|
||||||
sane.dns.zones."uninsane.org".TTL = 900;
|
sane.services.trust-dns.zones."uninsane.org".TTL = 900;
|
||||||
|
|
||||||
# SOA record structure: <https://en.wikipedia.org/wiki/SOA_record#Structure>
|
# SOA record structure: <https://en.wikipedia.org/wiki/SOA_record#Structure>
|
||||||
# SOA MNAME RNAME (... rest)
|
# SOA MNAME RNAME (... rest)
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
# Refresh = how frequently secondary NS should query master
|
# 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)
|
# 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)
|
# Expire = how long secondary NS should continue to reply to queries after master fails (> Refresh + Retry)
|
||||||
sane.dns.zones."uninsane.org".inet = {
|
sane.services.trust-dns.zones."uninsane.org".inet = {
|
||||||
SOA."@" = ''
|
SOA."@" = ''
|
||||||
ns1.uninsane.org. admin-dns.uninsane.org. (
|
ns1.uninsane.org. admin-dns.uninsane.org. (
|
||||||
2022122101 ; Serial
|
2022122101 ; Serial
|
||||||
@@ -30,20 +30,17 @@
|
|||||||
7d ; Expire
|
7d ; Expire
|
||||||
5m) ; Negative response TTL
|
5m) ; Negative response TTL
|
||||||
'';
|
'';
|
||||||
TXT."rev" = "2023052901";
|
TXT."rev" = "2022122101";
|
||||||
|
|
||||||
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
|
# 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.
|
# it's best that we keep this identical, or a superset of, what org. lists as our NS.
|
||||||
# so, org. can specify ns2/ns3 as being to the VPN, with no mention of ns1. we provide ns1 here.
|
# so, org. can specify ns2/ns3 as being to the VPN, with no mention of ns1. we provide ns1 here.
|
||||||
A."ns1" = "%ANATIVE%";
|
A."ns1" = "%NATIVE%";
|
||||||
A."ns2" = "185.157.162.178";
|
A."ns2" = "185.157.162.178";
|
||||||
A."ns3" = "185.157.162.178";
|
A."ns3" = "185.157.162.178";
|
||||||
A."ovpns" = "185.157.162.178";
|
A."ovpns" = "185.157.162.178";
|
||||||
|
A."native" = "%NATIVE%";
|
||||||
|
A."@" = "%NATIVE%";
|
||||||
NS."@" = [
|
NS."@" = [
|
||||||
"ns1.uninsane.org."
|
"ns1.uninsane.org."
|
||||||
"ns2.uninsane.org."
|
"ns2.uninsane.org."
|
||||||
@@ -51,70 +48,20 @@
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
# we need trust-dns to load our zone by relative path instead of /nix/store path
|
sane.services.trust-dns.zones."uninsane.org".file =
|
||||||
# because we generate it at runtime.
|
"/var/lib/trust-dns/uninsane.org.zone";
|
||||||
sane.services.trust-dns.zones."uninsane.org".file = lib.mkForce "uninsane.org.zone";
|
|
||||||
sane.services.trust-dns.zonedir = null;
|
|
||||||
|
|
||||||
sane.services.trust-dns.package =
|
systemd.services.trust-dns.preStart = let
|
||||||
let
|
|
||||||
sed = "${pkgs.gnused}/bin/sed";
|
sed = "${pkgs.gnused}/bin/sed";
|
||||||
zone-dir = "/var/lib/trust-dns";
|
zone-dir = "/var/lib/trust-dns";
|
||||||
zone-wan = "${zone-dir}/wan/uninsane.org.zone";
|
zone-out = "${zone-dir}/uninsane.org.zone";
|
||||||
zone-lan = "${zone-dir}/lan/uninsane.org.zone";
|
zone-template = pkgs.writeText "uninsane.org.zone.in" config.sane.services.trust-dns.generatedZones."uninsane.org";
|
||||||
zone-template = pkgs.writeText "uninsane.org.zone.in" config.sane.services.trust-dns.zones."uninsane.org".text;
|
in ''
|
||||||
in pkgs.writeShellScriptBin "named" ''
|
# make WAN records available to trust-dns
|
||||||
# compute wan/lan values
|
mkdir -p ${zone-dir}
|
||||||
mkdir -p ${zone-dir}/{ovpn,wan,lan}
|
ip=$(cat '${config.sane.services.dyn-dns.ipPath}')
|
||||||
wan=$(cat '${config.sane.services.dyn-dns.ipPath}')
|
${sed} s/%NATIVE%/$ip/ ${zone-template} > ${zone-out}
|
||||||
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
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
sane.services.dyn-dns.restartOnChange = [ "trust-dns.service" ];
|
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";
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
22
hosts/common/cross.nix
Normal file
22
hosts/common/cross.nix
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{ config, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
mkCrossFrom = localSystem: pkgs: import pkgs.path {
|
||||||
|
inherit localSystem;
|
||||||
|
crossSystem = pkgs.stdenv.hostPlatform.system;
|
||||||
|
inherit (config.nixpkgs) config overlays;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
# 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" = mkCrossFrom "x86_64-linux" next;
|
||||||
|
crossFrom."aarch64-linux" = mkCrossFrom "aarch64-linux" next;
|
||||||
|
})
|
||||||
|
];
|
||||||
|
}
|
@@ -1,73 +1,65 @@
|
|||||||
{ lib, pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
|
./cross.nix
|
||||||
./feeds.nix
|
./feeds.nix
|
||||||
./fs.nix
|
./fs.nix
|
||||||
./hardware.nix
|
./hardware.nix
|
||||||
./home
|
./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.nix
|
./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.
|
||||||
|
];
|
||||||
|
|
||||||
# some services which use private directories error if the parent (/var/lib/private) isn't 700.
|
# 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";
|
sane.fs."/var/lib/private".dir.acl.mode = "0700";
|
||||||
|
|
||||||
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.
|
# allow `nix-shell` (and probably nix-index?) to locate our patched and custom packages
|
||||||
# unclear _when_ this occurs. it's not a service.
|
nix.nixPath = [
|
||||||
# does the daemon continually scan the nix store?
|
"nixpkgs=${pkgs.path}"
|
||||||
# does the builder use some content-addressed db to efficiently dedupe?
|
"nixpkgs-overlays=${../..}/overlays"
|
||||||
nix.settings.auto-optimise-store = true;
|
];
|
||||||
|
|
||||||
fonts = {
|
fonts = {
|
||||||
enableDefaultFonts = true;
|
enableDefaultFonts = true;
|
||||||
fonts = with pkgs; [ font-awesome noto-fonts-emoji hack-font ];
|
fonts = with pkgs; [ font-awesome twitter-color-emoji hack-font ];
|
||||||
fontconfig.enable = true;
|
fontconfig.enable = true;
|
||||||
fontconfig.defaultFonts = {
|
fontconfig.defaultFonts = {
|
||||||
emoji = [ "Font Awesome 6 Free" "Noto Color Emoji" ];
|
emoji = [ "Font Awesome 6 Free" "Twitter Color Emoji" ];
|
||||||
monospace = [ "Hack" ];
|
monospace = [ "Hack" ];
|
||||||
serif = [ "DejaVu Serif" ];
|
serif = [ "DejaVu Serif" ];
|
||||||
sansSerif = [ "DejaVu Sans" ];
|
sansSerif = [ "DejaVu Sans" ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# XXX: twitter-color-emoji doesn't cross-compile; but not-fonts-emoji does
|
|
||||||
# fonts = {
|
|
||||||
# enableDefaultFonts = true;
|
|
||||||
# fonts = with pkgs; [ font-awesome twitter-color-emoji hack-font ];
|
|
||||||
# fontconfig.enable = true;
|
|
||||||
# fontconfig.defaultFonts = {
|
|
||||||
# emoji = [ "Font Awesome 6 Free" "Twitter Color Emoji" ];
|
|
||||||
# monospace = [ "Hack" ];
|
|
||||||
# serif = [ "DejaVu Serif" ];
|
|
||||||
# sansSerif = [ "DejaVu Sans" ];
|
|
||||||
# };
|
|
||||||
# };
|
|
||||||
|
|
||||||
# disable non-required packages like nano, perl, rsync, strace
|
# disable non-required packages like nano, perl, rsync, strace
|
||||||
environment.defaultPackages = [];
|
environment.defaultPackages = [];
|
||||||
|
|
||||||
@@ -83,20 +75,8 @@
|
|||||||
# NIXOS_OZONE_WL = "1";
|
# NIXOS_OZONE_WL = "1";
|
||||||
# LIBGL_ALWAYS_SOFTWARE = "1";
|
# LIBGL_ALWAYS_SOFTWARE = "1";
|
||||||
};
|
};
|
||||||
|
# enable zsh completions
|
||||||
# dconf docs: <https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/desktop_migration_and_administration_guide/profiles>
|
environment.pathsToLink = [ "/share/zsh" ];
|
||||||
# find keys/values with `dconf dump /`
|
|
||||||
programs.dconf.enable = true;
|
|
||||||
programs.dconf.packages = [
|
|
||||||
(pkgs.writeTextFile {
|
|
||||||
name = "dconf-user-profile";
|
|
||||||
destination = "/etc/dconf/profile/user";
|
|
||||||
text = ''
|
|
||||||
user-db:user
|
|
||||||
system-db:site
|
|
||||||
'';
|
|
||||||
})
|
|
||||||
];
|
|
||||||
|
|
||||||
# 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,9 +1,3 @@
|
|||||||
# 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, ... }:
|
{ lib, sane-data, ... }:
|
||||||
let
|
let
|
||||||
hourly = { freq = "hourly"; };
|
hourly = { freq = "hourly"; };
|
||||||
@@ -56,37 +50,24 @@ let
|
|||||||
(fromDb "lexfridman.com/podcast" // rat)
|
(fromDb "lexfridman.com/podcast" // rat)
|
||||||
## Astral Codex Ten
|
## Astral Codex Ten
|
||||||
(fromDb "sscpodcast.libsyn.com" // rat)
|
(fromDb "sscpodcast.libsyn.com" // rat)
|
||||||
## Less Wrong Curated
|
|
||||||
(fromDb "feeds.libsyn.com/421877" // rat)
|
|
||||||
## Econ Talk
|
## Econ Talk
|
||||||
(fromDb "feeds.simplecast.com/wgl4xEgL" // rat)
|
(fromDb "feeds.simplecast.com/wgl4xEgL" // rat)
|
||||||
## Cory Doctorow -- both podcast & text entries
|
## Cory Doctorow -- both podcast & text entries
|
||||||
(fromDb "craphound.com" // pol)
|
(fromDb "craphound.com" // pol)
|
||||||
## Maggie Killjoy -- referenced by Cory Doctorow
|
|
||||||
(fromDb "omny.fm/shows/cool-people-who-did-cool-stuff" // pol)
|
|
||||||
(fromDb "congressionaldish.libsyn.com" // pol)
|
(fromDb "congressionaldish.libsyn.com" // pol)
|
||||||
# (mkPod "https://podcasts.la.utexas.edu/this-is-democracy/feed/podcast/" // pol // weekly)
|
|
||||||
## Civboot -- https://anchor.fm/civboot
|
## Civboot -- https://anchor.fm/civboot
|
||||||
(fromDb "anchor.fm/s/34c7232c/podcast/rss" // tech)
|
(fromDb "anchor.fm/s/34c7232c/podcast/rss" // tech)
|
||||||
## Emerge: making sense of what's next -- <https://www.whatisemerging.com/emergepodcast>
|
## Emerge: making sense of what's next -- <https://www.whatisemerging.com/emergepodcast>
|
||||||
(mkPod "https://anchor.fm/s/21bc734/podcast/rss" // pol // infrequent)
|
(mkPod "https://anchor.fm/s/21bc734/podcast/rss" // pol // infrequent)
|
||||||
(fromDb "feeds.feedburner.com/80000HoursPodcast" // rat)
|
(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 "allinchamathjason.libsyn.com" // pol)
|
||||||
(fromDb "feeds.transistor.fm/acquired" // tech)
|
(fromDb "acquired.libsyn.com" // tech)
|
||||||
## ACQ2 - more "Acquired" episodes
|
# The Intercept - Deconstructed; also available: <rss.acast.com/deconstructed>
|
||||||
(fromDb "acquiredlpbonussecretsecret.libsyn.com" // tech)
|
(fromDb "rss.prod.firstlook.media/deconstructed/podcast.rss" // pol)
|
||||||
# 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
|
# The Intercept - Intercepted; also available: <https://rss.acast.com/intercepted-with-jeremy-scahill>
|
||||||
(fromDb "rss.acast.com/intercepted-with-jeremy-scahill")
|
(fromDb "rss.prod.firstlook.media/intercepted/podcast.rss" // pol)
|
||||||
# (fromDb "rss.prod.firstlook.media/intercepted/podcast.rss" // pol) #< possible URL rot
|
|
||||||
(fromDb "podcast.posttv.com/itunes/post-reports.xml" // pol)
|
(fromDb "podcast.posttv.com/itunes/post-reports.xml" // pol)
|
||||||
## Eric Weinstein
|
## Eric Weinstein
|
||||||
(fromDb "rss.art19.com/the-portal" // rat)
|
(fromDb "rss.art19.com/the-portal" // rat)
|
||||||
@@ -109,31 +90,20 @@ let
|
|||||||
(fromDb "seattlenice.buzzsprout.com" // pol)
|
(fromDb "seattlenice.buzzsprout.com" // pol)
|
||||||
## Sci-Fi? has Peter Watts; author of No Moods, Ads or Cutesy Fucking Icons (rifters.com)
|
## Sci-Fi? has Peter Watts; author of No Moods, Ads or Cutesy Fucking Icons (rifters.com)
|
||||||
(fromDb "talesfromthebridge.buzzsprout.com" // tech)
|
(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)
|
|
||||||
];
|
];
|
||||||
|
|
||||||
texts = [
|
texts = [
|
||||||
# AGGREGATORS (> 1 post/day)
|
# AGGREGATORS (> 1 post/day)
|
||||||
(fromDb "lwn.net" // tech)
|
(fromDb "lwn.net" // tech)
|
||||||
(fromDb "lesswrong.com" // rat)
|
(fromDb "lesswrong.com" // rat)
|
||||||
# (fromDb "econlib.org" // pol)
|
(fromDb "econlib.org" // pol)
|
||||||
|
|
||||||
# AGGREGATORS (< 1 post/day)
|
# AGGREGATORS (< 1 post/day)
|
||||||
(fromDb "palladiummag.com" // uncat)
|
(fromDb "palladiummag.com" // uncat)
|
||||||
(fromDb "profectusmag.com" // uncat)
|
(fromDb "profectusmag.com" // uncat)
|
||||||
(fromDb "semiaccurate.com" // tech)
|
(fromDb "semiaccurate.com" // tech)
|
||||||
(mkText "https://linuxphoneapps.org/blog/atom.xml" // tech // infrequent)
|
(mkText "https://linuxphoneapps.org/blog/atom.xml" // tech // infrequent)
|
||||||
(fromDb "tuxphones.com" // tech)
|
|
||||||
(fromDb "spectrum.ieee.org" // tech)
|
(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/>
|
## 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)
|
(mkText "https://forum.merveilles.town/rss.xml" // pol // infrequent)
|
||||||
|
|
||||||
@@ -141,12 +111,9 @@ let
|
|||||||
(fromDb "rifters.com/crawl" // uncat)
|
(fromDb "rifters.com/crawl" // uncat)
|
||||||
|
|
||||||
# DEVELOPERS
|
# DEVELOPERS
|
||||||
(fromDb "blog.jmp.chat" // tech)
|
|
||||||
(fromDb "uninsane.org" // tech)
|
(fromDb "uninsane.org" // tech)
|
||||||
(fromDb "ascii.textfiles.com" // tech) # Jason Scott
|
|
||||||
(fromDb "xn--gckvb8fzb.com" // tech)
|
|
||||||
(fromDb "mg.lol" // tech)
|
(fromDb "mg.lol" // tech)
|
||||||
# (fromDb "drewdevault.com" // tech)
|
(fromDb "drewdevault.com" // tech)
|
||||||
## Ken Shirriff
|
## Ken Shirriff
|
||||||
(fromDb "righto.com" // tech)
|
(fromDb "righto.com" // tech)
|
||||||
## shared blog by a few NixOS devs, notably onny
|
## shared blog by a few NixOS devs, notably onny
|
||||||
@@ -164,10 +131,6 @@ let
|
|||||||
(mkText "https://anish.lakhwara.com/home.html" // tech // weekly)
|
(mkText "https://anish.lakhwara.com/home.html" // tech // weekly)
|
||||||
(fromDb "jefftk.com" // tech)
|
(fromDb "jefftk.com" // tech)
|
||||||
(fromDb "pomeroyb.com" // tech)
|
(fromDb "pomeroyb.com" // tech)
|
||||||
(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
|
## Matt Webb -- engineering-ish, but dreamy
|
||||||
@@ -184,8 +147,7 @@ let
|
|||||||
(fromDb "lynalden.com" // pol)
|
(fromDb "lynalden.com" // pol)
|
||||||
(fromDb "austinvernon.site" // tech)
|
(fromDb "austinvernon.site" // tech)
|
||||||
(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)
|
(fromDb "blog.dshr.org" // pol)
|
||||||
## Matt Levine
|
## Matt Levine
|
||||||
@@ -193,7 +155,6 @@ let
|
|||||||
(fromDb "stpeter.im/atom.xml" // pol)
|
(fromDb "stpeter.im/atom.xml" // pol)
|
||||||
## Peter Saint-Andre -- side project of stpeter.im
|
## Peter Saint-Andre -- side project of stpeter.im
|
||||||
(fromDb "philosopher.coach" // rat)
|
(fromDb "philosopher.coach" // rat)
|
||||||
(fromDb "morningbrew.com/feed" // pol)
|
|
||||||
|
|
||||||
# RATIONALITY/PHILOSOPHY/ETC
|
# RATIONALITY/PHILOSOPHY/ETC
|
||||||
(mkSubstack "samkriss" // humor // infrequent)
|
(mkSubstack "samkriss" // humor // infrequent)
|
||||||
@@ -212,15 +173,10 @@ let
|
|||||||
(fromDb "sideways-view.com" // rat)
|
(fromDb "sideways-view.com" // rat)
|
||||||
## Sean Carroll
|
## Sean Carroll
|
||||||
(fromDb "preposterousuniverse.com" // rat)
|
(fromDb "preposterousuniverse.com" // rat)
|
||||||
(mkSubstack "eliqian" // rat // weekly)
|
|
||||||
(mkText "https://acoup.blog/feed" // rat // weekly)
|
|
||||||
|
|
||||||
## 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)
|
(fromDb "putanumonit.com" // rat)
|
||||||
|
|
||||||
# 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)
|
||||||
];
|
];
|
||||||
@@ -230,7 +186,6 @@ let
|
|||||||
(fromDb "xkcd.com" // img // humor)
|
(fromDb "xkcd.com" // img // humor)
|
||||||
(fromDb "pbfcomics.com" // img // humor)
|
(fromDb "pbfcomics.com" // img // humor)
|
||||||
# (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)
|
(fromDb "miniature-calendar.com" // img // art // daily)
|
||||||
|
@@ -1,131 +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"
|
|
||||||
"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 ++ [
|
|
||||||
"user"
|
"user"
|
||||||
"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
|
||||||
{
|
{
|
||||||
# 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/servo-media-wan" = {
|
|
||||||
device = "colin@uninsane.org:/var/lib/uninsane/media";
|
|
||||||
fsType = "fuse.sshfs";
|
|
||||||
options = fsOpts.sshColin ++ fsOpts.noauto;
|
|
||||||
noCheck = true;
|
|
||||||
};
|
|
||||||
sane.fs."/mnt/servo-media-wan" = sane-lib.fs.wantedDir;
|
|
||||||
fileSystems."/mnt/servo-media-lan" = {
|
|
||||||
device = "colin@servo:/var/lib/uninsane/media";
|
|
||||||
fsType = "fuse.sshfs";
|
|
||||||
options = fsOpts.sshColin ++ fsOpts.noauto;
|
|
||||||
noCheck = true;
|
|
||||||
};
|
|
||||||
sane.fs."/mnt/servo-media-lan" = sane-lib.fs.wantedDir;
|
|
||||||
fileSystems."/mnt/servo-root-wan" = {
|
|
||||||
device = "colin@uninsane.org:/";
|
|
||||||
fsType = "fuse.sshfs";
|
|
||||||
options = fsOpts.sshRoot ++ fsOpts.noauto;
|
|
||||||
noCheck = true;
|
|
||||||
};
|
|
||||||
sane.fs."/mnt/servo-root-wan" = sane-lib.fs.wantedDir;
|
|
||||||
fileSystems."/mnt/servo-root-lan" = {
|
|
||||||
device = "colin@servo:/";
|
|
||||||
fsType = "fuse.sshfs";
|
|
||||||
options = fsOpts.sshRoot ++ fsOpts.noauto;
|
|
||||||
noCheck = true;
|
|
||||||
};
|
|
||||||
sane.fs."/mnt/servo-root-lan" = sane-lib.fs.wantedDir;
|
|
||||||
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
|
||||||
];
|
];
|
||||||
|
@@ -28,11 +28,6 @@
|
|||||||
# 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 = "/";
|
||||||
|
12
hosts/common/home/aerc.nix
Normal file
12
hosts/common/home/aerc.nix
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# Terminal UI mail client
|
||||||
|
{ config, lib, sane-lib, ... }:
|
||||||
|
|
||||||
|
lib.mkIf config.sane.home-manager.enable
|
||||||
|
{
|
||||||
|
sops.secrets."aerc_accounts" = {
|
||||||
|
owner = config.users.users.colin.name;
|
||||||
|
sopsFile = ../../../secrets/universal/aerc_accounts.conf;
|
||||||
|
format = "binary";
|
||||||
|
};
|
||||||
|
sane.fs."/home/colin/.config/aerc/accounts.conf" = sane-lib.fs.wantedSymlinkTo config.sops.secrets.aerc_accounts.path;
|
||||||
|
}
|
@@ -1,9 +1,23 @@
|
|||||||
{ ... }:
|
{ ... }:
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
|
./aerc.nix
|
||||||
|
./firefox.nix
|
||||||
|
./gfeeds.nix
|
||||||
|
./git.nix
|
||||||
|
./gpodder.nix
|
||||||
./keyring.nix
|
./keyring.nix
|
||||||
|
./kitty.nix
|
||||||
|
./libreoffice.nix
|
||||||
./mime.nix
|
./mime.nix
|
||||||
|
./mpv.nix
|
||||||
|
./neovim.nix
|
||||||
|
./newsflash.nix
|
||||||
|
./splatmoji.nix
|
||||||
./ssh.nix
|
./ssh.nix
|
||||||
|
./sublime-music.nix
|
||||||
|
./vlc.nix
|
||||||
./xdg-dirs.nix
|
./xdg-dirs.nix
|
||||||
|
./zsh
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
199
hosts/common/home/firefox.nix
Normal file
199
hosts/common/home/firefox.nix
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
# 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, sane-lib, ...}:
|
||||||
|
with lib;
|
||||||
|
let
|
||||||
|
cfg = config.sane.web-browser;
|
||||||
|
# allow easy switching between firefox and librewolf with `defaultSettings`, below
|
||||||
|
librewolfSettings = {
|
||||||
|
browser = pkgs.librewolf-unwrapped;
|
||||||
|
# browser = pkgs.librewolf-unwrapped.overrideAttrs (drv: {
|
||||||
|
# # this allows side-loading unsigned addons
|
||||||
|
# MOZ_REQUIRE_SIGNING = false;
|
||||||
|
# });
|
||||||
|
libName = "librewolf";
|
||||||
|
dotDir = ".librewolf";
|
||||||
|
cacheDir = ".cache/librewolf"; # TODO: is it?
|
||||||
|
desktop = "librewolf.desktop";
|
||||||
|
};
|
||||||
|
firefoxSettings = {
|
||||||
|
browser = pkgs.firefox-esr-unwrapped;
|
||||||
|
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 (pkgs.librewolf-unwrapped) extraPrefsFiles;
|
||||||
|
inherit (cfg.browser) libName;
|
||||||
|
|
||||||
|
extraNativeMessagingHosts = [ pkgs.browserpass ];
|
||||||
|
# extraNativeMessagingHosts = [ pkgs.gopass-native-messaging-host ];
|
||||||
|
|
||||||
|
nixExtensions = concatMap (ext: optional ext.enable ext.package) (attrValues cfg.addons);
|
||||||
|
|
||||||
|
extraPolicies = {
|
||||||
|
NoDefaultBookmarks = true;
|
||||||
|
SearchEngines = {
|
||||||
|
Default = "DuckDuckGo";
|
||||||
|
};
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
addonOpts = types.submodule {
|
||||||
|
options = {
|
||||||
|
package = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
};
|
||||||
|
enable = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
sane.web-browser.browser = mkOption {
|
||||||
|
default = defaultSettings;
|
||||||
|
type = types.attrs;
|
||||||
|
};
|
||||||
|
sane.web-browser.persistData = mkOption {
|
||||||
|
description = "optional store name to which persist browsing data (like history)";
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
|
sane.web-browser.persistCache = mkOption {
|
||||||
|
description = "optional store name to which persist browser cache";
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = "cryptClearOnBoot";
|
||||||
|
};
|
||||||
|
sane.web-browser.addons = mkOption {
|
||||||
|
type = types.attrsOf addonOpts;
|
||||||
|
default = {
|
||||||
|
# get names from:
|
||||||
|
# - ~/ref/nix-community/nur-combined/repos/rycee/pkgs/firefox-addons/generated-firefox-addons.nix
|
||||||
|
# `wget ...xpi`; `unar ...xpi`; `cat */manifest.json | jq '.browser_specific_settings.gecko.id'`
|
||||||
|
# browserpass-ce.package = addon "browserpass-ce" "browserpass@maximbaz.com" "sha256-sXgUBbRvMnRpeIW1MTkmTcoqtW/8RDXAkxAq1evFkpc=";
|
||||||
|
browserpass-extension.package = localAddon pkgs.browserpass-extension;
|
||||||
|
bypass-paywalls-clean.package = addon "bypass-paywalls-clean" "{d133e097-46d9-4ecc-9903-fa6a722a6e0e}" "sha256-JOj5P7c2JTTReHCRZXm4BscaGr3i+9Y4Ey/y621x8PI=";
|
||||||
|
ether-metamask.package = addon "ether-metamask" "webextension@metamask.io" "sha256-G+MwJDOcsaxYSUXjahHJmkWnjLeQ0Wven8DU/lGeMzA=";
|
||||||
|
i2p-in-private-browsing.package = addon "i2p-in-private-browsing" "i2ppb@eyedeekay.github.io" "sha256-dJcJ3jxeAeAkRvhODeIVrCflvX+S4E0wT/PyYzQBQWs=";
|
||||||
|
sidebery.package = addon "sidebery" "{3c078156-979c-498b-8990-85f7987dd929}" "sha256-YONfK/rIjlsrTgRHIt3km07Q7KnpIW89Z9r92ZSCc6w=";
|
||||||
|
sponsorblock.package = addon "sponsorblock" "sponsorBlocker@ajay.app" "sha256-d2K3ufvurWnYVzqLbyR//MgejybkY9exitAf9RdLNRo=";
|
||||||
|
ublacklist.package = addon "ublacklist" "@ublacklist" "sha256-RqY5iHzbL2qizth7aguyOKWPyINXmrwOlf/OsfqAS48=";
|
||||||
|
ublock-origin.package = addon "ublock-origin" "uBlock0@raymondhill.net" "sha256-a/ivUmY1P6teq9x0dt4CbgHt+3kBsEMMXlOfZ5Hx7cg=";
|
||||||
|
|
||||||
|
browserpass-extension.enable = lib.mkDefault true;
|
||||||
|
bypass-paywalls-clean.enable = lib.mkDefault true;
|
||||||
|
ether-metamask.enable = lib.mkDefault true;
|
||||||
|
i2p-in-private-browsing.enable = lib.mkDefault config.services.i2p.enable;
|
||||||
|
sidebery.enable = lib.mkDefault true;
|
||||||
|
sponsorblock.enable = lib.mkDefault true;
|
||||||
|
ublacklist.enable = lib.mkDefault true;
|
||||||
|
ublock-origin.enable = lib.mkDefault true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf config.sane.home-manager.enable {
|
||||||
|
|
||||||
|
# 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>
|
||||||
|
sane.fs."/home/colin/${cfg.browser.dotDir}/managed-storage/uBlock0@raymondhill.net.json" = sane-lib.fs.wantedText ''
|
||||||
|
{
|
||||||
|
"name": "uBlock0@raymondhill.net",
|
||||||
|
"description": "ignored",
|
||||||
|
"type": "storage",
|
||||||
|
"data": {
|
||||||
|
"toOverwrite": "{\"filterLists\": [\"fanboy-cookiemonster\"]}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
sane.fs."/home/colin/${cfg.browser.dotDir}/${cfg.browser.libName}.overrides.cfg" = sane-lib.fs.wantedText ''
|
||||||
|
// 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);
|
||||||
|
'';
|
||||||
|
|
||||||
|
sane.packages.extraGuiPkgs = [ package ];
|
||||||
|
# flush the cache to disk to avoid it taking up too much tmp
|
||||||
|
sane.persist.home.byPath."${cfg.browser.cacheDir}" = lib.mkIf (cfg.persistCache != null) {
|
||||||
|
store = cfg.persistCache;
|
||||||
|
};
|
||||||
|
|
||||||
|
sane.persist.home.byPath."${cfg.browser.dotDir}/default" = lib.mkIf (cfg.persistData != null) {
|
||||||
|
store = cfg.persistData;
|
||||||
|
};
|
||||||
|
sane.fs."/home/colin/${cfg.browser.dotDir}/default" = sane-lib.fs.wantedDir;
|
||||||
|
# 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.
|
||||||
|
sane.fs."/home/colin/${cfg.browser.dotDir}/profiles.ini" = sane-lib.fs.wantedText ''
|
||||||
|
[Profile0]
|
||||||
|
Name=default
|
||||||
|
IsRelative=1
|
||||||
|
Path=default
|
||||||
|
Default=1
|
||||||
|
|
||||||
|
[General]
|
||||||
|
StartWithLastProfile=1
|
||||||
|
'';
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
42
hosts/common/home/gfeeds.nix
Normal file
42
hosts/common/home/gfeeds.nix
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# 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.fs."/home/colin/.config/org.gabmus.gfeeds.json" = sane-lib.fs.wantedText (
|
||||||
|
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,26 +1,19 @@
|
|||||||
{ lib, pkgs, ... }:
|
{ config, lib, pkgs, sane-lib, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
mkCfg = lib.generators.toINI { };
|
mkCfg = lib.generators.toINI { };
|
||||||
in
|
in
|
||||||
|
lib.mkIf config.sane.home-manager.enable
|
||||||
{
|
{
|
||||||
sane.programs.git.fs.".config/git/config".symlink.text = mkCfg {
|
sane.fs."/home/colin/.config/git/config" = sane-lib.fs.wantedText (mkCfg {
|
||||||
# top-level options documented:
|
|
||||||
# - <https://git-scm.com/docs/git-config#_variables>
|
|
||||||
|
|
||||||
user.name = "Colin";
|
user.name = "Colin";
|
||||||
user.email = "colin@uninsane.org";
|
user.email = "colin@uninsane.org";
|
||||||
|
|
||||||
alias.co = "checkout";
|
alias.co = "checkout";
|
||||||
|
|
||||||
# difftastic docs:
|
# difftastic docs:
|
||||||
# - <https://difftastic.wilfred.me.uk/git.html>
|
# - <https://difftastic.wilfred.me.uk/git.html>
|
||||||
diff.tool = "difftastic";
|
diff.tool = "difftastic";
|
||||||
difftool.prompt = false;
|
difftool.prompt = false;
|
||||||
"difftool \"difftastic\"".cmd = ''${pkgs.difftastic}/bin/difft "$LOCAL" "$REMOTE"'';
|
"difftool \"difftastic\"".cmd = ''${pkgs.difftastic}/bin/difft "$LOCAL" "$REMOTE"'';
|
||||||
# now run `git difftool` to use difftastic git
|
# now run `git difftool` to use difftastic git
|
||||||
|
});
|
||||||
# render dates as YYYY-MM-DD HH:MM:SS +TZ
|
|
||||||
log.date = "iso";
|
|
||||||
};
|
|
||||||
}
|
}
|
12
hosts/common/home/gpodder.nix
Normal file
12
hosts/common/home/gpodder.nix
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# gnome feeds RSS viewer
|
||||||
|
{ config, sane-lib, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
feeds = sane-lib.feeds;
|
||||||
|
all-feeds = config.sane.feeds;
|
||||||
|
wanted-feeds = feeds.filterByFormat ["podcast"] all-feeds;
|
||||||
|
in {
|
||||||
|
sane.fs."/home/colin/.config/gpodderFeeds.opml" = sane-lib.fs.wantedText (
|
||||||
|
feeds.feedsToOpml wanted-feeds
|
||||||
|
);
|
||||||
|
}
|
@@ -1,11 +1,11 @@
|
|||||||
{ config, sane-lib, ... }:
|
{ config, lib, sane-lib, ... }:
|
||||||
|
|
||||||
|
lib.mkIf config.sane.home-manager.enable
|
||||||
{
|
{
|
||||||
sane.user.persist.private = [ ".local/share/keyrings" ];
|
sane.persist.home.private = [ ".local/share/keyrings" ];
|
||||||
|
|
||||||
sane.user.fs."private/.local/share/keyrings/default" = {
|
sane.fs."/home/colin/private/.local/share/keyrings/default" = {
|
||||||
generated.script.script = builtins.readFile ../../../scripts/init-keyring;
|
generated.script.script = builtins.readFile ../../../scripts/init-keyring;
|
||||||
# TODO: is this `wantedBy` needed? can we inherit it?
|
|
||||||
wantedBy = [ config.sane.fs."/home/colin/private".unit ];
|
wantedBy = [ config.sane.fs."/home/colin/private".unit ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -1,17 +1,16 @@
|
|||||||
{ ... }:
|
{ config, lib, pkgs, sane-lib, ... }:
|
||||||
|
|
||||||
|
lib.mkIf config.sane.home-manager.enable
|
||||||
{
|
{
|
||||||
sane.programs.kitty.fs.".config/kitty/kitty.conf".symlink.text = ''
|
sane.fs."/home/colin/.config/kitty/kitty.conf" = sane-lib.fs.wantedText ''
|
||||||
# docs: https://sw.kovidgoyal.net/kitty/conf/
|
# docs: https://sw.kovidgoyal.net/kitty/conf/
|
||||||
# disable terminal bell (when e.g. you backspace too many times)
|
# disable terminal bell (when e.g. you backspace too many times)
|
||||||
enable_audio_bell no
|
enable_audio_bell no
|
||||||
|
|
||||||
map ctrl+n new_os_window_with_cwd
|
map ctrl+n new_os_window_with_cwd
|
||||||
include ${./PaperColor_dark.conf}
|
|
||||||
|
include ${pkgs.kitty-themes}/themes/PaperColor_dark.conf
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# include ${pkgs.kitty-themes}/themes/PaperColor_dark.conf
|
|
||||||
|
|
||||||
# THEME CHOICES:
|
# THEME CHOICES:
|
||||||
# docs: https://github.com/kovidgoyal/kitty-themes
|
# docs: https://github.com/kovidgoyal/kitty-themes
|
||||||
# theme = "1984 Light"; # dislike: awful, harsh blues/teals
|
# theme = "1984 Light"; # dislike: awful, harsh blues/teals
|
@@ -1,8 +1,9 @@
|
|||||||
{ ... }:
|
{ config, lib, sane-lib, ... }:
|
||||||
|
|
||||||
|
lib.mkIf config.sane.home-manager.enable
|
||||||
{
|
{
|
||||||
# libreoffice: disable first-run stuff
|
# libreoffice: disable first-run stuff
|
||||||
sane.programs.libreoffice-fresh.fs.".config/libreoffice/4/user/registrymodifications.xcu".symlink.text = ''
|
sane.fs."/home/colin/.config/libreoffice/4/user/registrymodifications.xcu" = sane-lib.fs.wantedText ''
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?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">
|
<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="FirstRun" oor:op="fuse"><value>false</value></prop></item>
|
@@ -1,7 +1,7 @@
|
|||||||
{ config, sane-lib, ...}:
|
{ config, lib, sane-lib, ...}:
|
||||||
|
|
||||||
let
|
let
|
||||||
www = config.sane.programs.web-browser.config.browser.desktop;
|
www = config.sane.web-browser.browser.desktop;
|
||||||
pdf = "org.gnome.Evince.desktop";
|
pdf = "org.gnome.Evince.desktop";
|
||||||
md = "obsidian.desktop";
|
md = "obsidian.desktop";
|
||||||
thumb = "org.gnome.gThumb.desktop";
|
thumb = "org.gnome.gThumb.desktop";
|
||||||
@@ -9,6 +9,7 @@ let
|
|||||||
# audio = "mpv.desktop";
|
# audio = "mpv.desktop";
|
||||||
audio = "vlc.desktop";
|
audio = "vlc.desktop";
|
||||||
in
|
in
|
||||||
|
lib.mkIf config.sane.home-manager.enable
|
||||||
{
|
{
|
||||||
|
|
||||||
# the xdg mime type for a file can be found with:
|
# the xdg mime type for a file can be found with:
|
||||||
@@ -28,7 +29,6 @@ in
|
|||||||
# VIDEO
|
# VIDEO
|
||||||
"video/mp4" = video;
|
"video/mp4" = video;
|
||||||
"video/quicktime" = video;
|
"video/quicktime" = video;
|
||||||
"video/webm" = video;
|
|
||||||
"video/x-matroska" = video;
|
"video/x-matroska" = video;
|
||||||
# HTML
|
# HTML
|
||||||
"text/html" = www;
|
"text/html" = www;
|
||||||
|
11
hosts/common/home/mpv.nix
Normal file
11
hosts/common/home/mpv.nix
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{ config, lib, sane-lib, ... }:
|
||||||
|
|
||||||
|
lib.mkIf config.sane.home-manager.enable
|
||||||
|
{
|
||||||
|
# format is <key>=%<length>%<value>
|
||||||
|
sane.fs."/home/colin/.config/mpv/mpv.conf" = sane-lib.fs.wantedText ''
|
||||||
|
save-position-on-quit=%3%yes
|
||||||
|
keep-open=%3%yes
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
let
|
let
|
||||||
inherit (builtins) map;
|
inherit (builtins) map;
|
||||||
inherit (lib) concatMapStrings mkIf optionalString;
|
inherit (lib) concatMapStrings optionalString;
|
||||||
# this structure roughly mirrors home-manager's `programs.neovim.plugins` option
|
# this structure roughly mirrors home-manager's `programs.neovim.plugins` option
|
||||||
plugins = with pkgs.vimPlugins; [
|
plugins = with pkgs.vimPlugins; [
|
||||||
# docs: surround-nvim: https://github.com/ur4ltz/surround.nvim/
|
# docs: surround-nvim: https://github.com/ur4ltz/surround.nvim/
|
||||||
@@ -70,11 +70,12 @@ let
|
|||||||
plugin-config-tex = concatMapStrings (p: optionalString (p.type or "" == "viml") p.config) plugins;
|
plugin-config-tex = concatMapStrings (p: optionalString (p.type or "" == "viml") p.config) plugins;
|
||||||
plugin-config-lua = concatMapStrings (p: optionalString (p.type or "" == "lua") p.config) plugins;
|
plugin-config-lua = concatMapStrings (p: optionalString (p.type or "" == "lua") p.config) plugins;
|
||||||
in
|
in
|
||||||
|
lib.mkIf config.sane.home-manager.enable
|
||||||
{
|
{
|
||||||
# private because there could be sensitive things in the swap
|
# private because there could be sensitive things in the swap
|
||||||
sane.programs.neovim.persist.private = [ ".cache/vim-swap" ];
|
sane.persist.home.private = [ ".cache/vim-swap" ];
|
||||||
|
|
||||||
programs.neovim = mkIf config.sane.programs.neovim.enabled {
|
programs.neovim = {
|
||||||
# neovim: https://github.com/neovim/neovim
|
# neovim: https://github.com/neovim/neovim
|
||||||
enable = true;
|
enable = true;
|
||||||
viAlias = true;
|
viAlias = true;
|
@@ -6,10 +6,7 @@ let
|
|||||||
all-feeds = config.sane.feeds;
|
all-feeds = config.sane.feeds;
|
||||||
wanted-feeds = feeds.filterByFormat ["text" "image"] all-feeds;
|
wanted-feeds = feeds.filterByFormat ["text" "image"] all-feeds;
|
||||||
in {
|
in {
|
||||||
sane.programs.newsflash = {
|
sane.fs."/home/colin/.config/newsflashFeeds.opml" = sane-lib.fs.wantedText (
|
||||||
persist.plaintext = [ ".local/share/news-flash" ];
|
|
||||||
fs.".config/newsflashFeeds.opml".symlink.text =
|
|
||||||
feeds.feedsToOpml wanted-feeds
|
feeds.feedsToOpml wanted-feeds
|
||||||
;
|
);
|
||||||
};
|
|
||||||
}
|
}
|
19
hosts/common/home/splatmoji.nix
Normal file
19
hosts/common/home/splatmoji.nix
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# 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-lib, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
sane.persist.home.plaintext = [ ".local/state/splatmoji" ];
|
||||||
|
sane.fs."/home/colin/.config/splatmoji/splatmoji.config" = sane-lib.fs.wantedText ''
|
||||||
|
history_file=/home/colin/.local/state/splatmoji/history
|
||||||
|
history_length=5
|
||||||
|
# TODO: wayland equiv
|
||||||
|
paste_command=xdotool key ctrl+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
|
||||||
|
# TODO: wayland equiv
|
||||||
|
xsel_command=xsel -b -i
|
||||||
|
'';
|
||||||
|
}
|
@@ -1,22 +1,19 @@
|
|||||||
{ config, lib, sane-lib, ... }:
|
{ config, lib, pkgs, sane-lib, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
let
|
let
|
||||||
host = config.networking.hostName;
|
host = config.networking.hostName;
|
||||||
user-pubkey-full = config.sane.ssh.pubkeys."colin@${host}" or {};
|
user-pubkey = config.sane.ssh.pubkeys."colin@${host}".asUserKey;
|
||||||
user-pubkey = user-pubkey-full.asUserKey or null;
|
|
||||||
host-keys = filter (k: k.user == "root") (attrValues config.sane.ssh.pubkeys);
|
host-keys = filter (k: k.user == "root") (attrValues config.sane.ssh.pubkeys);
|
||||||
known-hosts-text = concatStringsSep
|
known-hosts-text = concatStringsSep
|
||||||
"\n"
|
"\n"
|
||||||
(map (k: k.asHostKey) host-keys)
|
(map (k: k.asHostKey) host-keys)
|
||||||
;
|
;
|
||||||
in
|
in lib.mkIf config.sane.home-manager.enable {
|
||||||
{
|
|
||||||
# ssh key is stored in private storage
|
# ssh key is stored in private storage
|
||||||
sane.user.persist.private = [ ".ssh/id_ed25519" ];
|
sane.persist.home.private = [ ".ssh/id_ed25519" ];
|
||||||
sane.user.fs.".ssh/id_ed25519.pub" =
|
sane.fs."/home/colin/.ssh/id_ed25519.pub" = sane-lib.fs.wantedText user-pubkey;
|
||||||
mkIf (user-pubkey != null) (sane-lib.fs.wantedText user-pubkey);
|
sane.fs."/home/colin/.ssh/known_hosts" = sane-lib.fs.wantedText known-hosts-text;
|
||||||
sane.user.fs.".ssh/known_hosts" = sane-lib.fs.wantedText known-hosts-text;
|
|
||||||
|
|
||||||
users.users.colin.openssh.authorizedKeys.keys =
|
users.users.colin.openssh.authorizedKeys.keys =
|
||||||
let
|
let
|
||||||
|
12
hosts/common/home/sublime-music.nix
Normal file
12
hosts/common/home/sublime-music.nix
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{ config, lib, sane-lib, ... }:
|
||||||
|
|
||||||
|
lib.mkIf config.sane.home-manager.enable
|
||||||
|
{
|
||||||
|
# TODO: this should only be shipped on gui platforms
|
||||||
|
sops.secrets."sublime_music_config" = {
|
||||||
|
owner = config.users.users.colin.name;
|
||||||
|
sopsFile = ../../../secrets/universal/sublime_music_config.json.bin;
|
||||||
|
format = "binary";
|
||||||
|
};
|
||||||
|
sane.fs."/home/colin/.config/sublime-music/config.json" = sane-lib.fs.wantedSymlinkTo config.sops.secrets.sublime_music_config.path;
|
||||||
|
}
|
21
hosts/common/home/vlc.nix
Normal file
21
hosts/common/home/vlc.nix
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{ 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
|
||||||
|
lib.mkIf config.sane.home-manager.enable
|
||||||
|
{
|
||||||
|
sane.fs."/home/colin/.config/vlc/vlcrc" = sane-lib.fs.wantedText ''
|
||||||
|
[podcast]
|
||||||
|
podcast-urls=${podcast-urls}
|
||||||
|
[core]
|
||||||
|
metadata-network-access=0
|
||||||
|
[qt]
|
||||||
|
qt-privacy-ask=0
|
||||||
|
'';
|
||||||
|
}
|
@@ -1,9 +1,10 @@
|
|||||||
{ lib, sane-lib, ...}:
|
{ config, lib, sane-lib, ...}:
|
||||||
|
|
||||||
|
lib.mkIf config.sane.home-manager.enable
|
||||||
{
|
{
|
||||||
# XDG defines things like ~/Desktop, ~/Downloads, etc.
|
# XDG defines things like ~/Desktop, ~/Downloads, etc.
|
||||||
# these clutter the home, so i mostly don't use them.
|
# these clutter the home, so i mostly don't use them.
|
||||||
sane.user.fs.".config/user-dirs.dirs" = sane-lib.fs.wantedText ''
|
sane.fs."/home/colin/.config/user-dirs.dirs" = sane-lib.fs.wantedText ''
|
||||||
XDG_DESKTOP_DIR="$HOME/.xdg/Desktop"
|
XDG_DESKTOP_DIR="$HOME/.xdg/Desktop"
|
||||||
XDG_DOCUMENTS_DIR="$HOME/dev"
|
XDG_DOCUMENTS_DIR="$HOME/dev"
|
||||||
XDG_DOWNLOAD_DIR="$HOME/tmp"
|
XDG_DOWNLOAD_DIR="$HOME/tmp"
|
||||||
@@ -16,5 +17,5 @@
|
|||||||
|
|
||||||
# prevent `xdg-user-dirs-update` from overriding/updating our config
|
# prevent `xdg-user-dirs-update` from overriding/updating our config
|
||||||
# see <https://manpages.ubuntu.com/manpages/bionic/man5/user-dirs.conf.5.html>
|
# see <https://manpages.ubuntu.com/manpages/bionic/man5/user-dirs.conf.5.html>
|
||||||
sane.user.fs.".config/user-dirs.conf" = sane-lib.fs.wantedText "enabled=False";
|
sane.fs."/home/colin/.config/user-dirs.conf" = sane-lib.fs.wantedText "enabled=False";
|
||||||
}
|
}
|
||||||
|
141
hosts/common/home/zsh/default.nix
Normal file
141
hosts/common/home/zsh/default.nix
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
{ config, lib, pkgs, sane-lib, ... }:
|
||||||
|
|
||||||
|
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
|
||||||
|
lib.mkIf config.sane.home-manager.enable
|
||||||
|
{
|
||||||
|
sane.persist.home.plaintext = [
|
||||||
|
# we don't need to full zsh dir -- just the history file --
|
||||||
|
# but zsh will sometimes backup the history file and we get fewer errors if we do proper mounts instead of symlinks.
|
||||||
|
# TODO: should be private?
|
||||||
|
".local/share/zsh"
|
||||||
|
# cache gitstatus otherwise p10k fetched it from the net EVERY BOOT
|
||||||
|
".cache/gitstatus"
|
||||||
|
];
|
||||||
|
|
||||||
|
# zsh/prezto complains if zshrc doesn't exist; but it does allow an "empty" file.
|
||||||
|
sane.fs."/home/colin/.config/zsh/.zshrc" = sane-lib.fs.wantedText "# ";
|
||||||
|
|
||||||
|
programs.zsh = {
|
||||||
|
enable = true;
|
||||||
|
histFile = "$HOME/.local/share/zsh/history";
|
||||||
|
shellAliases = {
|
||||||
|
":q" = "exit";
|
||||||
|
# common typos
|
||||||
|
"cd.." = "cd ..";
|
||||||
|
"cd../" = "cd ../";
|
||||||
|
};
|
||||||
|
setOptions = [
|
||||||
|
# defaults:
|
||||||
|
"HIST_IGNORE_DUPS"
|
||||||
|
"SHARE_HISTORY"
|
||||||
|
"HIST_FCNTL_LOCK"
|
||||||
|
# disable `rm *` confirmations
|
||||||
|
"rmstarsilent"
|
||||||
|
];
|
||||||
|
|
||||||
|
# .zshenv config:
|
||||||
|
shellInit = ''
|
||||||
|
ZDOTDIR=$HOME/.config/zsh
|
||||||
|
'';
|
||||||
|
|
||||||
|
# .zshrc config:
|
||||||
|
interactiveShellInit =
|
||||||
|
(builtins.readFile ./p10k.zsh)
|
||||||
|
+ p10k-overrides
|
||||||
|
+ prezto-init
|
||||||
|
+ ''
|
||||||
|
# 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 *)'
|
||||||
|
|
||||||
|
# extra aliases
|
||||||
|
# TODO: move to `shellAliases` config?
|
||||||
|
function nd() {
|
||||||
|
mkdir -p "$1";
|
||||||
|
pushd "$1";
|
||||||
|
}
|
||||||
|
|
||||||
|
# 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"
|
||||||
|
'';
|
||||||
|
|
||||||
|
syntaxHighlighting.enable = true;
|
||||||
|
vteIntegration = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# enable a command-not-found hook to show nix packages that might provide the binary typed.
|
||||||
|
programs.nix-index.enable = true;
|
||||||
|
programs.command-not-found.enable = false; #< mutually exclusive with nix-index
|
||||||
|
|
||||||
|
# prezto = oh-my-zsh fork; controls prompt, auto-completion, etc.
|
||||||
|
# see: https://github.com/sorin-ionescu/prezto
|
||||||
|
# i believe this file is auto-sourced by the prezto init.zsh script.
|
||||||
|
sane.fs."/home/colin/.config/zsh/.zpreztorc" = sane-lib.fs.wantedText ''
|
||||||
|
zstyle ':prezto:*:*' color 'yes'
|
||||||
|
|
||||||
|
# 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
|
||||||
|
# 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
|
||||||
|
# TODO: enable AUTO_PARAM_SLASH
|
||||||
|
zstyle ':prezto:load' pmodule \
|
||||||
|
'environment' \
|
||||||
|
'terminal' \
|
||||||
|
'editor' \
|
||||||
|
'history' \
|
||||||
|
'directory' \
|
||||||
|
'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'
|
||||||
|
'';
|
||||||
|
}
|
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;
|
||||||
@@ -32,16 +27,6 @@
|
|||||||
sane.ids.mautrix-signal.gid = 2404;
|
sane.ids.mautrix-signal.gid = 2404;
|
||||||
sane.ids.navidrome.uid = 2405;
|
sane.ids.navidrome.uid = 2405;
|
||||||
sane.ids.navidrome.gid = 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.colin.uid = 1000;
|
sane.ids.colin.uid = 1000;
|
||||||
sane.ids.guest.uid = 1100;
|
sane.ids.guest.uid = 1100;
|
||||||
@@ -50,12 +35,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,4 +1,4 @@
|
|||||||
{ lib, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
# the default backend is "wpa_supplicant".
|
# the default backend is "wpa_supplicant".
|
||||||
@@ -20,8 +20,4 @@
|
|||||||
General.RoamThreshold = "-52"; # default -70
|
General.RoamThreshold = "-52"; # default -70
|
||||||
General.RoamThreshold5G = "-52"; # default -76
|
General.RoamThreshold5G = "-52"; # default -76
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.firewall.allowedUDPPorts = [
|
|
||||||
1900 # to received UPnP advertisements. required by sane-ip-check-upnp
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
@@ -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,18 +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 = [
|
|
||||||
"/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.
|
|
||||||
"/var/lib/systemd/backlight" # backlight brightness
|
|
||||||
"/var/lib/systemd/coredump"
|
|
||||||
];
|
|
||||||
}
|
|
@@ -1,6 +0,0 @@
|
|||||||
# Terminal UI mail client
|
|
||||||
{ ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
sane.programs.aerc.secrets.".config/aerc/accounts.conf" = ../../../secrets/common/aerc_accounts.conf.bin;
|
|
||||||
}
|
|
@@ -1,385 +0,0 @@
|
|||||||
{ lib, pkgs, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
inherit (builtins) attrNames;
|
|
||||||
|
|
||||||
flattenedPkgs = pkgs // (with pkgs; {
|
|
||||||
# XXX can't `inherit` a nested attr, so we move them to the toplevel
|
|
||||||
"cacert.unbundled" = pkgs.cacert.unbundled;
|
|
||||||
"gnome.cheese" = gnome.cheese;
|
|
||||||
"gnome.dconf-editor" = gnome.dconf-editor;
|
|
||||||
"gnome.file-roller" = gnome.file-roller;
|
|
||||||
"gnome.gnome-disk-utility" = gnome.gnome-disk-utility;
|
|
||||||
"gnome.gnome-maps" = gnome.gnome-maps;
|
|
||||||
"gnome.nautilus" = gnome.nautilus;
|
|
||||||
"gnome.gnome-system-monitor" = gnome.gnome-system-monitor;
|
|
||||||
"gnome.gnome-terminal" = gnome.gnome-terminal;
|
|
||||||
"gnome.gnome-weather" = gnome.gnome-weather;
|
|
||||||
"gnome.totem" = gnome.totem;
|
|
||||||
"libsForQt5.plasmatube" = libsForQt5.plasmatube;
|
|
||||||
});
|
|
||||||
|
|
||||||
sysadminPkgs = {
|
|
||||||
inherit (flattenedPkgs)
|
|
||||||
btrfs-progs
|
|
||||||
"cacert.unbundled" # some services require unbundled /etc/ssl/certs
|
|
||||||
cryptsetup
|
|
||||||
dig
|
|
||||||
efibootmgr
|
|
||||||
fatresize
|
|
||||||
fd
|
|
||||||
file
|
|
||||||
gawk
|
|
||||||
git
|
|
||||||
gptfdisk
|
|
||||||
hdparm
|
|
||||||
htop
|
|
||||||
iftop
|
|
||||||
inetutils # for telnet
|
|
||||||
iotop
|
|
||||||
iptables
|
|
||||||
jq
|
|
||||||
killall
|
|
||||||
lsof
|
|
||||||
miniupnpc
|
|
||||||
nano
|
|
||||||
netcat
|
|
||||||
nethogs
|
|
||||||
nmap
|
|
||||||
openssl
|
|
||||||
parted
|
|
||||||
pciutils
|
|
||||||
powertop
|
|
||||||
pstree
|
|
||||||
ripgrep
|
|
||||||
screen
|
|
||||||
smartmontools
|
|
||||||
socat
|
|
||||||
strace
|
|
||||||
subversion
|
|
||||||
tcpdump
|
|
||||||
tree
|
|
||||||
usbutils
|
|
||||||
wget
|
|
||||||
wirelesstools # iwlist
|
|
||||||
;
|
|
||||||
};
|
|
||||||
sysadminExtraPkgs = {
|
|
||||||
# application-specific packages
|
|
||||||
inherit (pkgs)
|
|
||||||
backblaze-b2
|
|
||||||
duplicity
|
|
||||||
sqlite # to debug sqlite3 databases
|
|
||||||
;
|
|
||||||
};
|
|
||||||
|
|
||||||
iphonePkgs = {
|
|
||||||
inherit (pkgs)
|
|
||||||
ifuse
|
|
||||||
ipfs
|
|
||||||
libimobiledevice
|
|
||||||
;
|
|
||||||
};
|
|
||||||
|
|
||||||
tuiPkgs = {
|
|
||||||
inherit (pkgs)
|
|
||||||
aerc # email client
|
|
||||||
offlineimap # email mailox sync
|
|
||||||
sfeed # RSS fetcher
|
|
||||||
visidata # TUI spreadsheet viewer/editor
|
|
||||||
w3m
|
|
||||||
;
|
|
||||||
};
|
|
||||||
|
|
||||||
consoleMediaPkgs = {
|
|
||||||
inherit (pkgs)
|
|
||||||
ffmpeg
|
|
||||||
imagemagick
|
|
||||||
sox
|
|
||||||
yt-dlp
|
|
||||||
;
|
|
||||||
};
|
|
||||||
# TODO: split these into smaller groups.
|
|
||||||
# - moby doesn't want a lot of these.
|
|
||||||
# - categories like
|
|
||||||
# - dev?
|
|
||||||
# - debugging?
|
|
||||||
consolePkgs = {
|
|
||||||
inherit (pkgs)
|
|
||||||
alsaUtils # for aplay, speaker-test
|
|
||||||
cdrtools
|
|
||||||
clinfo
|
|
||||||
dmidecode
|
|
||||||
efivar
|
|
||||||
flashrom
|
|
||||||
fwupd
|
|
||||||
gh # MS GitHub cli
|
|
||||||
git # needed as a user package, for config.
|
|
||||||
gnupg
|
|
||||||
gocryptfs
|
|
||||||
gopass # TODO: shouldn't be needed here
|
|
||||||
gopass-jsonapi
|
|
||||||
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
|
|
||||||
lm_sensors # for sensors-detect
|
|
||||||
lshw
|
|
||||||
# memtester
|
|
||||||
neovim
|
|
||||||
# nettools
|
|
||||||
# networkmanager
|
|
||||||
nixpkgs-review
|
|
||||||
# nixos-generators
|
|
||||||
nmon
|
|
||||||
# node2nix
|
|
||||||
# oathToolkit # for oathtool
|
|
||||||
# ponymix
|
|
||||||
pulsemixer
|
|
||||||
python3
|
|
||||||
ripgrep # needed as a user package so that its user-level config file can be installed
|
|
||||||
rsync
|
|
||||||
# python3Packages.eyeD3 # music tagging
|
|
||||||
sane-scripts
|
|
||||||
sequoia
|
|
||||||
snapper
|
|
||||||
sops
|
|
||||||
speedtest-cli
|
|
||||||
# ssh-to-age
|
|
||||||
sudo
|
|
||||||
# tageditor # music tagging
|
|
||||||
unar
|
|
||||||
wireguard-tools
|
|
||||||
xdg-utils # for xdg-open
|
|
||||||
# yarn
|
|
||||||
zsh
|
|
||||||
;
|
|
||||||
};
|
|
||||||
|
|
||||||
guiPkgs = {
|
|
||||||
inherit (flattenedPkgs)
|
|
||||||
# celluloid # mpv frontend
|
|
||||||
cozy # audiobook player
|
|
||||||
# emote
|
|
||||||
evince # works on phosh
|
|
||||||
|
|
||||||
# { pkg = fluffychat-moby; persist.plaintext = [ ".local/share/chat.fluffy.fluffychat" ]; } # TODO: ship normal fluffychat on non-moby?
|
|
||||||
|
|
||||||
# foliate # e-book reader
|
|
||||||
|
|
||||||
# XXX by default fractal stores its state in ~/.local/share/<UUID>.
|
|
||||||
# after logging in, manually change ~/.local/share/keyrings/... to point it to some predictable subdir.
|
|
||||||
# then reboot (so that libsecret daemon re-loads the keyring...?)
|
|
||||||
# { pkg = fractal-latest; persist.private = [ ".local/share/fractal" ]; }
|
|
||||||
# { pkg = fractal-next; persist.private = [ ".local/share/fractal" ]; }
|
|
||||||
|
|
||||||
# "gnome.cheese"
|
|
||||||
# gnome-feeds # RSS reader (with claimed mobile support)
|
|
||||||
"gnome.file-roller"
|
|
||||||
# "gnome.gnome-maps" # works on phosh
|
|
||||||
"gnome.nautilus"
|
|
||||||
# gnome-podcasts
|
|
||||||
# "gnome.gnome-system-monitor"
|
|
||||||
# "gnome.gnome-terminal" # works on phosh
|
|
||||||
# "gnome.gnome-weather"
|
|
||||||
gpodder
|
|
||||||
gthumb
|
|
||||||
jellyfin-media-player
|
|
||||||
komikku
|
|
||||||
koreader
|
|
||||||
# lollypop
|
|
||||||
# mpv
|
|
||||||
# networkmanagerapplet
|
|
||||||
# newsflash
|
|
||||||
nheko
|
|
||||||
pavucontrol
|
|
||||||
# picard # music tagging
|
|
||||||
# "libsForQt5.plasmatube" # Youtube player
|
|
||||||
soundconverter
|
|
||||||
# sublime-music
|
|
||||||
# tdesktop # broken on phosh
|
|
||||||
# tokodon
|
|
||||||
vlc
|
|
||||||
# pleroma client (Electron). input is broken on phosh. TODO(2023/02/02): fix electron19 input (insecure)
|
|
||||||
# whalebird
|
|
||||||
xterm # broken on phosh
|
|
||||||
;
|
|
||||||
};
|
|
||||||
desktopGuiPkgs = {
|
|
||||||
inherit (flattenedPkgs)
|
|
||||||
audacity
|
|
||||||
brave # for the integrated wallet -- as a backup
|
|
||||||
chromium
|
|
||||||
dino
|
|
||||||
electrum
|
|
||||||
element-desktop
|
|
||||||
font-manager
|
|
||||||
gajim # XMPP client
|
|
||||||
gimp # broken on phosh
|
|
||||||
"gnome.dconf-editor"
|
|
||||||
"gnome.gnome-disk-utility"
|
|
||||||
# "gnome.totem" # video player, supposedly supports UPnP
|
|
||||||
handbrake
|
|
||||||
hase
|
|
||||||
inkscape
|
|
||||||
kdenlive
|
|
||||||
kid3 # audio tagging
|
|
||||||
krita
|
|
||||||
libreoffice-fresh
|
|
||||||
mumble
|
|
||||||
obsidian
|
|
||||||
slic3r
|
|
||||||
steam
|
|
||||||
wireshark # could maybe ship the cli as sysadmin pkg
|
|
||||||
;
|
|
||||||
};
|
|
||||||
x86GuiPkgs = {
|
|
||||||
inherit (pkgs)
|
|
||||||
discord
|
|
||||||
|
|
||||||
# kaiteki # Pleroma client
|
|
||||||
# gnome.zenity # for kaiteki (it will use qarma, kdialog, or zenity)
|
|
||||||
# gpt2tc # XXX: unreliable mirror
|
|
||||||
|
|
||||||
# logseq # Personal Knowledge Management
|
|
||||||
losslesscut-bin
|
|
||||||
makemkv
|
|
||||||
monero-gui
|
|
||||||
signal-desktop
|
|
||||||
spotify
|
|
||||||
tor-browser-bundle-bin
|
|
||||||
zecwallet-lite
|
|
||||||
;
|
|
||||||
};
|
|
||||||
|
|
||||||
# packages not part of any package set; not enabled by default
|
|
||||||
otherPkgs = {
|
|
||||||
inherit (pkgs)
|
|
||||||
lemmy-server
|
|
||||||
mx-sanebot
|
|
||||||
stepmania
|
|
||||||
;
|
|
||||||
};
|
|
||||||
|
|
||||||
# define -- but don't enable -- the packages in some attrset.
|
|
||||||
declarePkgs = pkgsAsAttrs: lib.mapAttrs (_n: p: {
|
|
||||||
# no need to actually define the package here: it's defaulted
|
|
||||||
# package = mkDefault p;
|
|
||||||
}) pkgsAsAttrs;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
sane.programs = lib.mkMerge [
|
|
||||||
(declarePkgs consoleMediaPkgs)
|
|
||||||
(declarePkgs consolePkgs)
|
|
||||||
(declarePkgs desktopGuiPkgs)
|
|
||||||
(declarePkgs guiPkgs)
|
|
||||||
(declarePkgs iphonePkgs)
|
|
||||||
(declarePkgs sysadminPkgs)
|
|
||||||
(declarePkgs sysadminExtraPkgs)
|
|
||||||
(declarePkgs tuiPkgs)
|
|
||||||
(declarePkgs x86GuiPkgs)
|
|
||||||
(declarePkgs otherPkgs)
|
|
||||||
{
|
|
||||||
# link the various package sets into their own meta packages
|
|
||||||
consoleMediaUtils = {
|
|
||||||
package = null;
|
|
||||||
suggestedPrograms = attrNames consoleMediaPkgs;
|
|
||||||
};
|
|
||||||
consoleUtils = {
|
|
||||||
package = null;
|
|
||||||
suggestedPrograms = attrNames consolePkgs;
|
|
||||||
};
|
|
||||||
desktopGuiApps = {
|
|
||||||
package = null;
|
|
||||||
suggestedPrograms = attrNames desktopGuiPkgs;
|
|
||||||
};
|
|
||||||
guiApps = {
|
|
||||||
package = null;
|
|
||||||
suggestedPrograms = (attrNames guiPkgs)
|
|
||||||
++ [ "web-browser" ]
|
|
||||||
++ [ "tuiApps" ]
|
|
||||||
++ lib.optional (pkgs.system == "x86_64-linux") "x86GuiApps";
|
|
||||||
};
|
|
||||||
iphoneUtils = {
|
|
||||||
package = null;
|
|
||||||
suggestedPrograms = attrNames iphonePkgs;
|
|
||||||
};
|
|
||||||
sysadminUtils = {
|
|
||||||
package = null;
|
|
||||||
suggestedPrograms = attrNames sysadminPkgs;
|
|
||||||
};
|
|
||||||
sysadminExtraUtils = {
|
|
||||||
package = null;
|
|
||||||
suggestedPrograms = attrNames sysadminExtraPkgs;
|
|
||||||
};
|
|
||||||
tuiApps = {
|
|
||||||
package = null;
|
|
||||||
suggestedPrograms = attrNames tuiPkgs;
|
|
||||||
};
|
|
||||||
x86GuiApps = {
|
|
||||||
package = null;
|
|
||||||
suggestedPrograms = attrNames x86GuiPkgs;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
# nontrivial package definitions
|
|
||||||
|
|
||||||
dino.persist.private = [ ".local/share/dino" ];
|
|
||||||
|
|
||||||
# creds, but also 200 MB of node modules, etc
|
|
||||||
discord.persist.private = [ ".config/discord" ];
|
|
||||||
|
|
||||||
# creds/session keys, etc
|
|
||||||
element-desktop.persist.private = [ ".config/Element" ];
|
|
||||||
|
|
||||||
# `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" ];
|
|
||||||
|
|
||||||
# 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" ];
|
|
||||||
|
|
||||||
# not strictly necessary, but allows caching articles; offline use, etc.
|
|
||||||
nheko.persist.private = [
|
|
||||||
".config/nheko" # config file (including client token)
|
|
||||||
".cache/nheko" # media cache
|
|
||||||
".local/share/nheko" # per-account state database
|
|
||||||
];
|
|
||||||
|
|
||||||
# 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 a crash at startup
|
|
||||||
# TODO 2023/02/02: is this safe to remove yet?
|
|
||||||
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,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,38 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
./aerc.nix
|
|
||||||
./assorted.nix
|
|
||||||
./cozy.nix
|
|
||||||
./git.nix
|
|
||||||
./gnome-feeds.nix
|
|
||||||
./gpodder.nix
|
|
||||||
./imagemagick.nix
|
|
||||||
./jellyfin-media-player.nix
|
|
||||||
./kitty
|
|
||||||
./komikku.nix
|
|
||||||
./koreader
|
|
||||||
./libreoffice.nix
|
|
||||||
./mpv.nix
|
|
||||||
./neovim.nix
|
|
||||||
./newsflash.nix
|
|
||||||
./offlineimap.nix
|
|
||||||
./ripgrep.nix
|
|
||||||
./sfeed.nix
|
|
||||||
./splatmoji.nix
|
|
||||||
./steam.nix
|
|
||||||
./sublime-music.nix
|
|
||||||
./vlc.nix
|
|
||||||
./web-browser.nix
|
|
||||||
./wireshark.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,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,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,10 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
{
|
|
||||||
sane.programs.imagemagick = {
|
|
||||||
package = pkgs.imagemagick.override {
|
|
||||||
ghostscriptSupport = true;
|
|
||||||
};
|
|
||||||
suggestedPrograms = [ "ghostscript" ];
|
|
||||||
};
|
|
||||||
sane.programs.ghostscript = {};
|
|
||||||
}
|
|
@@ -1,13 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
sane.programs.jellyfin-media-player = {
|
|
||||||
# package = pkgs.jellyfin-media-player;
|
|
||||||
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,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,46 +0,0 @@
|
|||||||
{ config, lib, 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
|
|
||||||
# enable_filter = true => only render content that matches the filter_element css selector.
|
|
||||||
let fields = [
|
|
||||||
(lib.escapeShellArg feed.url)
|
|
||||||
"limit = 5"
|
|
||||||
"download_full_article = false"
|
|
||||||
"include_images = true"
|
|
||||||
"enable_filter = false"
|
|
||||||
"filter_element = \"\""
|
|
||||||
]; in "{ ${lib.concatStringsSep ", " fields } }"
|
|
||||||
) wantedFeeds;
|
|
||||||
in {
|
|
||||||
sane.programs.koreader = {
|
|
||||||
# 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,13 +0,0 @@
|
|||||||
{ ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
sane.programs.mpv = {
|
|
||||||
persist.plaintext = [ ".config/mpv/watch_later" ];
|
|
||||||
# format is <key>=%<length>%<value>
|
|
||||||
fs.".config/mpv/mpv.conf".symlink.text = ''
|
|
||||||
save-position-on-quit=%3%yes
|
|
||||||
keep-open=%3%yes
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@@ -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/
|
|
||||||
'';
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user