Compare commits
16 Commits
6978396646
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 2bdb173ac7 | |||
| d05212ffd3 | |||
| 380b428d9a | |||
| 2a911b057b | |||
| 403cf2fde5 | |||
| 65064d971c | |||
| 875fa633c7 | |||
| 1cbca207b6 | |||
| f701177197 | |||
| 778cde8c40 | |||
| f9d5c70fb1 | |||
| 1fd25998fb | |||
| 7994f174f6 | |||
| d48e4f8a08 | |||
| dcdd2c2d90 | |||
| 9a4ed1b04b |
@@ -5,6 +5,7 @@ keys:
|
||||
- &host_t2mbp age1yr7vurfxc3w8ewfw9djfm54atw6ayze69qglamecuft5q0n9gu2sadsa2m
|
||||
- &host_ideapad age1hya7pgpe8zal52w3pjf036tpapmehedatfm4r84h30t4wuh079ssedfd37
|
||||
- &host_nix-server age1p05z980kdtngk9mw67hfev72h7xhslplpxfk9yskgmf0hl4lu3ls04zht9
|
||||
- &host_r5500 age1pewusvlcgzcnk0kpskgc9qr6jlq8s2yzwnqrnh84p7v5z0kj3qhsya8h2x
|
||||
creation_rules:
|
||||
- path_regex: secrets/[^/]+\.(yaml|json|env|ini)$
|
||||
key_groups:
|
||||
@@ -15,6 +16,7 @@ creation_rules:
|
||||
- *host_t2mbp
|
||||
- *host_ideapad
|
||||
- *host_nix-server
|
||||
- *host_r5500
|
||||
# Host secrets at modules/hosts/nix-server/secrets.yaml (see configuration imports),
|
||||
# or optional extra files under _secrets/.
|
||||
- path_regex: modules/hosts/nix-server/(secrets\.(yaml|json|env|ini)|_secrets/.*\.(yaml|json|env|ini))$
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
# chiasson-nix
|
||||
|
||||
My personal NixOS + Home Manager flake. [flake.nix](../flake.nix) feeds `./modules` through flake-parts and [import-tree](https://github.com/vic/import-tree) so config stays in small files instead of one monster module.
|
||||
|
||||
How to work on it: [conventions.md](./conventions.md).
|
||||
|
||||
## Hosts
|
||||
|
||||
| Host | What it is |
|
||||
|------|------------|
|
||||
| `t2mbp` | Intel MacBook with T2 chip — Niri/DMS, `t2linux` + fan daemon |
|
||||
| `14900k` | Main x86 desktop — same GUI stack, also cross-builds aarch64 and exports NFS for Jellyfin |
|
||||
| `ideapad` | Lenovo IdeaPad Duet 3 (Chromebook, `lenovo-wormdingler`) — Mobile NixOS on Snapdragon, Niri/DMS, touch/tablet bits in `_private/` |
|
||||
| `uConsole` | Clockwork Pi uConsole (Pi 5 CM) — Niri/DMS, built with `nixos-raspberrypi` + oom-hardware |
|
||||
| `nix-server` | Headless x86 VM — Attic, Gitea, Immich, SwiftShare, Personal-Website, DDRM, Portainer, … |
|
||||
| `r5500` | Headless media box — Jellyfin, *arr, qBittorrent, Dispatcharr; library on NFS from `nix-server` |
|
||||
|
||||
Each machine: `modules/hosts/<name>/default.nix` → `nixosConfigurations.<name>`, real config in `*Configuration` + optional `_private/` and `_services/`.
|
||||
|
||||
## Deploy / rebuild
|
||||
|
||||
Remote builds use the `builder` user (`systemDeployBuilder`, wired through `client-services` on desktops).
|
||||
|
||||
Fleet deploy is [Navi](https://github.com/cafkafk/navi) — config in `modules/deploy/navi.nix`, outputs `flake.navi` / `flake.naviHive`.
|
||||
|
||||
```bash
|
||||
nix develop # devShell has navi + hints
|
||||
navi apply --on <host>
|
||||
navi apply-local --node 14900k --sudo # this machine, if hostname matches
|
||||
```
|
||||
|
||||
Plain rebuild still works: `sudo nixos-rebuild switch --flake .#<host>`.
|
||||
|
||||
## Repo layout
|
||||
|
||||
```
|
||||
modules/
|
||||
hosts/<host>/ # per-machine composition
|
||||
system/ # nixosModules.system aggregate
|
||||
desktop/ # GUI stack
|
||||
wisdom/ # HM modules (exports still named wisdom*)
|
||||
ssh/ # inbound NixOS + outbound HM
|
||||
deploy/ # navi hive
|
||||
lib/ # pure helpers → flake.lib
|
||||
```
|
||||
|
||||
Machine-only stuff lives in `hosts/<host>/_private/` — import-tree skips `_private/` globally, so those files only get pulled in where you import them.
|
||||
@@ -0,0 +1,105 @@
|
||||
# Conventions
|
||||
|
||||
## How the flake is wired
|
||||
|
||||
`flake.nix` runs import-tree on `./modules` with a few extra filters: skip `/package/`, `/packages/`, and `dms/home-manager/` (callPackage noise + DMS HM colocation). Don't add a global `/home-manager/` filter — `modules/ssh/home-manager/` needs to load.
|
||||
|
||||
Every scanned `.nix` should be a flake fragment:
|
||||
|
||||
```nix
|
||||
{ self, inputs, ... }: {
|
||||
flake.nixosModules.systemFoo = { config, lib, pkgs, ... }: { /* … */ };
|
||||
}
|
||||
```
|
||||
|
||||
Don't define the same `flake.nixosModules.foo` in two files — merge order isn't something to bet on.
|
||||
|
||||
**Outputs I actually use:** `nixosConfigurations.*`, `nixosModules.*`, `homeManagerModules.*`, `lib.*`, `packages.*`, `navi` / `naviHive`. `modules/parts.nix` declares supported systems and the `flake.lib` / `flake.homeManagerModules` option slots.
|
||||
|
||||
## Option namespaces
|
||||
|
||||
Project options live under `chiasson.*` only:
|
||||
|
||||
| Prefix | For |
|
||||
|--------|-----|
|
||||
| `chiasson.system.*` | Machine policy — docker, flatpak, audio, gaming, deploy builder, … |
|
||||
| `chiasson.desktop.*` | GUI — compositors, DMS, wallpapers, display manager |
|
||||
| `chiasson.home.*` | Home Manager toggles (module exports are still `wisdom*`) |
|
||||
| `chiasson.users.*` | Catalog, `enabled`, `hostOverrides`, `extraModules` |
|
||||
| `chiasson.ssh.*` | SSH inventory |
|
||||
|
||||
Leave upstream `services.*`, `networking.*`, `home.*`, etc. alone.
|
||||
|
||||
## Module shape
|
||||
|
||||
**NixOS leaf** — camelCase export, usually prefixed (`systemDocker`, `desktopNiri`):
|
||||
|
||||
```nix
|
||||
{ ... }: {
|
||||
flake.nixosModules.systemSomething = { config, lib, pkgs, ... }:
|
||||
let cfg = config.chiasson.system.something;
|
||||
in {
|
||||
options.chiasson.system.something.enable = lib.mkEnableOption "…";
|
||||
config = lib.mkIf cfg.enable { /* … */ };
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Aggregates: `nixosModules.system` and `nixosModules.desktop` import their leaves. Host configs import those stacks and set options — they shouldn't reimplement whole subsystems.
|
||||
|
||||
**Home** — files under `modules/wisdom/`. Baseline is `homeManagerModules.wisdom` (`chiasson.home.enable`). Everything else is separate exports (`wisdomBrowsersZen`, …); enable on a host via `chiasson.users.extraModules.<user>` and the matching `chiasson.home.*.enable`.
|
||||
|
||||
User apps / dotfiles → wisdom. Daemons, firewall, kernel → NixOS. Sometimes both (LocalSend: HM installs, `systemLocalsend` opens the firewall).
|
||||
|
||||
**Odd exports**
|
||||
|
||||
- `"client-services"` — shared setup for laptops/tablets/desktops (not the VMs). Turns on Bluetooth, lets Navi log in as `builder` to update the machine, enables printing and mounting USB drives, and sets SSH to password. Used on `t2mbp`, `14900k`, `ideapad`, `uConsole`. Skipped on `nix-server` and `r5500`.
|
||||
- `systemUconsoleKernelBuilder` — cross-build the uConsole kernel on x86_64, not for running on the Pi.
|
||||
- `systemFlatpak` — allowlist sync; skips heavy `flatpak update` when lists unchanged (`runHeavyMaintenanceEverySwitch`).
|
||||
|
||||
**Desktop notes**
|
||||
|
||||
- `chiasson.desktop.displayManager.variant`: `sddm` vs `dankgreeter` (DMS + Hyprland/Niri tends toward DankGreeter).
|
||||
- `desktopWallpapers` copies `inputs.wallpapers` into the store; override `chiasson.desktop.wallpapers.source` if needed.
|
||||
|
||||
|
||||
## Users
|
||||
|
||||
User definitions live in `usersCatalogDefaults` (`modules/system/users/catalog-default.nix`) — olivier, server, builder, etc. Pick who exists on a host with `chiasson.users.enabled`.
|
||||
|
||||
Passwords aren't in the repo. They're in `secrets/secrets.yaml` (encrypted with sops). Each host that has `olivier` must declare that secret and set `neededForUsers = true`; sops-nix decrypts it at boot, and the catalog points `hashedPasswordFile` at that file. That's why the catalog is a proper module instead of a static list — it needs `config.sops.secrets.…` at eval time.
|
||||
|
||||
On a host:
|
||||
|
||||
```nix
|
||||
chiasson.users.enabled = [ "olivier" ];
|
||||
chiasson.users.hostOverrides.<name> = { /* optional */ };
|
||||
chiasson.users.extraModules.olivier = [
|
||||
self.homeManagerModules.wisdomTerminalsKitty
|
||||
# …
|
||||
];
|
||||
```
|
||||
|
||||
`usersHomeIntegration` turns that into `users.users` + HM. Don't hand-roll catalog users unless you're changing the users module itself.
|
||||
|
||||
SSH: `sshInbound` on NixOS, outbound/rbw under `modules/ssh/home-manager/`.
|
||||
|
||||
## Adding things
|
||||
|
||||
**New NixOS leaf:** export `flake.nixosModules.whatever`, wire from `system/default.nix` or `desktop/default.nix` if it's global, or only from a host `configuration.nix` if it's not. `nix flake check`. Git-add new paths if eval uses the git tree.
|
||||
|
||||
**New HM slice:** export `flake.homeManagerModules.wisdomFoo`, add the file to `imports` in `modules/wisdom/default.nix`, then wire `extraModules` + options on hosts that need it.
|
||||
|
||||
**Derivations:** `let` inside a fragment, or `flake.packages` / `flake.lib` — not a bare `mkDerivation` file import-tree will try to load.
|
||||
|
||||
**New host:** `hosts/<name>/default.nix` with `nixosSystem`, `configuration.nix` exporting `*Configuration`, hardware + `_private/` as needed, register in `modules/deploy/navi.nix` if it should be in the fleet.
|
||||
|
||||
## When editing
|
||||
|
||||
- `nix flake check` after touching `modules/`.
|
||||
- Stage/commit new files if the flake is read from git.
|
||||
- Small diffs; `mkEnableOption` + `mkIf` for toggles.
|
||||
- Cross-module deps: assertions or `mkDefault`, mention it in the option description.
|
||||
- New flake inputs in `flake.nix` with `follows` where versions should track nixpkgs.
|
||||
- `client-services` SSH defaults are for my LAN — don't copy to anything internet-facing without tightening.
|
||||
- If I'll forget the behavior in six months, update these docs in the same change.
|
||||
Generated
+364
-22
@@ -16,6 +16,21 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"crane": {
|
||||
"locked": {
|
||||
"lastModified": 1770169865,
|
||||
"narHash": "sha256-iPiy13xzDQ9GjpOez+NNIjh/qjl7i4RDf9dF2x5mF9I=",
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"rev": "8254ccf3b5b5131890ee073776f2e61c6d1e55d4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"cursor": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
@@ -23,11 +38,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1779537840,
|
||||
"narHash": "sha256-IS3aolEKgyL0VuMfd/QX2AHvur1YukCTa6eZdxQWe1A=",
|
||||
"lastModified": 1780452866,
|
||||
"narHash": "sha256-Fq5cR/qGYcGwOOZf6sShtM+kljwecgntgcKXnIBrQDE=",
|
||||
"ref": "refs/heads/main",
|
||||
"rev": "8d9c19f98abf47aa4504efa8d2233730b4afed50",
|
||||
"revCount": 109,
|
||||
"rev": "344f4065e69455adbcdfb4db1cd8d07a73ae7140",
|
||||
"revCount": 114,
|
||||
"type": "git",
|
||||
"url": "https://git.chiasson.cloud/Olivier/cursor-nixos-flake"
|
||||
},
|
||||
@@ -52,6 +67,7 @@
|
||||
"url": "https://git.chiasson.cloud/Olivier/DDRM"
|
||||
},
|
||||
"original": {
|
||||
"rev": "c3d014f96855e45b53f7391ce19729493887cb96",
|
||||
"type": "git",
|
||||
"url": "https://git.chiasson.cloud/Olivier/DDRM"
|
||||
}
|
||||
@@ -76,6 +92,29 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"disko": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"navi",
|
||||
"nixos-anywhere",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1769524058,
|
||||
"narHash": "sha256-zygdD6X1PcVNR2PsyK4ptzrVEiAdbMqLos7utrMDEWE=",
|
||||
"owner": "nix-community",
|
||||
"repo": "disko",
|
||||
"rev": "71a3fc97d80881e91710fe721f1158d3b96ae14d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"ref": "master",
|
||||
"repo": "disko",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"dms": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
@@ -149,6 +188,46 @@
|
||||
"inputs": {
|
||||
"nixpkgs-lib": "nixpkgs-lib_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1769996383,
|
||||
"narHash": "sha256-AnYjnFWgS49RlqX7LrC4uA+sCCDBj0Ry/WOJ5XWAsa0=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "57928607ea566b5db3ad13af0e57e921e6b12381",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-parts_3": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
"navi",
|
||||
"nixos-anywhere",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1768135262,
|
||||
"narHash": "sha256-PVvu7OqHBGWN16zSi6tEmPwwHQ4rLPU9Plvs8/1TUBY=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "80daad04eddbbf5a4d883996a73f3f542fa437ac",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-parts_4": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": "nixpkgs-lib_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1778716662,
|
||||
"narHash": "sha256-m1Yf0wZ8j1OHjTc2UwHwyQRSnNeSgLJOd7q5Y45hzi4=",
|
||||
@@ -163,7 +242,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-parts_3": {
|
||||
"flake-parts_5": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
"nur",
|
||||
@@ -186,7 +265,25 @@
|
||||
},
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems_2"
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils_2": {
|
||||
"inputs": {
|
||||
"systems": "systems_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731533236,
|
||||
@@ -274,6 +371,50 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"navi": {
|
||||
"inputs": {
|
||||
"crane": "crane",
|
||||
"flake-parts": "flake-parts_2",
|
||||
"nix-github-actions": "nix-github-actions",
|
||||
"nixos-anywhere": "nixos-anywhere",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"stable": "stable"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1777283737,
|
||||
"narHash": "sha256-sVwTOYwxzUUqAEr5kjOZooJ/v8H2hcuZ42f17MgCqX8=",
|
||||
"owner": "cafkafk",
|
||||
"repo": "navi",
|
||||
"rev": "b060683e4ca2bd37a1c3bcb4e04abd2296190e9d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cafkafk",
|
||||
"repo": "navi",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-github-actions": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"navi",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1729742964,
|
||||
"narHash": "sha256-B4mzTcQ0FZHdpeWcpDYPERtyjJd/NIuaQ9+BV1h+MpA=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-github-actions",
|
||||
"rev": "e04df33f62cdcf93d73e9a04142464753a16db67",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-github-actions",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-monitor": {
|
||||
"locked": {
|
||||
"lastModified": 1771568669,
|
||||
@@ -289,10 +430,33 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-vm-test": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"navi",
|
||||
"nixos-anywhere",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1769079217,
|
||||
"narHash": "sha256-R6qzhu+YJolxE2vUsPQWWwUKMbAG5nXX3pBtg8BNX38=",
|
||||
"owner": "Enzime",
|
||||
"repo": "nix-vm-test",
|
||||
"rev": "58c15f78947b431d6c206e0966500c7e9139bd2f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "Enzime",
|
||||
"ref": "pr-105-latest",
|
||||
"repo": "nix-vm-test",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixcord": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"flake-parts": "flake-parts_2",
|
||||
"flake-parts": "flake-parts_4",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
@@ -312,7 +476,62 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixos-anywhere": {
|
||||
"inputs": {
|
||||
"disko": "disko",
|
||||
"flake-parts": "flake-parts_3",
|
||||
"nix-vm-test": "nix-vm-test",
|
||||
"nixos-images": "nixos-images",
|
||||
"nixos-stable": "nixos-stable",
|
||||
"nixpkgs": [
|
||||
"navi",
|
||||
"nixpkgs"
|
||||
],
|
||||
"treefmt-nix": "treefmt-nix"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1772874867,
|
||||
"narHash": "sha256-d79nCSys2aaV6E1tL/H4xEeKJvLFwEeP6yj5q0glbuQ=",
|
||||
"owner": "cafkafk",
|
||||
"repo": "nixos-anywhere",
|
||||
"rev": "b88c2ee9734ce4ec5aa63cf74c2ea58f6f9970ec",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cafkafk",
|
||||
"ref": "kexec-ssh-args-bug",
|
||||
"repo": "nixos-anywhere",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixos-images": {
|
||||
"inputs": {
|
||||
"nixos-stable": [
|
||||
"navi",
|
||||
"nixos-anywhere",
|
||||
"nixos-stable"
|
||||
],
|
||||
"nixos-unstable": [
|
||||
"navi",
|
||||
"nixos-anywhere",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1766770015,
|
||||
"narHash": "sha256-kUmVBU+uBUPl/v3biPiWrk680b8N9rRMhtY97wsxiJc=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixos-images",
|
||||
"rev": "e4dba54ddb6b2ad9c6550e5baaed2fa27938a5d2",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nixos-images",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixos-images_2": {
|
||||
"inputs": {
|
||||
"nixos-stable": [
|
||||
"nixos-raspberrypi",
|
||||
@@ -342,7 +561,7 @@
|
||||
"inputs": {
|
||||
"argononed": "argononed",
|
||||
"flake-compat": "flake-compat_2",
|
||||
"nixos-images": "nixos-images",
|
||||
"nixos-images": "nixos-images_2",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
@@ -362,17 +581,33 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"nixos-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1779357205,
|
||||
"narHash": "sha256-cCO8aTqss5x9Ky8GWkpY0Hy5fyTZEbtifSUV8QjSzic=",
|
||||
"owner": "nixos",
|
||||
"lastModified": 1769598131,
|
||||
"narHash": "sha256-e7VO/kGLgRMbWtpBqdWl0uFg8Y2XWFMdz0uUJvlML8o=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "f83fc3c307e74bc5fd5adb7eb6b8b13ffd2a36e1",
|
||||
"rev": "fa83fd837f3098e3e678e6cf017b2b36102c7211",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-25.11",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1750134718,
|
||||
"narHash": "sha256-v263g4GbxXv87hMXMCpjkIxd/viIF7p3JpJrwgKdNiI=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "9e83b64f727c88a7711a2c463a7b16eedb69a84c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
@@ -394,6 +629,21 @@
|
||||
}
|
||||
},
|
||||
"nixpkgs-lib_2": {
|
||||
"locked": {
|
||||
"lastModified": 1769909678,
|
||||
"narHash": "sha256-cBEymOf4/o3FD5AZnzC3J9hLbiZ+QDT/KDuyHXVJOpM=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "72716169fe93074c333e8d0173151350670b824c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-lib_3": {
|
||||
"locked": {
|
||||
"lastModified": 1777168982,
|
||||
"narHash": "sha256-GOkGPcboWE9BmGCRMLX3worL4EMnsnG8MyKmXNeYuhQ=",
|
||||
@@ -425,6 +675,22 @@
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1779357205,
|
||||
"narHash": "sha256-cCO8aTqss5x9Ky8GWkpY0Hy5fyTZEbtifSUV8QjSzic=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "f83fc3c307e74bc5fd5adb7eb6b8b13ffd2a36e1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1778869304,
|
||||
"narHash": "sha256-30sZNZoA1cqF5JNO9fVX+wgiQYjB7HJqqJ4ztCDeBZE=",
|
||||
@@ -442,7 +708,7 @@
|
||||
},
|
||||
"nur": {
|
||||
"inputs": {
|
||||
"flake-parts": "flake-parts_3",
|
||||
"flake-parts": "flake-parts_5",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
@@ -485,6 +751,27 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"personal-website": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1779906441,
|
||||
"narHash": "sha256-py8KJJMi4awjZHi5FWBPYfbRPvk3Rg9SeFkPJydsG2E=",
|
||||
"ref": "refs/heads/main",
|
||||
"rev": "339a9ba1ef79dc9976af77f1fea0302de8a696d0",
|
||||
"revCount": 16,
|
||||
"type": "git",
|
||||
"url": "https://git.chiasson.cloud/Olivier/Personal-Website"
|
||||
},
|
||||
"original": {
|
||||
"type": "git",
|
||||
"url": "https://git.chiasson.cloud/Olivier/Personal-Website"
|
||||
}
|
||||
},
|
||||
"quickshell": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
@@ -517,12 +804,14 @@
|
||||
"home-manager": "home-manager",
|
||||
"import-tree": "import-tree",
|
||||
"mobile-nixos": "mobile-nixos",
|
||||
"navi": "navi",
|
||||
"nix-monitor": "nix-monitor",
|
||||
"nixcord": "nixcord",
|
||||
"nixos-raspberrypi": "nixos-raspberrypi",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"nixpkgs": "nixpkgs_2",
|
||||
"nur": "nur",
|
||||
"oom-hardware": "oom-hardware",
|
||||
"personal-website": "personal-website",
|
||||
"sops-nix": "sops-nix",
|
||||
"spicetify-nix": "spicetify-nix",
|
||||
"swiftshare": "swiftshare",
|
||||
@@ -558,7 +847,7 @@
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": "systems"
|
||||
"systems": "systems_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1779000518,
|
||||
@@ -574,9 +863,25 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"stable": {
|
||||
"locked": {
|
||||
"lastModified": 1750133334,
|
||||
"narHash": "sha256-urV51uWH7fVnhIvsZIELIYalMYsyr2FCalvlRTzqWRw=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "36ab78dab7da2e4e27911007033713bab534187b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-25.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"swiftshare": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"flake-utils": "flake-utils_2",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
@@ -625,6 +930,21 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_3": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"t2fanrd": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
@@ -648,11 +968,11 @@
|
||||
"t2linux-patches": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1779369552,
|
||||
"narHash": "sha256-vDcWjgjhYAQcXZH40QN17ZV9BS0zqZeme9APXBqjlHs=",
|
||||
"lastModified": 1779914035,
|
||||
"narHash": "sha256-VsHuI2CbQ8gFplW+51gUJvCqo1Ts10Ueks9aTtkAOiw=",
|
||||
"owner": "t2linux",
|
||||
"repo": "linux-t2-patches",
|
||||
"rev": "716093d3244566cd708362661de269ab7e67ff0f",
|
||||
"rev": "7ee7d19c38e5df31a386b2a0c35ca8f064003960",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -661,6 +981,28 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"treefmt-nix": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"navi",
|
||||
"nixos-anywhere",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1769691507,
|
||||
"narHash": "sha256-8aAYwyVzSSwIhP2glDhw/G0i5+wOrren3v6WmxkVonM=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "28b19c5844cc6e2257801d43f2772a4b4c050a1b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"wallpapers": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
@@ -679,7 +1021,7 @@
|
||||
},
|
||||
"wrapper-modules": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
"nixpkgs": "nixpkgs_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1779297405,
|
||||
|
||||
@@ -92,11 +92,19 @@
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
# DDRM browser-extension backend
|
||||
ddrm = {
|
||||
url = "git+https://git.chiasson.cloud/Olivier/DDRM";
|
||||
# After pushing Personal-Website, `nix flake update personal-website` refreshes the lock pin.
|
||||
personal-website = {
|
||||
url = "git+https://git.chiasson.cloud/Olivier/Personal-Website";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
# DDRM browser-extension backend
|
||||
ddrm = {
|
||||
url = "git+https://git.chiasson.cloud/Olivier/DDRM?rev=c3d014f96855e45b53f7391ce19729493887cb96";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
navi.url = "github:cafkafk/navi";
|
||||
};
|
||||
|
||||
outputs = inputs:
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
{
|
||||
inputs,
|
||||
self,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
ssh = self.lib.sshInventory;
|
||||
|
||||
# Remote deploy identity (see `nixosModules.systemDeployBuilder`).
|
||||
defaultTargetUser = _: "builder";
|
||||
|
||||
hostSpecs = {
|
||||
"14900k" = {
|
||||
configuration = self.nixosModules."14900kConfiguration";
|
||||
system = "x86_64-linux";
|
||||
specialArgs = {
|
||||
inherit self inputs;
|
||||
host = "14900k";
|
||||
system = "x86_64-linux";
|
||||
};
|
||||
};
|
||||
ideapad = {
|
||||
configuration = self.nixosModules.ideapadConfiguration;
|
||||
system = "aarch64-linux";
|
||||
specialArgs = {
|
||||
inherit self inputs;
|
||||
host = "ideapad";
|
||||
system = "aarch64-linux";
|
||||
};
|
||||
};
|
||||
t2mbp = {
|
||||
configuration = self.nixosModules.t2mbpConfiguration;
|
||||
system = "x86_64-linux";
|
||||
specialArgs = {
|
||||
inherit self inputs;
|
||||
host = "t2mbp";
|
||||
system = "x86_64-linux";
|
||||
};
|
||||
};
|
||||
uConsole = {
|
||||
modules = [
|
||||
inputs.nixos-raspberrypi.nixosModules.raspberry-pi-5.base
|
||||
inputs.oom-hardware.nixosModules.uc.kernel
|
||||
inputs.oom-hardware.nixosModules.uc.configtxt
|
||||
inputs.oom-hardware.nixosModules.uc.base-cm5
|
||||
self.nixosModules.uConsoleConfiguration
|
||||
];
|
||||
system = "aarch64-linux";
|
||||
specialArgs = inputs // {
|
||||
inherit self;
|
||||
inputs = inputs;
|
||||
host = "uConsole";
|
||||
system = "aarch64-linux";
|
||||
};
|
||||
};
|
||||
nix-server = {
|
||||
configuration = self.nixosModules.nix-serverConfiguration;
|
||||
system = "x86_64-linux";
|
||||
specialArgs = {
|
||||
inherit self inputs;
|
||||
host = "nix-server";
|
||||
system = "x86_64-linux";
|
||||
};
|
||||
};
|
||||
r5500 = {
|
||||
configuration = self.nixosModules.r5500Configuration;
|
||||
system = "x86_64-linux";
|
||||
specialArgs = {
|
||||
inherit self inputs;
|
||||
host = "r5500";
|
||||
system = "x86_64-linux";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
deployments = lib.mapAttrs (
|
||||
name: entry:
|
||||
{
|
||||
targetHost = entry.hostName;
|
||||
targetUser = defaultTargetUser name;
|
||||
tags =
|
||||
[ name ]
|
||||
++ lib.optionals (name == "nix-server") [ "server" ]
|
||||
++ lib.optionals (lib.elem name [
|
||||
"ideapad"
|
||||
"uConsole"
|
||||
]) [ "aarch64" ];
|
||||
}
|
||||
// lib.optionalAttrs (name == "14900k") {
|
||||
allowLocalDeployment = true;
|
||||
}
|
||||
// lib.optionalAttrs (name == "nix-server") {
|
||||
targetPort = 22;
|
||||
}
|
||||
) ssh.activeHosts;
|
||||
|
||||
metaNixpkgs = import inputs.nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
};
|
||||
in
|
||||
{
|
||||
flake.navi = self.lib.mkNaviHiveConfig {
|
||||
inherit metaNixpkgs hostSpecs deployments;
|
||||
};
|
||||
|
||||
flake.naviHive = inputs.navi.lib.makeHive self.outputs.navi;
|
||||
|
||||
perSystem =
|
||||
{
|
||||
pkgs,
|
||||
system,
|
||||
...
|
||||
}:
|
||||
lib.optionalAttrs (lib.elem system [
|
||||
"x86_64-linux"
|
||||
"aarch64-linux"
|
||||
]) {
|
||||
devShells.default = pkgs.mkShell {
|
||||
packages = [ inputs.navi.packages.${system}.default ];
|
||||
shellHook = ''
|
||||
echo "Navi fleet deploy (from repo root):"
|
||||
echo " navi apply --on <host> # build + switch one host"
|
||||
echo " navi apply-local --node 14900k --sudo # switch this machine locally (needs root), --node if hostname differs"
|
||||
echo " navi tui # interactive fleet dashboard"
|
||||
'';
|
||||
};
|
||||
|
||||
apps = {
|
||||
navi = {
|
||||
type = "app";
|
||||
program = lib.getExe inputs.navi.packages.${system}.default;
|
||||
};
|
||||
navi-tui = {
|
||||
type = "app";
|
||||
program =
|
||||
toString (
|
||||
pkgs.writeShellApplication {
|
||||
name = "navi-tui";
|
||||
runtimeInputs = [ inputs.navi.packages.${system}.default ];
|
||||
text = ''
|
||||
exec navi tui "$@"
|
||||
'';
|
||||
}
|
||||
);
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -149,7 +149,7 @@ in {
|
||||
|
||||
# Core features
|
||||
enableSystemMonitoring = true; # System monitoring widgets (dgop)
|
||||
dgop.package = inputs.dgop.packages.${pkgs.system}.default;
|
||||
dgop.package = inputs.dgop.packages.${pkgs.stdenv.hostPlatform.system}.default;
|
||||
enableVPN = true; # VPN management widget
|
||||
enableDynamicTheming = true; # Wallpaper-based theming (matugen)
|
||||
enableAudioWavelength = true; # Audio visualizer (cava)
|
||||
@@ -355,7 +355,7 @@ in {
|
||||
syncModeWithPortal = true;
|
||||
terminalsAlwaysDark = true;
|
||||
|
||||
showDock = true;
|
||||
showDock = false;
|
||||
dockAutoHide = true;
|
||||
dockGroupByApp = true;
|
||||
dockOpenOnOverview = false;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"name": "Bitwarden (rbw) lock",
|
||||
"description": "Bar control for rbw vault: locked/unlocked padlock; click to unlock or lock",
|
||||
"version": "1.0.0",
|
||||
"author": "NixOS-V2",
|
||||
"author": "chiasson.cloud",
|
||||
"type": "widget",
|
||||
"capabilities": ["dankbar-widget"],
|
||||
"component": "./RbwLockToggle.qml",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"name": "Virtual Keyboard Toggle",
|
||||
"description": "Bar button to show/hide the wvkbd on-screen keyboard (for touch/tablet)",
|
||||
"version": "1.0.0",
|
||||
"author": "NixOS-V2",
|
||||
"author": "chiasson.cloud",
|
||||
"type": "widget",
|
||||
"capabilities": ["dankbar-widget"],
|
||||
"component": "./WvkbdToggle.qml",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
guiEnabled = d.hyprland.enable || d.niri.enable || d.plasma.enable;
|
||||
|
||||
wallpaperDir = pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "nixos-v2-wallpapers";
|
||||
pname = "chiasson-nix-wallpapers";
|
||||
version = "0.1";
|
||||
src = builtins.path {
|
||||
path = cfg.source;
|
||||
@@ -26,7 +26,7 @@
|
||||
{
|
||||
options.chiasson.desktop.wallpapers = {
|
||||
enable = lib.mkEnableOption ''
|
||||
Copy `source` into the store; sets `NIXOS_V2_WALLPAPERS` and `/etc/wallpapers`.
|
||||
Copy `source` into the store; sets `CHIASSON_NIX_WALLPAPERS` and `/etc/wallpapers`.
|
||||
'' // {
|
||||
default = true;
|
||||
};
|
||||
@@ -43,8 +43,8 @@
|
||||
|
||||
config = lib.mkIf (guiEnabled && cfg.enable) {
|
||||
environment = {
|
||||
variables.NIXOS_V2_WALLPAPERS = installPath;
|
||||
sessionVariables.NIXOS_V2_WALLPAPERS = installPath;
|
||||
variables.CHIASSON_NIX_WALLPAPERS = installPath;
|
||||
sessionVariables.CHIASSON_NIX_WALLPAPERS = installPath;
|
||||
etc."wallpapers".source = installPath;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# NFS exports from nixdesk (14900k) to nix-server (192.168.2.238):
|
||||
# NFS exports from nixdesk (14900k) to r5500 (192.168.2.100), formerly nix-server (192.168.2.238):
|
||||
# - /mnt/deep/jellyfin → nix-server /mnt/nixdesk-jellyfin (Jellyfin bulk libraries)
|
||||
#
|
||||
# Jellyfin root on nixdesk uses owner olivier + group nfsmedia (990); dirs here are 2775 so
|
||||
@@ -48,7 +48,8 @@ in
|
||||
# Squash nix-server clients to olivier:nfsmedia so Jellyfin can write .nfo/posters into
|
||||
# existing olivier-owned library folders (990-only squash was "other" r-x on typical 755 trees).
|
||||
exports = ''
|
||||
/mnt/deep/jellyfin 192.168.2.238(rw,sync,no_subtree_check,crossmnt,root_squash,all_squash,anonuid=${toString olivierUid},anongid=990,fsid=1)
|
||||
/mnt/deep/jellyfin 192.168.2.100(rw,sync,no_subtree_check,crossmnt,root_squash,all_squash,anonuid=${toString olivierUid},anongid=990,fsid=1)
|
||||
/mnt/deep/jellyfin 192.168.2.238(rw,sync,no_subtree_check,crossmnt,root_squash,all_squash,anonuid=${toString olivierUid},anongid=990,fsid=2)
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# Moonfin 2.0.0 Jellyfin client — upstream Flatpak bundle (not on Flathub yet).
|
||||
# https://github.com/Moonfin-Client/Moonfin-Core/releases/tag/2.0.0
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
chiasson.system.flatpak.bundles = [
|
||||
{
|
||||
appId = "org.moonfin.linux";
|
||||
bundle = pkgs.fetchurl {
|
||||
url = "https://github.com/Moonfin-Client/Moonfin-Core/releases/download/2.0.0/Moonfin_Linux_v2.0.0.flatpak";
|
||||
hash = "sha256-sLtrsqBaJ1wriTkIdLylqMc9ygNkHrNm4YS/816nIFQ=";
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -19,6 +19,7 @@
|
||||
./_private/displays.nix
|
||||
./_private/media-disk.nix
|
||||
./_private/jellyfin-nfs-export.nix
|
||||
./_private/moonfin-flatpak.nix
|
||||
];
|
||||
|
||||
sops = {
|
||||
@@ -96,6 +97,8 @@ services.cloudflare-warp.enable = true;
|
||||
gaming.launchers.enableBottles = false;
|
||||
gaming.gamescope.enable = true;
|
||||
gaming.steam.steamTinkerLaunch.enable = true;
|
||||
gaming.sunshine.enable = true;
|
||||
gaming.sunshine.cudaSupport = true;
|
||||
|
||||
monitorInput.enable = true;
|
||||
|
||||
@@ -124,6 +127,9 @@ services.cloudflare-warp.enable = true;
|
||||
thunderbird
|
||||
|
||||
prismlauncher
|
||||
dualsensectl
|
||||
|
||||
devenv
|
||||
];
|
||||
|
||||
|
||||
@@ -158,8 +164,10 @@ services.cloudflare-warp.enable = true;
|
||||
{
|
||||
programs.git = {
|
||||
enable = true;
|
||||
userName = "OlivierChiasson";
|
||||
userEmail = "olivierchiasson@hotmail.fr";
|
||||
settings.user = {
|
||||
name = "OlivierChiasson";
|
||||
email = "olivierchiasson@hotmail.fr";
|
||||
};
|
||||
};
|
||||
|
||||
chiasson.home = {
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
{ self, ... }: {
|
||||
#TODO[epic=Moderate] Move this somewhere else, would prefer not relying on this module
|
||||
flake.nixosModules."client-services" = { ... }: {
|
||||
imports = [ self.nixosModules.systemBluetooth ];
|
||||
imports = [
|
||||
self.nixosModules.systemBluetooth
|
||||
self.nixosModules.systemDeployBuilder
|
||||
];
|
||||
|
||||
chiasson.system.deploy.builder.enable = true;
|
||||
|
||||
# Lab-ish SSH defaults on clients — tighten for anything exposed.
|
||||
services.openssh = {
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
# Per-session tablet-mode / autorotate daemons live in `_private/touch-tablet.nix`.
|
||||
chiasson.desktop = {
|
||||
niri.enable = true;
|
||||
hyprland.enable = true;
|
||||
hyprland.enable = false;
|
||||
|
||||
defaultSession = "niri";
|
||||
shell = "dms";
|
||||
@@ -120,7 +120,7 @@
|
||||
"-lc"
|
||||
''
|
||||
ssh -t olivier@nixdesk \
|
||||
"nixos-rebuild switch --flake path:/home/olivier/NixOS-V2#ideapad --target-host olivier@ideapad --sudo --ask-sudo-password 2>&1"
|
||||
"nixos-rebuild switch --flake path:/home/olivier/chiasson-nix#ideapad --target-host olivier@ideapad --sudo --ask-sudo-password 2>&1"
|
||||
''
|
||||
];
|
||||
};
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# personal-website sops secrets
|
||||
|
||||
Add these keys to `secrets.yaml` (on a host with your age key):
|
||||
|
||||
```yaml
|
||||
personal-website:
|
||||
ghcr-token: <same PAT as swiftshare/ghcr-token, or new>
|
||||
database-password: <strong password>
|
||||
auth-secret: <openssl rand -base64 32>
|
||||
oauth-discord-client-secret: <Discord OAuth secret>
|
||||
```
|
||||
|
||||
```bash
|
||||
cd modules/hosts/nix-server
|
||||
sops secrets.yaml
|
||||
```
|
||||
|
||||
After editing, verify with `sops -d secrets.yaml | yq '.personal-website'`.
|
||||
@@ -0,0 +1,26 @@
|
||||
# Cloudflare dynamic DNS via NixOS (kissgyorgy/cloudflare-dyndns).
|
||||
{ config, ... }:
|
||||
let
|
||||
secretFilePath = ../secrets.yaml;
|
||||
in
|
||||
{
|
||||
sops.secrets."cloudflare-ddns/api-token".sopsFile = secretFilePath;
|
||||
|
||||
services.cloudflare-dyndns = {
|
||||
enable = true;
|
||||
apiTokenFile = config.sops.secrets."cloudflare-ddns/api-token".path;
|
||||
domains = [
|
||||
"chiasson.cloud"
|
||||
"chiassoncloud.services"
|
||||
"swiftshare.cloud"
|
||||
"blackfry.day"
|
||||
"yestur.day"
|
||||
"rp-own.life"
|
||||
"xn--1iu.cc"
|
||||
];
|
||||
proxied = true;
|
||||
ipv4 = true;
|
||||
ipv6 = false;
|
||||
# Default: *:0/5 (every 5 minutes).
|
||||
};
|
||||
}
|
||||
@@ -9,7 +9,9 @@
|
||||
{
|
||||
systemd.tmpfiles.settings."nix-server-dispatcharr-data" = {
|
||||
"/var/lib/dispatcharr"."d" = {
|
||||
mode = "0755";
|
||||
# Dispatcharr runs as a non-root user inside the container; keep /data writable.
|
||||
# (Plugins like EPG Janitor write to `/data/*.json`.)
|
||||
mode = "0777";
|
||||
user = "root";
|
||||
group = "root";
|
||||
};
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
{ lib, ... }:
|
||||
{
|
||||
services.gitea = {
|
||||
enable = true;
|
||||
|
||||
# Migrated sqlite DB and repos; do not provision a fresh database.
|
||||
database = {
|
||||
type = "sqlite3";
|
||||
createDatabase = false;
|
||||
};
|
||||
|
||||
settings = {
|
||||
server = {
|
||||
DOMAIN = "git.chiasson.cloud";
|
||||
HTTP_PORT = 3002;
|
||||
ROOT_URL = "https://git.chiasson.cloud/";
|
||||
# Clone URLs and LAN git@… -p 222 (was Docker host 222 → container 22).
|
||||
# Port 222 is <1024 (privileged); systemd must grant CAP_NET_BIND_SERVICE below.
|
||||
SSH_PORT = 222;
|
||||
START_SSH_SERVER = true;
|
||||
SSH_LISTEN_HOST = "0.0.0.0";
|
||||
SSH_LISTEN_PORT = 222;
|
||||
};
|
||||
|
||||
service.DISABLE_REGISTRATION = false;
|
||||
};
|
||||
};
|
||||
|
||||
# First boot after migration runs DB migrate + hook regen; default WatchdogSec=30 kills
|
||||
# gitea while storage/actions init is still running. Type=notify also fails if startup
|
||||
# is slow; PrivateUsers breaks access to migrated files owned by the real gitea uid.
|
||||
# Port 222 is privileged (<1024); Docker mapped host 222→container 22 as root.
|
||||
systemd.services.gitea.serviceConfig = {
|
||||
Type = lib.mkForce "simple";
|
||||
PrivateUsers = lib.mkForce false;
|
||||
NoNewPrivileges = lib.mkForce false;
|
||||
AmbientCapabilities = "CAP_NET_BIND_SERVICE";
|
||||
CapabilityBoundingSet = lib.mkForce [ "CAP_NET_BIND_SERVICE" ];
|
||||
TimeoutStartSec = lib.mkForce "20min";
|
||||
WatchdogSec = lib.mkForce 0;
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
3002
|
||||
222
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
{ config, ... }:
|
||||
let
|
||||
secretFilePath = ../secrets.yaml;
|
||||
in
|
||||
{
|
||||
sops.secrets."personal-website/database-password".sopsFile = secretFilePath;
|
||||
sops.secrets."personal-website/auth-secret".sopsFile = secretFilePath;
|
||||
sops.secrets."personal-website/oauth-discord-client-secret".sopsFile = secretFilePath;
|
||||
|
||||
sops.templates."personal-website-postgres.env" = {
|
||||
content = ''
|
||||
POSTGRES_PASSWORD=${config.sops.placeholder."personal-website/database-password"}
|
||||
POSTGRES_USER=chiassoncloud
|
||||
POSTGRES_DB=chiassoncloud
|
||||
'';
|
||||
};
|
||||
|
||||
sops.templates."personal-website.env" = {
|
||||
content = ''
|
||||
DATABASE_URL=postgresql://chiassoncloud:${config.sops.placeholder."personal-website/database-password"}@personal-website-db:5432/chiassoncloud
|
||||
AUTH_SECRET=${config.sops.placeholder."personal-website/auth-secret"}
|
||||
AUTH_DISCORD_SECRET=${config.sops.placeholder."personal-website/oauth-discord-client-secret"}
|
||||
'';
|
||||
};
|
||||
|
||||
services.personalWebsite = {
|
||||
enable = true;
|
||||
|
||||
app = {
|
||||
image = "ghcr.io/olivierchiasson/personal-website:main";
|
||||
ghcr = {
|
||||
username = "olivierchiasson";
|
||||
passwordFile = config.sops.secrets."swiftshare/ghcr-token".path;
|
||||
};
|
||||
|
||||
port = 3001;
|
||||
authUrl = "https://chiasson.cloud";
|
||||
publicUrl = "https://chiasson.cloud";
|
||||
disableTelemetry = true;
|
||||
environmentFiles = [ config.sops.templates."personal-website.env".path ];
|
||||
};
|
||||
|
||||
database = {
|
||||
user = "chiassoncloud";
|
||||
name = "chiassoncloud";
|
||||
environmentFiles = [ config.sops.templates."personal-website-postgres.env".path ];
|
||||
};
|
||||
|
||||
auth.discord.clientId = "1400660345068191855";
|
||||
|
||||
umami = {
|
||||
websiteId = "3b2f29d3-11b8-4a3b-bc76-bda3f27926d1";
|
||||
scriptUrl = "https://analytics.chiasson.cloud/script.js";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -10,25 +10,19 @@
|
||||
{
|
||||
imports = [
|
||||
inputs.ddrm.nixosModules.default
|
||||
self.nixosModules.systemDeployBuilder
|
||||
self.nixosModules.nix-serverHardware
|
||||
inputs.sops-nix.nixosModules.sops
|
||||
self.nixosModules.system
|
||||
self.nixosModules.users
|
||||
./_services/attic-cache-server.nix
|
||||
./_services/portainer.nix
|
||||
./_services/organizr.nix
|
||||
./_services/swiftshare.nix
|
||||
./_services/personal-website.nix
|
||||
./_services/immich.nix
|
||||
./_services/jellyfin.nix
|
||||
./_services/nixdesk-nfs-client.nix
|
||||
./_services/ddrm-media-server.nix
|
||||
./_services/sonarr.nix
|
||||
./_services/prowlarr.nix
|
||||
./_services/flaresolverr.nix
|
||||
./_services/radarr.nix
|
||||
./_services/qbittorrent.nix
|
||||
./_services/seerr.nix
|
||||
./_services/dispatcharr.nix
|
||||
./_services/gitea.nix
|
||||
./_services/cloudflare-dyndns.nix
|
||||
];
|
||||
|
||||
boot.loader.grub = {
|
||||
@@ -80,6 +74,8 @@
|
||||
extraPackages = with pkgs; [ btop ];
|
||||
};
|
||||
|
||||
chiasson.system.deploy.builder.enable = true;
|
||||
|
||||
chiasson.users = {
|
||||
enabled = [ "server" ];
|
||||
hostOverrides.server = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
swiftshare:
|
||||
ghcr-token: ENC[AES256_GCM,data:wNzBA8Ib5WjxoKkGiWkfeGspKzy/vzbwwAp/+cjRF9Vsmlyx67OovQ==,iv:MCrkALYCHiPDb1tNQaWRrxuYSRXD6JtzJzEOr1aqhBk=,tag:okQfIP5IJUUIFfwAlZM1ow==,type:str]
|
||||
ghcr-token: ENC[AES256_GCM,data:V/5dLVLv4BbAxdMiBxXgmNbK17HAQkqzHJA2NWzOFfFlcy3dq8SnZQ==,iv:YTB3Bef+kZXunXVUCkFj/YZo1POdx2K+bNvzarSJ1Iw=,tag:HEBT4ZKMXTIy+ZEkNx3rHw==,type:str]
|
||||
database-password: ENC[AES256_GCM,data:r9GSaoQ7bS644ipb3kU=,iv:KYDTzYtjfz5meDb0nemY1lhSFEorKHL0hSRIcQaHg5c=,tag:RVjAfb8XGsybAgIc2/hH+g==,type:str]
|
||||
auth-secret: ENC[AES256_GCM,data:tTXLMWASBfF49gBFrf+CZ3R4oTt7hEGUhAqEdvoQtm0zbb2VUhTq7y4tH/c=,iv:Halfu9hBex4SEUMHLAicqApTxZP0NV9pJZTr+bBSek4=,tag:1WqN75zT+zoka9sIXOJGfQ==,type:str]
|
||||
oauth-discord-client-secret: ENC[AES256_GCM,data:a9Iarcpl1HOFXdsDMh3H662T8yqVvGtfguVICwWVrAg=,iv:LsUserWQcEDV0TiRWj1sHh5/ZiFQzyc1gRWg+Ewwjik=,tag:33Ml08oHVXl0ZMmiwQ2mig==,type:str]
|
||||
@@ -11,10 +11,15 @@ swiftshare:
|
||||
minio-secret-key: ENC[AES256_GCM,data:szkx+MTbMWmfbQ==,iv:+1zlHJRKMR4XDv1rrkOeilz06YA1W/1o+egylm/ZjPs=,tag:70QO3dPp9WRd71Puzl47QA==,type:str]
|
||||
immich:
|
||||
database-password: ENC[AES256_GCM,data:YWLt2pty/yVrrF7K,iv:uqrQGfST/A6LzRZ4+O0puXA1bd/7CL5A/T7jU+/++X8=,tag:/gNGK3z4RembX+tBET4M5g==,type:str]
|
||||
personal-website:
|
||||
database-password: ENC[AES256_GCM,data:PR6nNKOqB/SE956hXA4=,iv:/1usgEXfY+ef9bOAaCdjduqBqoonAm5saFBSjdGhm1Q=,tag:mDThIsYVUKyN6vQlh2YYbQ==,type:str]
|
||||
auth-secret: ENC[AES256_GCM,data:NHY+0tOA6FRmvkKZ/KgpogwOf+DuF42aoxspPUdVSi/iY5dF2yY8hwHaehI=,iv:9Gv/1YDcU+rMuX3PrwwT97qdsywIn+/wWEk17evyloo=,tag:R6RZbRhyXkwfZ0p/fZ+YcA==,type:str]
|
||||
oauth-discord-client-secret: ENC[AES256_GCM,data:YegPgoSRKNcDaID9LPWxHDz4T7VnhFfuWMyALfFhpg8=,iv:VSLWA1HG1+Y70tKnRoFulBZSKdoJTYmIDzCXIZeFYCc=,tag:yNR8rrm/7Mrj/RIVNLFfsg==,type:str]
|
||||
cloudflare-ddns:
|
||||
api-token: ENC[AES256_GCM,data:wFKbclETO0YQTcfNUdKyr6mxQODeiaYn3gLeC1mWeRda97rOvlum+Q==,iv:IuT4exNhh0z+9DbY3WNnVqEy4398DTm7aluhOv9XFss=,tag:GGPoSJLBScTmXyQ7Vab6EA==,type:str]
|
||||
sops:
|
||||
age:
|
||||
- recipient: age1yyzgmazjxkvwtfcv9re3lqmt2ru5dcrfu3sauysm0wzfwzvyap8qkjkq32
|
||||
enc: |
|
||||
- enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBlVWpFK2RRSHRxVFVSdEdI
|
||||
S01BSEZQUTZCV0tvM1lpSFNYc3g3ek5QNjJrClNyVUtKYnRtWVRYRkE2SStWRVRR
|
||||
@@ -22,8 +27,8 @@ sops:
|
||||
ZUpnemRBSmlSZVpmRW0wNFhIK3BibVkKdD14ki8dJbYMjsBkC1Nm5TOM6M33eLJ6
|
||||
IUrKDWeZXEVe2sMhBb31Zv+tinwtHSsvpxDIsjstpxtH+5wTyoQVdA==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1elk6zwmcylwfk7gd4pjda7g29upftjvxys8py42s8d42jklnyv7s7dm9z2
|
||||
enc: |
|
||||
recipient: age1yyzgmazjxkvwtfcv9re3lqmt2ru5dcrfu3sauysm0wzfwzvyap8qkjkq32
|
||||
- enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA1bFJDNDdsWGIzMDl3TmRr
|
||||
MStsZVFRa1dIVmJGU3krWWlpc2FZMU9EREF3CkdDZFc0Y3ZIMVZxNHorWFRHaWwy
|
||||
@@ -31,8 +36,8 @@ sops:
|
||||
NUZIYnZIMDRWTXpwTURMc2tzelp3VjAKHHBkHhz+t03W0ojsOBB2i3K4ZMUXvrwF
|
||||
4mjNqNBcAJ1uHgJP7qvpNjxEW1LcsdQKmXavoqizX+XfLaA3zEwB0Q==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1p05z980kdtngk9mw67hfev72h7xhslplpxfk9yskgmf0hl4lu3ls04zht9
|
||||
enc: |
|
||||
recipient: age1elk6zwmcylwfk7gd4pjda7g29upftjvxys8py42s8d42jklnyv7s7dm9z2
|
||||
- enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAwTWR0N3UwdTB0UDZxRmV5
|
||||
R3dkYUhZaElMbkxxSllTNWkrb05VSkJrMUNRCjZTUTlvVTU2MHY5ZS9oU2pCSlFu
|
||||
@@ -40,7 +45,8 @@ sops:
|
||||
WWZwbkR4dTFjK2NZcW9pTTNHd252N3cKiz8l9AWciFOBU+wcT9T1WA4bToPYfq8G
|
||||
Nf0uOoSWPTJ/2SRNkSu7FMumATH4ldQ6TFSwKda3mBfBwhnFzLq10Q==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2026-04-30T18:45:45Z"
|
||||
mac: ENC[AES256_GCM,data:DD9NZcYQVSByaQvGAB7b/Wpk7SWBBsWtzAM9MkIHMmyxNomiPPUFQR6+18QDUCHQXk1xXMUi79bnTRz8SdoBXVjbHG8Qhy3n6D1sFeEgXC42pgem7hBPfmJlgcIPNYEguXPISLsp/Zx9ISEnH5Zul0v8/G2ACN7Y/U3jtaHx4U8=,iv:g1k16EhTR+t9jCpvhmiXYZV99aMk1DrS4frpl5q93lM=,tag:FigaXNw+IbpZ7E0a+ySb3g==,type:str]
|
||||
recipient: age1p05z980kdtngk9mw67hfev72h7xhslplpxfk9yskgmf0hl4lu3ls04zht9
|
||||
lastmodified: "2026-05-28T21:04:07Z"
|
||||
mac: ENC[AES256_GCM,data:L53UYFh5xtuMx19GKAg3jW7U0/DlwJ2usy/pup+4t1HQN3KHxMwbc4BzLYkLnRBTwKMJdfKXiYmmYiYvfbbWzsPtfXLxPnF/5ROiCJ2NlxAe86SmRy2nI++eTHAXRgexIhYyL7SchsroGRvW2B3aL1jV+Eu11fD9trA9Ex1EfuI=,iv:XrRJCFSgwW2+N+4FnWrFFZz8UEVzhuhpRtHGtf8dyqc=,tag:LcO4+ilwKdU+JPyjyKaGNw==,type:str]
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.12.2
|
||||
version: 3.13.1
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
# Media stack storage on r5500: btrfs subvolume @media-stack on the OS disk (sda4).
|
||||
{ config, pkgs, lib, ... }:
|
||||
let
|
||||
btrfsUuid = "934a5ec3-4bab-49c3-96c9-c857c50076ba";
|
||||
btrfsDevice = "/dev/disk/by-uuid/${btrfsUuid}";
|
||||
# Created under subvol=@ → full path is @/@media-stack (not a top-level @media-stack).
|
||||
mediaSubvol = "@/@media-stack";
|
||||
in
|
||||
{
|
||||
# Create @media-stack before /mnt/media-stack is mounted.
|
||||
systemd.services.r5500-media-stack-subvolume = {
|
||||
description = "Create btrfs subvolume @media-stack on sda4 if missing";
|
||||
before = [ "mnt-media\\x2dmedia\\x2dstack.mount" ];
|
||||
wantedBy = [ "local-fs-pre.target" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = ''
|
||||
rootMount="/mnt/.r5500-btrfs-root"
|
||||
mkdir -p "$rootMount"
|
||||
if ! mountpoint -q "$rootMount"; then
|
||||
mount -o subvol=@ "${btrfsDevice}" "$rootMount"
|
||||
umountAfter=1
|
||||
else
|
||||
umountAfter=0
|
||||
fi
|
||||
if ! ${pkgs.btrfs-progs}/bin/btrfs subvolume show "$rootMount/@media-stack" >/dev/null 2>&1; then
|
||||
${pkgs.btrfs-progs}/bin/btrfs subvolume create "$rootMount/@media-stack"
|
||||
fi
|
||||
if [ "$umountAfter" -eq 1 ]; then
|
||||
umount "$rootMount"
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
# Optional 1 TiB cap (run once after first boot if desired):
|
||||
# sudo btrfs quota enable /mnt/media-stack && sudo btrfs qgroup limit 1T /mnt/media-stack
|
||||
|
||||
fileSystems."/mnt/media-stack" = {
|
||||
device = btrfsDevice;
|
||||
fsType = "btrfs";
|
||||
neededForBoot = false;
|
||||
options = [
|
||||
"subvol=${mediaSubvol}"
|
||||
"compress=zstd"
|
||||
"noatime"
|
||||
"nofail"
|
||||
"x-systemd.device-timeout=30"
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
# Shared media group, directory layout, and Jellyfin config bind-mount on /mnt/media-stack.
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
paths = import ./media-stack-paths.nix;
|
||||
prowlarrCustomIndexer = "${./../_services/prowlarr/torrent9-custom.yml}";
|
||||
inherit (paths)
|
||||
mediaRoot
|
||||
downloadsDir
|
||||
downloadsIncompleteDir
|
||||
sonarrDataDir
|
||||
radarrDataDir
|
||||
prowlarrDataDir
|
||||
qbittorrentDataDir
|
||||
seerrConfigDir
|
||||
dispatcharrDataDir
|
||||
organizrDataDir
|
||||
jellyfinConfigDir
|
||||
jellyfinMoviesDir
|
||||
jellyfinTvDir
|
||||
;
|
||||
in
|
||||
{
|
||||
_module.args.mediaStackPaths = paths;
|
||||
|
||||
users.groups.media = { };
|
||||
|
||||
users.users.server.extraGroups = [ "media" ];
|
||||
|
||||
# Layout dirs only after /mnt/media-stack is mounted (tmpfiles at early boot would
|
||||
# otherwise create paths on the root fs and break bind mounts / boot).
|
||||
systemd.services.r5500-media-stack-dirs = {
|
||||
description = "Create media-stack directory layout";
|
||||
after = [ "mnt-media\\x2dmedia\\x2dstack.mount" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = ''
|
||||
set -e
|
||||
install -d -m 0775 -o root -g media ${mediaRoot}
|
||||
install -d -m 2775 -o root -g media ${jellyfinMoviesDir} ${jellyfinTvDir} ${downloadsDir}
|
||||
install -d -m 2775 -o root -g media ${downloadsIncompleteDir}
|
||||
install -d -m 0755 -o jellyfin -g jellyfin ${jellyfinConfigDir}
|
||||
install -d -m 0700 -o sonarr -g sonarr ${sonarrDataDir}
|
||||
install -d -m 0700 -o radarr -g radarr ${radarrDataDir}
|
||||
install -d -m 0700 -o prowlarr -g prowlarr ${prowlarrDataDir}
|
||||
install -d -m 0750 -o qbittorrent -g qbittorrent ${qbittorrentDataDir}
|
||||
install -d -m 0755 -o jellyseerr -g jellyseerr ${seerrConfigDir} 2>/dev/null \
|
||||
|| install -d -m 0755 -o root -g root ${seerrConfigDir}
|
||||
install -d -m 0777 -o root -g root ${dispatcharrDataDir}
|
||||
install -d -m 0755 -o organizr -g organizr ${organizrDataDir} 2>/dev/null \
|
||||
|| install -d -m 0755 -o root -g root ${organizrDataDir}
|
||||
install -d -m 0700 -o prowlarr -g prowlarr ${prowlarrDataDir}/Definitions/Custom
|
||||
ln -sfn ${prowlarrCustomIndexer} ${prowlarrDataDir}/Definitions/Custom/torrent9-custom.yml
|
||||
'';
|
||||
};
|
||||
|
||||
# Jellyfin metadata on the media subvolume; nofail so a missing subvol never bricks boot.
|
||||
fileSystems."/var/lib/jellyfin" = {
|
||||
device = jellyfinConfigDir;
|
||||
fsType = "none";
|
||||
neededForBoot = false;
|
||||
options = [
|
||||
"bind"
|
||||
"nofail"
|
||||
"x-systemd.after=mnt-media\\x2dmedia\\x2dstack.mount"
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
# Path constants for the r5500 media stack (imported by _services/* and media-paths.nix).
|
||||
{
|
||||
mediaRoot = "/mnt/media-stack";
|
||||
downloadsDir = "/mnt/media-stack/downloads";
|
||||
downloadsIncompleteDir = "/mnt/media-stack/downloads/incomplete";
|
||||
sonarrDataDir = "/mnt/media-stack/sonarr";
|
||||
radarrDataDir = "/mnt/media-stack/radarr";
|
||||
prowlarrDataDir = "/mnt/media-stack/prowlarr";
|
||||
qbittorrentDataDir = "/mnt/media-stack/qbittorrent";
|
||||
seerrConfigDir = "/mnt/media-stack/seerr";
|
||||
dispatcharrDataDir = "/mnt/media-stack/dispatcharr";
|
||||
organizrDataDir = "/mnt/media-stack/organizr";
|
||||
jellyfinConfigDir = "/mnt/media-stack/jellyfin/config";
|
||||
jellyfinMoviesDir = "/mnt/media-stack/jellyfin/movies";
|
||||
jellyfinTvDir = "/mnt/media-stack/jellyfin/tv";
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{ lib, pkgs, mediaStackPaths, ... }:
|
||||
let
|
||||
dataDir = mediaStackPaths.dispatcharrDataDir;
|
||||
in
|
||||
{
|
||||
systemd.tmpfiles.settings."r5500-dispatcharr-data" = {
|
||||
"${dataDir}"."d" = {
|
||||
mode = "0777";
|
||||
user = "root";
|
||||
group = "root";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.docker-dispatcharr.preStart = lib.mkBefore ''
|
||||
${pkgs.coreutils}/bin/mkdir -p ${dataDir}
|
||||
'';
|
||||
|
||||
virtualisation.oci-containers.containers.dispatcharr = {
|
||||
image = "ghcr.io/dispatcharr/dispatcharr:latest";
|
||||
ports = [ "9191:9191" ];
|
||||
volumes = [
|
||||
"${dataDir}:/data"
|
||||
];
|
||||
environment = {
|
||||
DISPATCHARR_ENV = "aio";
|
||||
REDIS_HOST = "localhost";
|
||||
CELERY_BROKER_URL = "redis://localhost:6379/0";
|
||||
DISPATCHARR_LOG_LEVEL = "info";
|
||||
TZ = "America/Moncton";
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 9191 ];
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
# Docker backend for Dispatcharr and Organizr on r5500.
|
||||
{ ... }:
|
||||
{
|
||||
virtualisation.docker.enable = true;
|
||||
virtualisation.oci-containers.backend = "docker";
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{ ... }:
|
||||
{
|
||||
services.flaresolverr.enable = true;
|
||||
networking.firewall.allowedTCPPorts = [ 8191 ];
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
# Jellyfin on r5500. Local libraries: /mnt/media-stack/jellyfin/{movies,tv}.
|
||||
# Bulk libraries: /mnt/nixdesk-jellyfin/{movies,tv} (NFS from 14900k).
|
||||
{ lib, ... }:
|
||||
{
|
||||
nixpkgs.overlays = [
|
||||
(final: prev: {
|
||||
jellyfin-web = prev.jellyfin-web.overrideAttrs (oldAttrs: {
|
||||
postInstall =
|
||||
(oldAttrs.postInstall or "")
|
||||
+ ''
|
||||
find "$out" -type f \( -name 'banner-light.*.png' -o -name 'banner-dark.*.png' \) \
|
||||
-exec truncate -s 0 {} \;
|
||||
'';
|
||||
});
|
||||
})
|
||||
];
|
||||
|
||||
users.users.jellyfin.extraGroups = [ "media" ];
|
||||
|
||||
services.jellyfin = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
|
||||
systemd.services.jellyfin.serviceConfig = {
|
||||
SupplementaryGroups = [ "media" ];
|
||||
PrivateUsers = lib.mkForce false;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
# NFS mounts of nixdesk (14900k) bulk storage for r5500. Exports live in
|
||||
# modules/hosts/14900k/_private/jellyfin-nfs-export.nix
|
||||
#
|
||||
# Jellyfin library paths:
|
||||
# Movies → /mnt/nixdesk-jellyfin/movies
|
||||
# Shows → /mnt/nixdesk-jellyfin/tv
|
||||
{ ... }:
|
||||
let
|
||||
nfsExportHost = "192.168.2.25";
|
||||
nfsClientOpts = [
|
||||
"rw"
|
||||
"noatime"
|
||||
"nofail"
|
||||
"_netdev"
|
||||
"nfsvers=3"
|
||||
"tcp"
|
||||
"lookupcache=none"
|
||||
"x-systemd.automount"
|
||||
"x-systemd.idle-timeout=3600"
|
||||
];
|
||||
in
|
||||
{
|
||||
fileSystems."/mnt/nixdesk-jellyfin" = {
|
||||
device = "${nfsExportHost}:/mnt/deep/jellyfin";
|
||||
fsType = "nfs";
|
||||
options = nfsClientOpts;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
{ lib, pkgs, mediaStackPaths, ... }:
|
||||
let
|
||||
configDir = mediaStackPaths.organizrDataDir;
|
||||
in
|
||||
{
|
||||
users.groups.organizr = { gid = 950; };
|
||||
users.users.organizr = {
|
||||
isSystemUser = true;
|
||||
uid = 950;
|
||||
group = "organizr";
|
||||
};
|
||||
|
||||
systemd.tmpfiles.settings."r5500-organizr-config" = {
|
||||
"${configDir}"."d" = {
|
||||
mode = "0755";
|
||||
user = "organizr";
|
||||
group = "organizr";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.tmpfiles.settings."r5500-organizr-config-perms" = {
|
||||
"${configDir}"."Z" = {
|
||||
mode = "0755";
|
||||
user = "organizr";
|
||||
group = "organizr";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.docker-organizr.preStart = lib.mkBefore ''
|
||||
${pkgs.coreutils}/bin/mkdir -p ${configDir}
|
||||
${pkgs.coreutils}/bin/chown -R organizr:organizr ${configDir}
|
||||
'';
|
||||
|
||||
virtualisation.oci-containers.containers.organizr = {
|
||||
image = "ghcr.io/organizr/organizr:latest";
|
||||
ports = [ "8888:80" ];
|
||||
volumes = [
|
||||
"${configDir}:/config"
|
||||
];
|
||||
environment = {
|
||||
PUID = "950";
|
||||
PGID = "950";
|
||||
TZ = "America/Moncton";
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 8888 ];
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{ lib, mediaStackPaths, ... }:
|
||||
{
|
||||
services.prowlarr = {
|
||||
enable = true;
|
||||
dataDir = mediaStackPaths.prowlarrDataDir;
|
||||
};
|
||||
|
||||
users.groups.prowlarr = { };
|
||||
users.users.prowlarr = {
|
||||
isSystemUser = true;
|
||||
group = "prowlarr";
|
||||
extraGroups = [ "media" ];
|
||||
};
|
||||
|
||||
systemd.services.prowlarr.serviceConfig.ReadWritePaths = lib.mkAfter [
|
||||
mediaStackPaths.prowlarrDataDir
|
||||
];
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 9696 ];
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
---
|
||||
id: torrent9-custom
|
||||
name: Torrent9 (Custom URL)
|
||||
description: "Torrent9 is a FRENCH Public site for MOVIES / TV / GENERAL"
|
||||
language: fr-FR
|
||||
type: public
|
||||
encoding: UTF-8
|
||||
followredirect: true
|
||||
testlinktorrent: false
|
||||
links:
|
||||
- https://www.torrent9.club/
|
||||
- https://www6.torrent9.to/
|
||||
legacylinks:
|
||||
- https://www.torrent9.pl/ # this is a proxy for torrent9clone
|
||||
- https://torrent9.black-mirror.xyz/ # this is a proxy for torrent9clone
|
||||
- https://torrent9.unblocked.casa/ # this is a proxy for torrent9clone
|
||||
- https://torrent9.proxyportal.fun/ # this is a proxy for torrent9clone
|
||||
- https://torrent9.uk-unblock.xyz/ # this is a proxy for torrent9clone
|
||||
- https://torrent9.ind-unblock.xyz/ # this is a proxy for torrent9clone
|
||||
- https://ww1.torrent9.to/
|
||||
- https://www.torrent9.is/
|
||||
- https://torrent9.li/ # not a proxy for torrent9 or torrent9clone
|
||||
- https://www.oxtorrent.me/
|
||||
- https://www.torrent9.gg/
|
||||
- https://www.torrent9.fi/ # this is the torrent9clone domain
|
||||
- https://www.torrent9.fm/
|
||||
- https://torrent9.se/ # redirect to www.
|
||||
- https://torrent9.ninjaproxy1.com/ # no response data
|
||||
- https://torrent9.proxyninja.org/ # Error 1007
|
||||
- https://www.torrent9.se/
|
||||
- https://torrent9.unblockninja.com/ # 403 forbidden
|
||||
- https://ww1.torrent9.fm/
|
||||
- https://www.torrent9.zone/ # clone? details links are broken
|
||||
- https://torrent9.to/
|
||||
- https://ww2.torrent9.to/
|
||||
- https://www5.torrent9.to/
|
||||
|
||||
caps:
|
||||
# dont forget to update the search fields category case block
|
||||
categorymappings:
|
||||
- {id: films, cat: Movies, desc: "Movies"}
|
||||
- {id: series, cat: TV, desc: "TV"}
|
||||
- {id: musique, cat: Audio, desc: "Music"}
|
||||
- {id: ebook, cat: Books, desc: "Books"}
|
||||
- {id: logiciels, cat: PC, desc: "Software"}
|
||||
- {id: jeux-pc, cat: PC/Games, desc: "PC Games"}
|
||||
- {id: other, cat: Other, desc: "Other"} # dummy cat for results missing icon
|
||||
|
||||
modes:
|
||||
search: [q]
|
||||
tv-search: [q, season, ep]
|
||||
movie-search: [q]
|
||||
music-search: [q]
|
||||
book-search: [q]
|
||||
allowrawsearch: true
|
||||
|
||||
settings:
|
||||
- name: info_flaresolverr
|
||||
type: info_flaresolverr
|
||||
- name: multilang
|
||||
type: checkbox
|
||||
label: Replace MULTi by another language in release name
|
||||
default: false
|
||||
- name: multilanguage
|
||||
type: select
|
||||
label: Replace MULTi by this language
|
||||
default: FRENCH
|
||||
options:
|
||||
FRENCH: FRENCH
|
||||
MULTi FRENCH: MULTi FRENCH
|
||||
ENGLISH: ENGLISH
|
||||
MULTi ENGLISH: MULTi ENGLISH
|
||||
VOSTFR: VOSTFR
|
||||
MULTi VOSTFR: MULTi VOSTFR
|
||||
- name: vostfr
|
||||
type: checkbox
|
||||
label: Replace VOSTFR and SUBFRENCH with ENGLISH
|
||||
default: false
|
||||
- name: sort
|
||||
type: select
|
||||
label: Sort requested from site (Only works for searches with Keywords)
|
||||
default: ".html"
|
||||
options:
|
||||
".html": best
|
||||
".html,trie-date-d": created desc
|
||||
".html,trie-date-a": created asc
|
||||
".html,trie-seeds-d": seeders desc
|
||||
".html,trie-seeds-a": seeders asc
|
||||
".html,trie-poid-d": size desc
|
||||
".html,trie-poid-a": size asc
|
||||
".html,trie-nom-d": title desc
|
||||
".html,trie-nom-a": title asc
|
||||
|
||||
download:
|
||||
selectors:
|
||||
- selector: a[href^="magnet:?"]
|
||||
attribute: href
|
||||
- selector: script:contains("magnet:?")
|
||||
filters:
|
||||
- name: regexp
|
||||
args: "\\s'(magnet:\\?.+?)';"
|
||||
|
||||
search:
|
||||
paths:
|
||||
- path: "{{ if .Keywords }}search_torrent/{{ .Keywords }}{{ .Config.sort }}{{ else }}home/{{ end }}"
|
||||
keywordsfilters:
|
||||
# if searching for season packs with S01 to saison 1 #9712
|
||||
- name: re_replace
|
||||
args: ["(?i)(S0)(\\d{1,2})$", "saison $2"]
|
||||
- name: re_replace
|
||||
args: ["(?i)(S)(\\d{1,3})$", "saison $2"]
|
||||
- name: replace
|
||||
args: [" ", "-"]
|
||||
|
||||
headers:
|
||||
# site blocks all Linux User-Agents, so use a slightly altered Windows Jackett UA here (e.g. Safari/537.36 > Safari/537.35)
|
||||
User-Agent: ["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.35"]
|
||||
|
||||
rows:
|
||||
selector: table.table-striped > tbody > tr
|
||||
filters:
|
||||
- name: andmatch
|
||||
|
||||
fields:
|
||||
category_optional:
|
||||
selector: td:nth-child(1) i
|
||||
optional: true
|
||||
case:
|
||||
i[class="fa fa-video-camera"]: films
|
||||
i[class="fa fa-tv"]: series # search by name
|
||||
i[class="fa fa-desktop"]: series # keywordless search
|
||||
i[class="fa fa-music"]: musique
|
||||
i[class="fa fa-gamepad"]: jeux-pc
|
||||
i[class="fa fa-laptop"]: logiciels
|
||||
i[class="fa fa-book"]: ebook
|
||||
category:
|
||||
text: "{{ if .Result.category_optional }}{{ .Result.category_optional }}{{ else }}other{{ end }}"
|
||||
title_default:
|
||||
selector: td:nth-child(1) a
|
||||
title_optional:
|
||||
selector: td:nth-child(1) a[title]
|
||||
attribute: title
|
||||
optional: true
|
||||
title_phase1:
|
||||
text: "{{ if .Result.title_optional }}{{ .Result.title_optional }}{{ else }}{{ .Result.title_default }}{{ end }}"
|
||||
filters:
|
||||
- name: re_replace
|
||||
args: ["(?i)\\b(FRENCH|MULTI|TRUEFRENCH|VOSTFR|SUBFRENCH)\\b(.+?)(\\b((19|20)\\d{2})\\b)$", "$3 $1$2"]
|
||||
title_vostfr:
|
||||
text: "{{ .Result.title_phase1 }}"
|
||||
filters:
|
||||
- name: re_replace
|
||||
args: ["(?i)\\b(vostfr|subfrench)\\b", "ENGLISH"]
|
||||
title_phase2:
|
||||
text: "{{ if .Config.vostfr }}{{ .Result.title_vostfr }}{{ else }}{{ .Result.title_phase1 }}{{ end }}"
|
||||
title_multilang:
|
||||
text: "{{ .Result.title_phase2 }}"
|
||||
filters:
|
||||
- name: re_replace
|
||||
args: ["(?i)\\b(MULTI(?!.*(?:FRENCH|ENGLISH|VOSTFR)))\\b", "{{ .Config.multilanguage }}"]
|
||||
title:
|
||||
text: "{{ if .Config.multilang }}{{ .Result.title_multilang }}{{ else }}{{ .Result.title_phase2 }}{{ end }}"
|
||||
details:
|
||||
selector: td:nth-child(1) a
|
||||
attribute: href
|
||||
download:
|
||||
selector: td:nth-child(1) a
|
||||
attribute: href
|
||||
date:
|
||||
selector: td:nth-child(2):contains("/")
|
||||
optional: true
|
||||
default: now
|
||||
filters:
|
||||
- name: dateparse
|
||||
args: "dd/MM/yyyy"
|
||||
size:
|
||||
selector: "{{ if .Keywords }}td:nth-child(3){{ else }}td:nth-child(2){{ end }}"
|
||||
filters:
|
||||
- name: re_replace
|
||||
args: ["(\\w)o", "$1B"]
|
||||
seeders:
|
||||
selector: "{{ if .Keywords }}td:nth-child(4){{ else }}td:nth-child(3){{ end }}"
|
||||
optional: true
|
||||
default: 0
|
||||
leechers:
|
||||
selector: "{{ if .Keywords }}td:nth-child(5){{ else }}td:nth-child(4){{ end }}"
|
||||
optional: true
|
||||
default: 0
|
||||
downloadvolumefactor:
|
||||
text: 0
|
||||
uploadvolumefactor:
|
||||
text: 1
|
||||
# engine n/a
|
||||
@@ -0,0 +1,43 @@
|
||||
{ lib, mediaStackPaths, ... }:
|
||||
let
|
||||
webPort = 8081;
|
||||
btPort = 51413;
|
||||
inherit (mediaStackPaths) downloadsDir downloadsIncompleteDir qbittorrentDataDir;
|
||||
in
|
||||
{
|
||||
services.qbittorrent = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
webuiPort = webPort;
|
||||
torrentingPort = btPort;
|
||||
};
|
||||
|
||||
users.groups.qbittorrent = { };
|
||||
users.users.qbittorrent = {
|
||||
isSystemUser = true;
|
||||
group = "qbittorrent";
|
||||
extraGroups = [ "media" ];
|
||||
home = qbittorrentDataDir;
|
||||
};
|
||||
|
||||
fileSystems."/var/lib/qbittorrent" = {
|
||||
device = qbittorrentDataDir;
|
||||
fsType = "none";
|
||||
neededForBoot = false;
|
||||
options = [
|
||||
"bind"
|
||||
"nofail"
|
||||
"x-systemd.after=mnt-media\\x2dmedia\\x2dstack.mount"
|
||||
];
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ webPort btPort ];
|
||||
networking.firewall.allowedUDPPorts = [ btPort ];
|
||||
|
||||
# Default save path for new torrents (existing qBittorrent.conf may override after migration).
|
||||
systemd.services.qbittorrent.preStart = lib.mkAfter ''
|
||||
mkdir -p ${downloadsDir} ${downloadsIncompleteDir}
|
||||
chmod 2775 ${downloadsDir} ${downloadsIncompleteDir}
|
||||
chgrp media ${downloadsDir} ${downloadsIncompleteDir}
|
||||
'';
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{ lib, mediaStackPaths, ... }:
|
||||
{
|
||||
services.radarr = {
|
||||
enable = true;
|
||||
dataDir = mediaStackPaths.radarrDataDir;
|
||||
};
|
||||
|
||||
users.groups.radarr = { };
|
||||
users.users.radarr = {
|
||||
isSystemUser = true;
|
||||
group = "radarr";
|
||||
extraGroups = [ "media" ];
|
||||
};
|
||||
|
||||
systemd.services.radarr.serviceConfig.ReadWritePaths = lib.mkAfter [
|
||||
mediaStackPaths.radarrDataDir
|
||||
];
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 7878 ];
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{ lib, mediaStackPaths, ... }:
|
||||
{
|
||||
nixpkgs.overlays = [
|
||||
(final: prev: {
|
||||
seerr = prev.seerr.overrideAttrs (oldAttrs: {
|
||||
postInstall =
|
||||
(oldAttrs.postInstall or "")
|
||||
+ ''
|
||||
find "$out/share/public" -maxdepth 1 -type f \( -name 'logo_full.svg' -o -name 'logo_stacked.svg' \) \
|
||||
-exec truncate -s 0 {} \;
|
||||
'';
|
||||
});
|
||||
})
|
||||
];
|
||||
|
||||
services.seerr = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
configDir = mediaStackPaths.seerrConfigDir;
|
||||
};
|
||||
|
||||
users.groups.jellyseerr = { };
|
||||
users.users.jellyseerr = {
|
||||
isSystemUser = true;
|
||||
group = "jellyseerr";
|
||||
};
|
||||
|
||||
systemd.services.seerr.serviceConfig = {
|
||||
DynamicUser = lib.mkForce false;
|
||||
User = "jellyseerr";
|
||||
Group = "jellyseerr";
|
||||
ReadWritePaths = [ mediaStackPaths.seerrConfigDir ];
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{ lib, mediaStackPaths, ... }:
|
||||
{
|
||||
services.sonarr = {
|
||||
enable = true;
|
||||
dataDir = mediaStackPaths.sonarrDataDir;
|
||||
};
|
||||
|
||||
users.groups.sonarr = { };
|
||||
users.users.sonarr = {
|
||||
isSystemUser = true;
|
||||
group = "sonarr";
|
||||
extraGroups = [ "media" ];
|
||||
};
|
||||
|
||||
systemd.services.sonarr.serviceConfig.ReadWritePaths = lib.mkAfter [
|
||||
mediaStackPaths.sonarrDataDir
|
||||
];
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 8989 ];
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
{ self, inputs, ... }: {
|
||||
flake.nixosModules.r5500Configuration =
|
||||
{
|
||||
self,
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
self.nixosModules.systemDeployBuilder
|
||||
self.nixosModules.r5500Hardware
|
||||
inputs.sops-nix.nixosModules.sops
|
||||
self.nixosModules.system
|
||||
self.nixosModules.users
|
||||
./_private/media-disk.nix
|
||||
./_private/media-paths.nix
|
||||
./_services/docker-media.nix
|
||||
./_services/nixdesk-nfs-client.nix
|
||||
./_services/jellyfin.nix
|
||||
./_services/sonarr.nix
|
||||
./_services/radarr.nix
|
||||
./_services/prowlarr.nix
|
||||
./_services/flaresolverr.nix
|
||||
./_services/seerr.nix
|
||||
./_services/qbittorrent.nix
|
||||
./_services/dispatcharr.nix
|
||||
./_services/organizr.nix
|
||||
];
|
||||
|
||||
boot.loader.grub = {
|
||||
enable = true;
|
||||
efiSupport = false;
|
||||
device = "/dev/sda";
|
||||
};
|
||||
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
settings = {
|
||||
PasswordAuthentication = true;
|
||||
KbdInteractiveAuthentication = false;
|
||||
PermitRootLogin = "no";
|
||||
UseDns = false;
|
||||
};
|
||||
};
|
||||
|
||||
sops = {
|
||||
defaultSopsFile = ../../../secrets/secrets.yaml;
|
||||
defaultSopsFormat = "yaml";
|
||||
age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
|
||||
};
|
||||
|
||||
sops.secrets."users/server/hashedPassword".neededForUsers = true;
|
||||
|
||||
security.sudo.wheelNeedsPassword = true;
|
||||
|
||||
nix.settings = {
|
||||
experimental-features = [ "nix-command" "flakes" ];
|
||||
trusted-users = [ "root" "@wheel" ];
|
||||
allowed-users = [ "root" "@wheel" ];
|
||||
};
|
||||
|
||||
chiasson.system = {
|
||||
networking = {
|
||||
hostName = "r5500";
|
||||
networkManager.enable = true;
|
||||
};
|
||||
extraPackages = with pkgs; [ btop git ];
|
||||
};
|
||||
|
||||
chiasson.system.deploy.builder.enable = true;
|
||||
|
||||
chiasson.users = {
|
||||
enabled = [ "server" ];
|
||||
hostOverrides.server = {
|
||||
hashedPasswordFile = config.sops.secrets."users/server/hashedPassword".path;
|
||||
};
|
||||
};
|
||||
|
||||
services.xserver.enable = lib.mkDefault false;
|
||||
|
||||
system.stateVersion = "25.11";
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{ self, inputs, ... }: {
|
||||
flake.nixosConfigurations.r5500 = inputs.nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
specialArgs = {
|
||||
inherit self inputs;
|
||||
host = "r5500";
|
||||
system = "x86_64-linux";
|
||||
};
|
||||
modules = [
|
||||
self.nixosModules.r5500Configuration
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
{ ... }: {
|
||||
flake.nixosModules.r5500Hardware =
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
modulesPath,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
(modulesPath + "/installer/scan/not-detected.nix")
|
||||
];
|
||||
|
||||
boot.initrd.availableKernelModules = [
|
||||
"uhci_hcd"
|
||||
"ehci_pci"
|
||||
"ahci"
|
||||
"usb_storage"
|
||||
"usbhid"
|
||||
"sd_mod"
|
||||
];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ "kvm-intel" ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
fileSystems."/" = {
|
||||
device = "/dev/disk/by-uuid/934a5ec3-4bab-49c3-96c9-c857c50076ba";
|
||||
fsType = "btrfs";
|
||||
options = [ "subvol=@" ];
|
||||
};
|
||||
|
||||
fileSystems."/home" = {
|
||||
device = "/dev/disk/by-uuid/934a5ec3-4bab-49c3-96c9-c857c50076ba";
|
||||
fsType = "btrfs";
|
||||
options = [ "subvol=@home" ];
|
||||
};
|
||||
|
||||
fileSystems."/boot" = {
|
||||
device = "/dev/disk/by-uuid/6399d086-687b-4ca9-ad34-da1dd85203d5";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
swapDevices = [
|
||||
{ device = "/dev/disk/by-uuid/ddb9fea1-7c44-44bc-bc74-79a3adb6cc35"; }
|
||||
];
|
||||
|
||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||
};
|
||||
}
|
||||
@@ -49,8 +49,9 @@ let
|
||||
// (args.argsOverride or { })
|
||||
);
|
||||
|
||||
# linux_6_19 was dropped from nixpkgs; t2linux/linux-t2-patches HEAD targets 7.x (see 76589a8).
|
||||
linuxT2Kernel = (pkgs.callPackage linuxT2GenericFromDir { }) {
|
||||
kernel = pkgs.linux_6_19;
|
||||
kernel = pkgs.linux_latest;
|
||||
t2linuxPatchesSrc = inputs.t2linux-patches;
|
||||
};
|
||||
in
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# nixpkgs unstable dropped several Raspberry Pi attrs; nixos-raspberrypi modules still
|
||||
# reference them but ship derivations under pkgs/raspberrypi/.
|
||||
{ inputs, ... }: {
|
||||
nixpkgs.overlays = [
|
||||
(final: _prev:
|
||||
let
|
||||
rp = "${inputs.nixos-raspberrypi}/pkgs/raspberrypi";
|
||||
in
|
||||
{
|
||||
raspberrypi-utils = final.callPackage "${rp}/raspberrypi-utils.nix" { };
|
||||
raspberrypi-udev-rules = final.callPackage "${rp}/udev-rules.nix" { };
|
||||
})
|
||||
];
|
||||
}
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
self.nixosModules."client-services"
|
||||
./_private/platform.nix
|
||||
./_private/raspberrypi-utils-overlay.nix
|
||||
./_private/wifi-brcmfmac.nix
|
||||
./_private/services.nix
|
||||
./_private/cockpit.nix
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
# Build a raw Navi hive attrset from host specs + deployment targets.
|
||||
# Call `inputs.navi.lib.makeHive` on the result to produce `flake.naviHive`.
|
||||
{ lib, inputs, ... }: {
|
||||
flake.lib.mkNaviHiveConfig =
|
||||
{
|
||||
metaNixpkgs,
|
||||
hostSpecs,
|
||||
deployments,
|
||||
}:
|
||||
let
|
||||
deployNodes = lib.filterAttrs (name: _: deployments ? ${name}) hostSpecs;
|
||||
in
|
||||
{
|
||||
meta = {
|
||||
nixpkgs = metaNixpkgs;
|
||||
nodeNixpkgs = lib.mapAttrs (
|
||||
name: spec:
|
||||
import inputs.nixpkgs {
|
||||
system = spec.system;
|
||||
}
|
||||
) deployNodes;
|
||||
nodeSpecialArgs = lib.mapAttrs (_: spec: spec.specialArgs) deployNodes;
|
||||
allowApplyAll = false;
|
||||
};
|
||||
}
|
||||
// lib.mapAttrs (
|
||||
name: spec:
|
||||
{
|
||||
imports = spec.modules or [ spec.configuration ];
|
||||
deployment = deployments.${name};
|
||||
}
|
||||
) deployNodes;
|
||||
}
|
||||
@@ -37,6 +37,12 @@
|
||||
aliases = [ "nix-server" ];
|
||||
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL3KDicMjtOFR6LfZrFzfAD1gdYUdwv6ZM4PSgtmIuzd nix-server";
|
||||
};
|
||||
|
||||
r5500 = {
|
||||
hostName = "192.168.2.100";
|
||||
aliases = [ "r5500" ];
|
||||
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK7iWCEtkYDLZFRF3w1gzyAok5VCAGUOwu4iWZdMjf3D r5500";
|
||||
};
|
||||
};
|
||||
|
||||
mkIdentityFileName = hostName: ".ssh/id_ed25519_${lib.strings.toLower hostName}.pub";
|
||||
@@ -54,11 +60,18 @@
|
||||
(builtins.attrNames selectedHosts)
|
||||
);
|
||||
|
||||
# Must come before inventory `Host` blocks and before `Host *`: LAN Gitea SSH is not a catalog PC,
|
||||
# and `Host *` sets `IdentityAgent none` — without this, git@192.168.2.103 never sees rbw keys.
|
||||
# Gitea git-over-SSH listens on port 222. System SSH (nix deploy, server@…) uses port 22
|
||||
# via the catalog `nix-server` Host block — never list nix-server or 192.168.2.238 here.
|
||||
giteaSshBlock = identityAgent: ''
|
||||
Host git.chiasson.cloud gitea casaos 192.168.2.103
|
||||
HostName 192.168.2.103
|
||||
Host git.chiasson.cloud gitea
|
||||
HostName 192.168.2.238
|
||||
Port 222
|
||||
User git
|
||||
IdentityAgent ${identityAgent}
|
||||
IdentitiesOnly no
|
||||
|
||||
Match host nix-server,192.168.2.238 user git
|
||||
HostName 192.168.2.238
|
||||
Port 222
|
||||
User git
|
||||
IdentityAgent ${identityAgent}
|
||||
@@ -78,11 +91,16 @@
|
||||
entry = selectedHosts.${hostName};
|
||||
hostPatterns = builtins.concatStringsSep " " (entry.aliases ++ [ entry.hostName ]);
|
||||
userLine = if user == null then "" else " User ${user}\n";
|
||||
portLine =
|
||||
if hostName == "nix-server" then
|
||||
" Port 22\n"
|
||||
else
|
||||
"";
|
||||
in
|
||||
''
|
||||
Host ${hostPatterns}
|
||||
HostName ${entry.hostName}
|
||||
${userLine} IdentityFile ~/${mkIdentityFileName hostName}
|
||||
${userLine}${portLine} IdentityFile ~/${mkIdentityFileName hostName}
|
||||
IdentityAgent ${identityAgent}
|
||||
IdentitiesOnly yes
|
||||
'')
|
||||
|
||||
@@ -7,26 +7,10 @@
|
||||
let
|
||||
cfg = config.chiasson.ssh.inbound;
|
||||
inventory = self.lib.sshInventory;
|
||||
resolveSelection =
|
||||
selection:
|
||||
if selection == "all" then
|
||||
inventory.authorizedKeys
|
||||
else
|
||||
let
|
||||
missing = builtins.filter (name: !(builtins.hasAttr name inventory.hosts)) selection;
|
||||
in
|
||||
if missing != [ ] then
|
||||
throw "ssh.inbound: unknown host keys: ${builtins.concatStringsSep ", " missing}"
|
||||
else
|
||||
lib.unique (
|
||||
builtins.filter (key: key != null) (
|
||||
builtins.map (hostName: inventory.hosts.${hostName}.publicKey) selection
|
||||
)
|
||||
);
|
||||
in
|
||||
{
|
||||
options.chiasson.ssh.inbound = {
|
||||
enable = lib.mkEnableOption "Apply `authorizedKeys` from the SSH inventory.";
|
||||
enable = lib.mkEnableOption "Apply SSH inventory public keys to `authorized_keys`.";
|
||||
userAuthorizedHosts = lib.mkOption {
|
||||
type = lib.types.attrsOf (lib.types.either (lib.types.enum [ "all" ]) (lib.types.listOf lib.types.str));
|
||||
default = { };
|
||||
@@ -35,15 +19,15 @@
|
||||
admin = [ "14900k" "t2mbp" ];
|
||||
};
|
||||
description = ''
|
||||
Per user: `"all"` or a list of inventory host names whose keys land in `authorized_keys`.
|
||||
Catalog users that receive the SSH inventory public keys in `authorized_keys`.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
users.users = lib.mapAttrs
|
||||
(_user: selection: {
|
||||
openssh.authorizedKeys.keys = resolveSelection selection;
|
||||
(_user: _selection: {
|
||||
openssh.authorizedKeys.keys = inventory.authorizedKeys;
|
||||
})
|
||||
cfg.userAuthorizedHosts;
|
||||
};
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
self.nixosModules.systemPalera1n
|
||||
self.nixosModules.systemCaching
|
||||
inputs.swiftshare.nixosModules.systemServiceSwiftshare
|
||||
inputs.personal-website.nixosModules.systemServicePersonalWebsite
|
||||
self.nixosModules.systemServiceImmich
|
||||
];
|
||||
};
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
# Navi / remote-deploy identity: push closures + activate system profiles over SSH.
|
||||
{ ... }: {
|
||||
flake.nixosModules.systemDeployBuilder =
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.chiasson.system.deploy.builder;
|
||||
in
|
||||
{
|
||||
options.chiasson.system.deploy.builder = {
|
||||
enable = lib.mkEnableOption ''
|
||||
Fleet deploy user for Navi (and similar tools).
|
||||
|
||||
Creates the `builder` catalog user, trusts it with the Nix daemon for
|
||||
`nix copy`, and grants passwordless sudo for non-interactive activation.
|
||||
SSH inbound is limited to the deploy machine key (see catalog `builder.ssh`).
|
||||
'';
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
chiasson.users.enabled = lib.mkAfter [ "builder" ];
|
||||
|
||||
users.users.builder = {
|
||||
password = "!";
|
||||
# nix copy / navi push opens an SSH session; nologin breaks the store protocol.
|
||||
shell = pkgs.bash;
|
||||
};
|
||||
|
||||
nix.settings.trusted-users = lib.mkAfter [ "builder" ];
|
||||
|
||||
# Navi wraps remote steps in `sudo -H --` (nix-env, switch-to-configuration,
|
||||
# provenance under /etc/navi, readlink, …). Scoped store-path rules are fragile;
|
||||
# this account has no wheel; SSH/key-only in practice (password locked).
|
||||
security.sudo.extraRules = [
|
||||
{
|
||||
users = [ "builder" ];
|
||||
commands = [
|
||||
{
|
||||
command = "ALL";
|
||||
options = [
|
||||
"NOPASSWD"
|
||||
"SETENV"
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -12,7 +12,8 @@
|
||||
else true
|
||||
)
|
||||
cfg.flathub.appIds;
|
||||
allowedAppIds = cfg.flathub.appIds ++ cfg.unmanaged.appIds;
|
||||
bundleAppIds = map (b: b.appId) cfg.bundles;
|
||||
allowedAppIds = cfg.flathub.appIds ++ cfg.unmanaged.appIds ++ bundleAppIds;
|
||||
# Bump in Nix when allowlists change; used to skip slow `flatpak update` / `uninstall --unused` on no-op rebuilds.
|
||||
declarativeHash = builtins.hashString "sha256" (
|
||||
lib.concatStringsSep "\n" (
|
||||
@@ -20,6 +21,8 @@
|
||||
++ lib.sort lib.lessThan allowedAppIds
|
||||
++ [ "flathub" ]
|
||||
++ lib.sort lib.lessThan flathubForSystem
|
||||
++ [ "bundles" ]
|
||||
++ map (b: "${b.appId}@${b.bundle.outPath}") cfg.bundles
|
||||
)
|
||||
);
|
||||
stateFile = "/var/lib/nixos/flatpak-declarative.hash";
|
||||
@@ -60,6 +63,28 @@
|
||||
Installed from elsewhere (not Flathub); never auto-installed and never removed by the script.
|
||||
'';
|
||||
};
|
||||
|
||||
bundles = lib.mkOption {
|
||||
type = lib.types.listOf (
|
||||
lib.types.submodule {
|
||||
options = {
|
||||
appId = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Flatpak application ID inside the bundle (e.g. org.moonfin.linux).";
|
||||
};
|
||||
bundle = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
description = "Upstream .flatpak bundle file (e.g. pkgs.fetchurl { ... }).";
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
default = [ ];
|
||||
description = ''
|
||||
System-wide installs from upstream Flatpak bundles (not Flathub).
|
||||
Reinstalled on switch when the bundle path or appId changes.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
@@ -104,6 +129,22 @@
|
||||
fi
|
||||
done
|
||||
|
||||
${lib.concatStringsSep "\n" (
|
||||
map (
|
||||
b: ''
|
||||
echo "flatpak: ensuring ${b.appId} from bundle."
|
||||
if ! ${pkgs.flatpak}/bin/flatpak --system install \
|
||||
--assumeyes \
|
||||
--noninteractive \
|
||||
--reinstall \
|
||||
--bundle \
|
||||
${lib.escapeShellArg b.bundle.outPath}; then
|
||||
echo "flatpak: WARN failed to install ${b.appId} from bundle (skip)." >&2
|
||||
fi
|
||||
''
|
||||
) cfg.bundles
|
||||
)}
|
||||
|
||||
run_heavy=0
|
||||
if [ "$HEAVY" -eq 1 ]; then
|
||||
run_heavy=1
|
||||
|
||||
@@ -88,6 +88,39 @@
|
||||
'';
|
||||
};
|
||||
|
||||
sunshine = {
|
||||
enable = lib.mkEnableOption "Sunshine — self-hosted Moonlight streaming host";
|
||||
|
||||
openFirewall = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "Open Sunshine/Moonlight ports via `services.sunshine.openFirewall`.";
|
||||
};
|
||||
|
||||
capSysAdmin = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Grant CAP_SYS_ADMIN to Sunshine for DRM/KMS capture (`services.sunshine.capSysAdmin`).
|
||||
'';
|
||||
};
|
||||
|
||||
autoStart = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "Start Sunshine with the graphical session.";
|
||||
};
|
||||
|
||||
cudaSupport = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Build Sunshine with CUDA/NVENC (`pkgs.sunshine.override { cudaSupport = true; }`).
|
||||
Enable on NVIDIA hosts for hardware encoding.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
launchers = {
|
||||
enableBottles = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
@@ -128,6 +161,17 @@
|
||||
dedicatedServer.openFirewall = cfg.steam.dedicatedServer.openFirewall;
|
||||
};
|
||||
|
||||
services.sunshine = lib.mkIf cfg.sunshine.enable {
|
||||
enable = true;
|
||||
openFirewall = cfg.sunshine.openFirewall;
|
||||
capSysAdmin = cfg.sunshine.capSysAdmin;
|
||||
autoStart = cfg.sunshine.autoStart;
|
||||
package = pkgs.sunshine.override {
|
||||
cudaSupport = cfg.sunshine.cudaSupport;
|
||||
cudaPackages = pkgs.cudaPackages;
|
||||
};
|
||||
};
|
||||
|
||||
hardware.graphics = lib.mkIf cfg.graphics.enable {
|
||||
enable = true;
|
||||
enable32Bit = cfg.graphics.enable32Bit;
|
||||
|
||||
@@ -77,6 +77,20 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
builder = {
|
||||
isNormalUser = true;
|
||||
description = "Navi fleet deploy (push + activate only)";
|
||||
extraGroups = [ ];
|
||||
createHome = false;
|
||||
|
||||
homeManager = {
|
||||
enable = false;
|
||||
module = null;
|
||||
};
|
||||
|
||||
ssh.inbound.enable = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#
|
||||
# git diff master..ie/telequebec-update -- \
|
||||
# yt_dlp/extractor/telequebec.py yt_dlp/extractor/_extractors.py \
|
||||
# > path/to/NixOS-V2/modules/patches/yt-dlp-telequebec.patch
|
||||
# > path/to/chiasson-nix/modules/patches/yt-dlp-telequebec.patch
|
||||
#
|
||||
{ ... }: {
|
||||
flake.nixosModules.systemYtDlpTelequebecPatch =
|
||||
|
||||
@@ -13,8 +13,9 @@
|
||||
at-spi2-core,
|
||||
libsecret,
|
||||
libuuid,
|
||||
libxscrnsaver,
|
||||
libxtst,
|
||||
mesa,
|
||||
xorg,
|
||||
}:
|
||||
|
||||
let
|
||||
@@ -56,8 +57,8 @@ stdenvNoCC.mkDerivation {
|
||||
at-spi2-core
|
||||
libsecret
|
||||
libuuid
|
||||
xorg.libXScrnSaver
|
||||
xorg.libXtst
|
||||
libxscrnsaver
|
||||
libxtst
|
||||
];
|
||||
|
||||
unpackPhase = "true";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# HM side of the flake; option tree is `chiasson.home.*` (docs/module-conventions.md).
|
||||
# HM side of the flake; option tree is `chiasson.home.*` (docs/conventions.md).
|
||||
{ self, inputs, ... }: {
|
||||
imports = [
|
||||
./apps/discord.nix
|
||||
|
||||
@@ -110,8 +110,14 @@
|
||||
gtk3.extraConfig = {
|
||||
gtk-application-prefer-dark-theme = 1;
|
||||
};
|
||||
gtk4.extraConfig = {
|
||||
gtk-application-prefer-dark-theme = 1;
|
||||
gtk4 = {
|
||||
theme = {
|
||||
name = cfg.gtkTheme.name;
|
||||
package = cfg.gtkTheme.package;
|
||||
};
|
||||
extraConfig = {
|
||||
gtk-application-prefer-dark-theme = 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -12,15 +12,7 @@
|
||||
cursorPkgs.default
|
||||
else
|
||||
null;
|
||||
# NixOS-New `home-shared.nix`: `cursor-cli` alongside the AppImage. nixpkgs now names this
|
||||
# `cursor-agent`; keep both for compatibility across pins.
|
||||
defaultAgentPkg =
|
||||
if pkgs ? cursor-agent then
|
||||
pkgs.cursor-agent
|
||||
else if pkgs ? cursor-cli then
|
||||
pkgs.cursor-cli
|
||||
else
|
||||
null;
|
||||
cursorCli = if pkgs ? cursor-cli then pkgs.cursor-cli else null;
|
||||
nixIdeTools = [ pkgs.nixd pkgs.nixfmt ];
|
||||
cursorWithNixIde =
|
||||
if cursorPkg == null then
|
||||
@@ -47,21 +39,6 @@
|
||||
default = true;
|
||||
description = "`EDITOR` / `VISUAL` → `cursor --wait`.";
|
||||
};
|
||||
agent = {
|
||||
enable = lib.mkEnableOption ''
|
||||
Cursor Agent CLI (`cursor-agent` in current nixpkgs; older pins used `cursor-cli`).
|
||||
'' // {
|
||||
default = true;
|
||||
};
|
||||
package = lib.mkOption {
|
||||
type = with lib.types; nullOr package;
|
||||
default = defaultAgentPkg;
|
||||
defaultText = "pkgs.cursor-agent or pkgs.cursor-cli or null";
|
||||
description = ''
|
||||
Package providing the `cursor-agent` CLI. Set to `null` to omit the CLI while keeping the GUI app.
|
||||
'';
|
||||
};
|
||||
};
|
||||
nixIde = {
|
||||
enable = lib.mkEnableOption ''
|
||||
Nix IDE extension tooling (`nixd` LSP, `nixfmt` formatter).
|
||||
@@ -82,8 +59,14 @@
|
||||
else
|
||||
cursorPkg)
|
||||
]
|
||||
++ lib.optionals (cfg.agent.enable && cfg.agent.package != null) [ cfg.agent.package ]
|
||||
++ lib.optionals (cursorCli != null) [ cursorCli ]
|
||||
++ lib.optionals cfg.nixIde.enable nixIdeTools;
|
||||
|
||||
# Cursor's updater drops a generic-linux binary here; remove it so `cursor-agent` resolves to cursor-cli.
|
||||
home.activation.removeBrokenCursorAgent = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
||||
$DRY_RUN_CMD rm -f "$HOME/.local/bin/cursor-agent"
|
||||
'';
|
||||
|
||||
home.sessionVariables = lib.mkIf cfg.setAsDefaultEditor {
|
||||
EDITOR = "cursor --wait";
|
||||
VISUAL = "cursor --wait";
|
||||
|
||||
+51
-42
@@ -12,60 +12,69 @@ caching:
|
||||
token: ENC[AES256_GCM,data:8omssG3GwCFIegfz+8IAGGhFGj01RB3dqqHeFpmZOzMJUshIDvSRuTTpGFhUBC7Xue8h09hAhpirIHmqzyG3I+e2Se/VZZoByXmpyIKesl3+NqOXDkJvgImqhvFVkTiSe5p/vSN3slWDylfkThQ0hZYw5mB9J13M5965iUnWcRbg+1fYFdTuSgrHY8Rxt4da0287A0YGnsN63k7j32XOJndxsRoOLoo+IQ+X+hiPOJkfGYxY0MglnxaxhPwH8SP1V+p78N75Z2npOtMdEikdHmj/NmKbqUXN2P0+IXthxV17WePCulZVsKC1Jw+clgbyAvHcQeVG/yyrcb1CRRQpszHtq1Pz7DHvfAG+gxyPNyP7D6oQNT8foX4C6CwuHgYQtM1x0D6oAL+lppQWJ0kEV/GDlJSXQnp/aBbVAqDmqS0TCx40nVmQ0PvMcjtsiZJigkRJRNLCg6n+qmhc5Rh9RhslPN5JXU0orWs9QYAoLXzdDDGP/R9tlEhwQBxwGrFAp016iilqPavMdI8txrWWdvezQuAh//eeW5LQSa6t363VCjX8phnXeJltOgXYlyuKnCCmv0a6XwhmT0PA+32/F0BxTf9lcZConpurlvOHdznaVeUXcFOEwKouDC7smPIZZqcRU8OIbWs7YXqMgatgb/bJVtB0P0Avsj9t9Uz8Dv8xBV+90U5qwM7HV16FIERorDquzgKFcvtb8/QfjTINoswpHZKNCbmQPxfJYPheJFwMQGFn+b+ecv+Z7qng9JEujJSNtEPv2CIuVmSxZJaU5g2CMu3rFGIA3qF81Bf1Ri8n+KYWgOKpQt11nClouv2XePO8JKI6fslF411zJ8zD4E/6Qg95UWhLh0RG2cXzYSXXvrpXDlIe9spc4OLuj4tFtXkiZZvfM5MgRTtoh93soypUpEbswTji2UprC3OPikjIIW49YysGVsH2100/67HbtinRoazM1M+DjaD2pMryx7kW/oVpyaW61wiqtHk9nq8vqROLWBhQxzGSh9157z/46AT+8PN89gFh5uNdFuhFz8e8/HIV3HtIrzrtR+flJfHJ1ZT5dhTDicSMiC/DhG/hupX4GHGX6zlaMgBqB8bKxxvs+v0iHfSkDIkuenZ+nTD72DP5yuIQVIwGV16CZA6rusjb1zLn6QYpvQtCuqlih+epsGNEYP6B3rvNMc/N7JcwY4YMTK+C46EC9mXhpfPn0a5OdD4kQ6s=,iv:+g9W5MzgtLppD1K3dZ/tCuaMxaa194W3Lf23/jUmDvk=,tag:5uVwIOkB2+MRHPGlKGQtGg==,type:str]
|
||||
sops:
|
||||
age:
|
||||
- recipient: age1yyzgmazjxkvwtfcv9re3lqmt2ru5dcrfu3sauysm0wzfwzvyap8qkjkq32
|
||||
enc: |
|
||||
- enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtc25Wd0dlZldBVHZKTDRW
|
||||
ZlVHamluT0hPbVArdWx0Qlk5czR6ZldIaEhRCnVkUVp6cHRwdnNsRDBhV285Q0tV
|
||||
RitNWHNrUy9pN0dpanFSVHJjK0VuM1kKLS0tIHVLRWFRNmZyR2JOR3FwYjZsME9v
|
||||
L2ZKbFIydkJ5L25GSWFBamhtbHZXV0UKAPIGMBbIdR7sCxsCYJa/9kajqmceOAJa
|
||||
/jjxxcaWDkv5cmq0u8qFZEDkTjY3PKoJofBcx5q0npuJmrIA/oLeJA==
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBBTmhhd2M0M1ZsdEtReUFM
|
||||
MEs0SHZ4dUkxNWdUZjBoSFVQd0RvZTdWVndnCitxNGRGUWcwWWpZcytpUzhOcCtF
|
||||
SHRoSzZkcWVnZzdrL0JoVkk0cTlSbWcKLS0tIGFCUFd6WXpxVWg2MVFCcnJ1Qklp
|
||||
TDBBc21HWHJiZkZPZ3ZyWFhOeEFaT3cK5SFqqR2Fc6o/RTDPkly6xS+hEY331ws6
|
||||
8KIGxGXC9iO7ExGOD5nzLzFJmjZzfp6IIvdQ0rzkJY4C1vKW1pPZMw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1elk6zwmcylwfk7gd4pjda7g29upftjvxys8py42s8d42jklnyv7s7dm9z2
|
||||
enc: |
|
||||
recipient: age1yyzgmazjxkvwtfcv9re3lqmt2ru5dcrfu3sauysm0wzfwzvyap8qkjkq32
|
||||
- enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBvcm5rZmtlUy9yQSs3Vnhh
|
||||
eDVYaUxvcCtMYXhEa0ViTmFYK3JONnFsTWw0Cmdad2ZKdGcxeGQzeGVnTXRUeGJZ
|
||||
R1kxQ1ZDK0FsQzc4S1EwMFN4VVZaTzAKLS0tIDJ5S3QycG5ZdThIVlZEVjBnMG9K
|
||||
V1RSem1LdWpKT2o2aHh5dC9wVGJRakUK+5/eE+9WtSXmwoJ2Nqk4ni01GS4c3gLQ
|
||||
p+wcpiOsxwnnisZTxag2yCn4hlv6FcOUWOcISq5H/sxwKgjBaeeuRQ==
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBEeWEwQ0o4TDZkSFI4WGFZ
|
||||
QXZIVGQ4ajI5SFpLczJpZHh3Tm9lMkZ6K1dBCjhWeDVWcVNWM01maXVDdTRYRzI4
|
||||
OUk0c0czSzNhVWxkUWdIU3JCaytZdkEKLS0tIHpBNzdpT0oxNkhBalVXYkpzRitn
|
||||
dXRWUmxmTFNnYm5ZbzFYMjJ5THJlQ3cKn6AZhiS/eqvmsFbKkv79sE198ywNeNZf
|
||||
BQJSQ353CmJQ7z7uL0m+/96aeaUu9Kjk37bPeMmxrXhhW7Kvwzwuiw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age193gw802ytal7h5p5q37kpd9079k2vsflzmnvupcwfxh2kjdrwqtsk3g6rm
|
||||
enc: |
|
||||
recipient: age1elk6zwmcylwfk7gd4pjda7g29upftjvxys8py42s8d42jklnyv7s7dm9z2
|
||||
- enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6TjZVN3dFbmg5MGhNVFdD
|
||||
YTZ4WVdOUWRGTzkrUmRGVUpobmg0Y0ozaUFNClh6cXhKWVkxcTlRYmZ5NmNqeEJJ
|
||||
YzdYR1FyRExabXBDSnVSbXNxZy91am8KLS0tIHZLa0dXWHZhMDU5Q3BNR2U3NG00
|
||||
eFp4Vmxha0xOVTVwd09PVzgrdzFNL2sKDEofAS4W4i8+VBU0wl1yTWmOogNbGHhY
|
||||
azvb0QmxrYpurxjep3BYsc/5Co6U4mwowidoyzQLsiBJWDWy3wPdLQ==
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBHbDY1WXl5Wk81Rk0zOXE4
|
||||
dGczVWZQZW9pMkxrZUdIWUg1V0EzQVdOb1Y0CmxYMnR1RDk4TUVCQm4xVWlnMHNB
|
||||
eSs2QVZpQy83KzZMZDAzbGRkR2xmQ0UKLS0tIE5GNFRTWDhFQ1IrZUY0Si96UUhp
|
||||
WXc4djdTVmp1bG5kN3ByTHViVy81R1kKGEgUjmwNtL7CFqILNWUEh2mHM4C3L9de
|
||||
FBoqaUvE9Dc8lmxjicKKAlnf2ZbwTZ6+Iv2I+KLakjFMznSi4QFO0g==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1yr7vurfxc3w8ewfw9djfm54atw6ayze69qglamecuft5q0n9gu2sadsa2m
|
||||
enc: |
|
||||
recipient: age193gw802ytal7h5p5q37kpd9079k2vsflzmnvupcwfxh2kjdrwqtsk3g6rm
|
||||
- enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2d3dLVitDTVpyNllCTEJN
|
||||
R1RLc2NkRnBrandDakhxeTJWeEdMVkZyS0JRCnl5Uk9FSk1iZmxCZUI1ZWdmYlJa
|
||||
dEFlbjkxYjI4Y2FDZmswOGZqMUxGUXcKLS0tIGdqVWNaU1NWcGs4QXZyTkc5Z2VK
|
||||
MGpaWmtHdzdpRDJxQXNveTd5WFkzTTgKxKuoC36uLqy+QoSGVcQekv5wn69yF0qH
|
||||
2qZPAm3wnf0KzZ8Wo/B8nXkjkq4llfKHbwfePiMRL4RObKXAejYhLA==
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBxZmxST1V3WXN1N01VaE16
|
||||
Njd3S2kzT1l1R2o5TXErYXIyTEo2ZWxNemxrCm5QZG92WDBjNzNLRUxqZ2txLzNz
|
||||
dUU3cURjN1Y3d2ZBMHZuV0hOUWFsVzAKLS0tIG85TnBvL0F2dzBTdHQwdmZoOFhs
|
||||
d2F5QWsxaUR0M2x1M1RVaHp0ZG1vVlkKtrMg6lwXFrXyZiweS6C1a46/Z5oDbHpm
|
||||
FJ7xh8z3fPGRsoDWa/Qet8seNgIbLfAgyQvtIzKiKDTat4f73WIrsw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1hya7pgpe8zal52w3pjf036tpapmehedatfm4r84h30t4wuh079ssedfd37
|
||||
enc: |
|
||||
recipient: age1yr7vurfxc3w8ewfw9djfm54atw6ayze69qglamecuft5q0n9gu2sadsa2m
|
||||
- enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4am5wWWRkL3J0dlZVaWJR
|
||||
eVdMNnhTdGJqeFlNdnppTHNLdjdjcVNYbUQ4CjcwdGM5Nmdvck1wb0RSRjMwL01D
|
||||
STlFdkdDallLLzNnbGY4WndiLzdRMzAKLS0tIHRENzRFTVA2MWE5djVHUy9peVdG
|
||||
dkZDTTJvWU1vZHN2ZUR1R1Z3UWpkSlEKjo621j7xjyyHcc/ij8/X0H5uNLD6SnZa
|
||||
o+apPj44+fTJFL5+VjP/XOsx0rCKTQhnV0gGfZU2SPtfH2BUiDjV0g==
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB3TDhIdDRXVmgyVVZHQXp5
|
||||
N3dlTXBZb0E0bEtuZ2RFN3pQYkZWK25SbEg0CkFaMXRleFBISFAvSzNSSGpBbFVo
|
||||
eTgxZitQNmZmYWx0a2dPcjRMdGpzNDQKLS0tIHpOTmtCM2lCS0NkZ2cvb0loK0pt
|
||||
RTBMdHdnTnFBT2IzQ3JvWWpmZStFSTgK6CxSfV6tlejPie4xKiVUnEhpH7DYJ2lu
|
||||
9U9bw7i3qKvjSlFQBYghF0P4EK32k3x8lkAucK3m3ub8+wbunOJWTg==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1p05z980kdtngk9mw67hfev72h7xhslplpxfk9yskgmf0hl4lu3ls04zht9
|
||||
enc: |
|
||||
recipient: age1hya7pgpe8zal52w3pjf036tpapmehedatfm4r84h30t4wuh079ssedfd37
|
||||
- enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA5YmF1K1ZtQmhoMGRVM0Fk
|
||||
bW1PL0RPQ1ZUZEg4VU5VUi9BdlNhM2hPZkRNCnVIaUJJR1dFeXA1SWk2UFBkQW9a
|
||||
cjc4bFRDb2p0eXJodG5IWk01ekdCdG8KLS0tIHFzU3l3WGcyTmZ0QjRyTmQwcDRZ
|
||||
Mnp5K1VjcncrWWt4SEUrUVlCTTc3OVkKtRqPoatEp8NvZW4Z73nfCUshdz90SCad
|
||||
VFgYF/2DYc7lSDP7otbsjBzGlauQQTWF1wfgEVOkw2EzOt2LCoflbg==
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAwbW1GSERmWGNvK2dCRjVC
|
||||
M2U1SERPU3dGRnlwRmV4bHdNd3RxYzJ2YWk4Cm52bXZuYkt4dlEvbVA0cm51cmRX
|
||||
MW1NYXllU1MwdE5jeEI4VmU5TytjcDAKLS0tIHNPOTIyN0ZlSHI3M0F3S01POGZF
|
||||
RFM3NndnWSt4NnM5TkcyeXRmUFB1Q2MKDCuWlWqV/Dogr6wXDb02BGrsnpyGe22D
|
||||
ivWjVoYx5ClxlKyt7Xuies9fLNjRTVfjJFD5DQTinSPjxrusJg0O5w==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
recipient: age1p05z980kdtngk9mw67hfev72h7xhslplpxfk9yskgmf0hl4lu3ls04zht9
|
||||
- enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA5UkhFTld1T2x4bEZ0Mldy
|
||||
dmZ4b3UzaHgxN2FUenBaVFRFY0puZlVVM2dRClVMK3VCM0w3cUM5Um90YmM1TUhu
|
||||
Vk5wMm4vZXNsTnlQWFV0ZG1tS25UWkkKLS0tIDR3d2NmZjVzUEF2aHN3NW05bGVp
|
||||
L0NHbUF3NzJ3NUtnZFVRMVdLa2ZtWWcKzuMx/jDuZ3z7IPPvAmcYyjLi4c3Toj7a
|
||||
6POXxpxjGhlWJaV47jqeN+7mQY2oTHE/x4raoX/KA2ouXL29K8QpmA==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
recipient: age1pewusvlcgzcnk0kpskgc9qr6jlq8s2yzwnqrnh84p7v5z0kj3qhsya8h2x
|
||||
lastmodified: "2026-03-24T00:15:02Z"
|
||||
mac: ENC[AES256_GCM,data:dYTwO5DtkKinTKfBXGuvXRFxl8yavxXMKTw27M5/GcK/kkstHBG119IRk9B9KC6s6IHTY81U3MeUxE9XwdBiE7q4m15+ZO2vmdBVhN8wAh+82P9BP0HSaxLkjWLeKWBfULyLX/YXmQVsr09/NUEVSZcugJ6m40Ta+X9AQgO+cyA=,iv:FmsznsKTuIr61s3Zn0QZKSKvb/e2AljEB1ijKE52RKk=,tag:rHF2Xi4iP9VF33rxpBr5pg==,type:str]
|
||||
unencrypted_suffix: _unencrypted
|
||||
|
||||
Reference in New Issue
Block a user