From 87cb3b4c0f2d62084569adad373d29e172190dcd Mon Sep 17 00:00:00 2001 From: ibizaman Date: Wed, 3 Dec 2025 18:32:50 +0100 Subject: [PATCH] docs: update usage documentation --- docs/redirects.json | 34 +- docs/usage.md | 1316 +++++++------------------------------------ 2 files changed, 227 insertions(+), 1123 deletions(-) diff --git a/docs/redirects.json b/docs/redirects.json index 0938ea6..56f5935 100644 --- a/docs/redirects.json +++ b/docs/redirects.json @@ -4403,17 +4403,17 @@ "usage": [ "usage.html#usage" ], - "usage-complete-example": [ - "usage.html#usage-complete-example" + "usage-examples": [ + "usage.html#usage-examples" ], - "usage-example-colmena": [ - "usage.html#usage-example-colmena" + "usage-examples-colmena": [ + "usage.html#usage-examples-colmena" ], - "usage-example-deployrs": [ - "usage.html#usage-example-deployrs" + "usage-examples-deploy-rs": [ + "usage.html#usage-examples-deploy-rs" ], - "usage-example-nixosrebuild": [ - "usage.html#usage-example-nixosrebuild" + "usage-examples-nixosrebuild": [ + "usage.html#usage-examples-nixosrebuild" ], "usage-flake": [ "usage.html#usage-flake" @@ -4424,12 +4424,30 @@ "usage-flake-lib": [ "usage.html#usage-flake-lib" ], + "usage-flake-modules": [ + "usage.html#usage-flake-modules" + ], + "usage-flake-overlays": [ + "usage.html#usage-flake-overlays" + ], + "usage-flake-patches": [ + "usage.html#usage-flake-patches" + ], "usage-flake-substituter": [ "usage.html#usage-flake-substituter" ], "usage-flake-tag": [ "usage.html#usage-flake-tag" ], + "usage-flake-tag-explicit": [ + "usage.html#usage-flake-tag-explicit" + ], + "usage-flake-tag-implicit": [ + "usage.html#usage-flake-tag-implicit" + ], + "usage-flake-unfree": [ + "usage.html#usage-flake-unfree" + ], "usage-secrets": [ "usage.html#usage-secrets" ] diff --git a/docs/usage.md b/docs/usage.md index 2ebac3b..86ae9ec 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -4,9 +4,9 @@ ## Flake {#usage-flake} -Self Host Blocks is available as a flake. It also uses its own `pkgs.lib` and +Self Host Blocks (SHB) is available as a flake. It also uses its own `pkgs.lib` and `nixpkgs` and it is required to use the provided ones as input for your -deployments, otherwise you might end up blocked when Self Host Blocks patches a +deployments, otherwise you might end up blocked when SHB patches a module, function or package. The following snippet is thus required to use Self Host Blocks: @@ -16,10 +16,10 @@ Host Blocks: outputs = { selfhostblocks, ... }: let system = "x86_64-linux"; - shb = selfhostblocks.lib.${system}; + nixpkgs' = selfhostblocks.lib.${system}.patchedNixpkgs; in nixosConfigurations = { - myserver = shb.pkgs.nixosSystem { + myserver = nixpkgs'.nixosSystem { inherit system; modules = [ selfhostblocks.nixosModules.default @@ -30,21 +30,107 @@ Host Blocks: } ``` -::: {.note} -For seasoned nixers or if you want to add your patches and overlays, -SHB provides a decomposed version of the `nixosSystem` function above. -For more examples, see the buildable examples at -[`./demo/minimal/flake.nix`](@REPO@/demo/minimal/flake.nix). +::: {.info} +In case somehow this documentation became stale, +look at the examples in [`./demo/minimal/flake.nix`](@REPO@/demo/minimal/flake.nix) +which provides examples tested in CI - so assured to always be up to date - +on how to use SHB. ::: -If you use `sops-nix` for secrets, SHB provides an additional module, not -imported in the `default` module. It can be added by importing +### Modules {#usage-flake-modules} +The `default` module imports all modules except the SOPS module. +That module is only needed if you want to use [sops-nix](#usage-secrets) to manage secrets. + +You can also import each module individually. +You might want to do this to only import SHB overlays if you actually intend to use them. +Importing the `nextcloud` module for example will anyway transitively import needed support modules +so you can't go wrong: + +```diff + modules = [ +- selfhostblocks.nixosModules.default ++ selfhostblocks.nixosModules.nextcloud + ./configuration.nix + ]; ``` -inputs.sops-nix.nixosModules.default -inputs.selfhostblocks.nixosModules.sops + +To list all modules, run: + +```bash +$ nix flake show github:ibizaman/selfhostblocks --allow-import-from-derivation + +... + +├───nixosModules +│ ├───arr: NixOS module +│ ├───audiobookshelf: NixOS module +│ ├───authelia: NixOS module +│ ├───borgbackup: NixOS module +│ ├───davfs: NixOS module +│ ├───default: NixOS module +│ ├───deluge: NixOS module +│ ├───forgejo: NixOS module +│ ├───grocy: NixOS module +│ ├───hardcodedsecret: NixOS module +│ ├───hledger: NixOS module +│ ├───home-assistant: NixOS module +│ ├───immich: NixOS module +│ ├───jellyfin: NixOS module +│ ├───karakeep: NixOS module +│ ├───lib: NixOS module +│ ├───lldap: NixOS module +│ ├───mitmdump: NixOS module +│ ├───monitoring: NixOS module +│ ├───nextcloud-server: NixOS module +│ ├───nginx: NixOS module +│ ├───open-webui: NixOS module +│ ├───paperless: NixOS module +│ ├───pinchflat: NixOS module +│ ├───postgresql: NixOS module +│ ├───restic: NixOS module +│ ├───sops: NixOS module +│ ├───ssl: NixOS module +│ ├───tinyproxy: NixOS module +│ ├───vaultwarden: NixOS module +│ ├───vpn: NixOS module +│ └───zfs: NixOS module + +... ``` +### Patches {#usage-flake-patches} + +To add your own patches on top of the patches provided by SHB, +you can remove the `patchedNixpkgs` line and instead apply the patches yourself: + +```diff +- nixpkgs' = selfhostblocks.lib.${system}.patchedNixpkgs; ++ pkgs = import selfhostblocks.inputs.nixpkgs { ++ inherit system; ++ }; ++ nixpkgs' = pkgs.applyPatches { ++ name = "nixpkgs-patched"; ++ src = selfhostblocks.inputs.nixpkgs; ++ patches = selfhostblocks.lib.${system}.patches; ++ }; ++ nixosSystem' = import "${nixpkgs'}/nixos/lib/eval-config.nix"; + in + nixosConfigurations = { +- myserver = nixpkgs'.nixosSystem { ++ myserver = nixosSystem' { +``` + +### Overlays {#usage-flake-overlays} + +SHB applies its own overlays using `nixpkgs.overlays`. +Each module provided by SHB set that option if needed. + +If you don't want to have those overlays applied for modules you don't intend to use SHB for, +you will want to avoid importing the `default` module +and instead import only the module for the services or blocks you intend to use, +like shows in the [Modules](#usage-flake-modules) section. + ### Substituter {#usage-flake-substituter} You can also use the public cache as a substituter with: @@ -59,20 +145,64 @@ nix.settings.substituters = [ ]; ``` -### Tag Updates {#usage-flake-tag} +### Unfree {#usage-flake-unfree} -To pin Self Host Blocks to a release/tag, run the following snippet: +SHB does not necessarily attempt to provide only free packages. +Currently, the only module using unfree modules is the [Open WebUI](@REPO@/modules/services/open-webui.nix) one. + +To be able to use that module, you can follow the [nixpkgs manual](https://nixos.org/manual/nixpkgs/stable/#sec-allow-unfree) +and set either: ```nix -nix flake update --override-input selfhostblocks github:ibizaman/selfhostblocks/@VERSION@ selfhostblocks +{ + nixpkgs.config.allowUnfree = true; +} ``` -Updating Self Host Blocks to a new version can be done the same way. +or the option `nixpkgs.config.allowUnfreePredicate`. + +### Tag Updates {#usage-flake-tag} + +To pin SHB to a release/tag, you can either use an implicit or explicit way. + +#### Implicit {#usage-flake-tag-implicit} + +Here, use the usual `inputs` form: + +```nix +{ + inputs.selfhostblocks.url = "github:ibizaman/selfhostblocks"; +} +``` + +then use the `flake update --override-input` command: + +```bash +nix flake update selfhostblocks \ + --override-input selfhostblocks github:ibizaman/selfhostblocks/@VERSION@ +``` + +Note that running `nix flake update` will update the version of SHB to the latest from the main branch, +canceling the override you just did above. +So beware when running that command. + +#### Explicit {#usage-flake-tag-explicit} + +Here, set the version in the input directly: + +```nix +{ + inputs.selfhostblocks.url = "github:ibizaman/selfhostblocks?ref=@VERSION@"; +} +``` + +Note that running `nix flake update` in this case will not update SHB, +you must update the tag explicitly then run `nix flake update`. ### Auto Updates {#usage-flake-autoupdate} To avoid burden on the maintainers to keep `nixpkgs` input updated with -upstream, the [GitHub repository][repo] for Self Host Blocks updates the +upstream, the [GitHub repository][repo] for SHB updates the `nixpkgs` input every couple days, and verifies all tests pass before automatically merging the new `nixpkgs` version. The setup is explained in [this blog post][automerge]. @@ -80,49 +210,29 @@ automatically merging the new `nixpkgs` version. The setup is explained in [repo]: https://github.com/ibizaman/selfhostblocks [automerge]: https://blog.tiserbox.com/posts/2023-12-25-automated-flake-lock-update-pull-requests-and-merging.html -### SHB Lib {#usage-flake-lib} +### Lib {#usage-flake-lib} -Providing patches to downstream users is finicky, to say the least. -For example, using `selfhostblocks.inputs.nixpkgs` directly will _not_ work. -So Self Host Blocks provides a few attributes under the `selfhostblocks.lib.${system}` flake output: +The `selfhostblocks.nixosModules.lib` module +adds a module argument called `shb` by setting the +`_module.args.shb` option. +It is imported by nearly all other SHB modules +but you could still import it on its own +if you want to access SHB's functions and no other module. -```nix -{ - inputs = { - selfhostblocks.url = "github:ibizaman/selfhostblocks"; - }; - outputs = { selfhostblocks, ... }: - let - shb = selfhostblocks.lib.${system}; - in - { - // Use shb.replaceSecrets for example. - } -} -``` +The library of functions is also available under the traditional +`selfhostblocks.lib` flake output. -- At the top-level, all functions defined by SHB under - [`./lib/default.nix`](@REPO@/lib/default.nix) and - [`./test/common.nix`](@REPO@/test/common.nix). -- `patches`: the list of patches applied by SHB [`./patches`](@REPO@/patches) to - nixpkgs. -- `contracts`: all contract modules. -- `patchNixpkgs`: a re-export of `nixpkgs.legacyPackages.${system}.applyPatches` - with the arguments made a bit more explicit. -- `patchedNixpkgs`: nixpkgs with `patches` applied. -- `pkgs`: `nixpkgs.legacyPackages.${system}` with `patches` applied and also: - - `config.allowUnfree` set to `true` - - `lib.shb` holds functions defined by - [`./lib/default.nix`](@REPO@/lib/default.nix) - - `lib.evalModules` is patched to include patches provided by nixpkgs - - `nixosSystem` is patched to include patches provided by nixpkgs +The functions layout is, in pseudo-code: -For normal usage, one should only need the provided `.nixosSystem`, `.pkgs` and -in some cases `.nixpkgs`. +- `shb.*` all functions from [`./lib/default.nix`](@REPO@/lib/default.nix). +- `shb.contracts.*` all functions from [`./modules/contracts/default.nix`](@REPO@/modules/contracts/default.nix). +- `shb.test.*` all functions from [`./test/common.nix`](@REPO@/test/common.nix). -## Example Deployment with Nixos-Rebuild {#usage-example-nixosrebuild} +## Example Deployments {#usage-examples} -The following snippets show how to deploy Self Host Blocks using the standard +### With Nixos-Rebuild {#usage-examples-nixosrebuild} + +The following snippets show how to deploy SHB using the standard deployment system [nixos-rebuild][nixos-rebuild]. [nixos-rebuild]: https://nixos.org/manual/nixos/stable/#sec-changing-config @@ -135,11 +245,10 @@ deployment system [nixos-rebuild][nixos-rebuild]. outputs = { self, selfhostblocks }: let system = "x86_64-linux"; - - pkgs' = selfhostblocks.lib.${system}.pkgs; + nixpkgs' = selfhostblocks.lib.${system}.patchedNixpkgs; in { nixosConfigurations = { - machine = pkgs'.nixosSystem { + machine = nixpkgs'.nixosSystem { inherit system; modules = [ selfhostblocks.nixosModules.default @@ -152,8 +261,7 @@ deployment system [nixos-rebuild][nixos-rebuild]. The above snippet assumes one machine to deploy to, so `nixpkgs` is defined exclusively by the `selfhostblocks` input. It is more likely that you have -multiple machines, some not using Self Host Blocks, then you can do the -following: +multiple machines, some not using SHB, then you can do the following: ```nix { @@ -166,19 +274,13 @@ following: outputs = { self, selfhostblocks }: { let system = "x86_64-linux"; - lib = selfhostblocks.lib.${system}; - - nixpkgs' = lib.shb.patchedNixpkgs; - - shbNixpkgs = import nixpkgs' { - inherit system; - }; + nixpkgs' = selfhostblocks.lib.${system}.patchedNixpkgs; in nixosConfigurations = { machine1 = nixpkgs.lib.nixosSystem { }; - machine2 = shbNixpkgs.lib.nixosSystem { + machine2 = nixpkgs'.lib.nixosSystem { system = "x86_64-linux"; modules = [ selfhostblocks.nixosModules.default @@ -192,9 +294,9 @@ following: In the above snippet, `machine1` will use the `nixpkgs` version from your inputs while `machine2` will use the `nixpkgs` version from `selfhostblocks`. -## Example Deployment With Colmena {#usage-example-colmena} +### With Colmena {#usage-examples-colmena} -The following snippets show how to deploy Self Host Blocks using the deployment +The following snippets show how to deploy SHB using the deployment system [Colmena][Colmena]. [colmena]: https://colmena.cli.rs @@ -208,17 +310,14 @@ system [Colmena][Colmena]. outputs = { self, selfhostblocks }: { let system = "x86_64-linux"; - lib = selfhostblocks.lib.${system}; - - nixpkgs' = lib.shb.patchedNixpkgs; - - shbNixpkgs = import nixpkgs' { + nixpkgs' = selfhostblocks.lib.${system}.patchedNixpkgs; + pkgs' = import nixpkgs' { inherit system; }; in colmena = { meta = { - nixpkgs = shbNixpkgs; + nixpkgs = pkgs'; }; machine = { selfhostblocks, ... }: { @@ -233,7 +332,7 @@ system [Colmena][Colmena]. The above snippet assumes one machine to deploy to, so `nixpkgs` is defined exclusively by the `selfhostblocks` input. It is more likely that you have -multiple machines, some not using Self Host Blocks, in this case you can use the +multiple machines, some not using SHB, in this case you can use the `colmena.meta.nodeNixpkgs` option: ```nix @@ -247,20 +346,21 @@ multiple machines, some not using Self Host Blocks, in this case you can use the outputs = { self, selfhostblocks }: { let system = "x86_64-linux"; - lib = selfhostblocks.lib.${system}; + pkgs = import nixpkgs { + inherit system; + }; - nixpkgs' = lib.shb.patchedNixpkgs; - - shbNixpkgs = import nixpkgs' { + nixpkgs' = selfhostblocks.lib.${system}.patchedNixpkgs; + pkgs' = import nixpkgs' { inherit system; }; in colmena = { meta = { - nixpkgs = import nixpkgs { inherit system; }; + nixpkgs = pkgs; nodeNixpkgs = { - machine2 = shbNixpkgs; + machine2 = pkgs'; }; }; @@ -281,9 +381,9 @@ multiple machines, some not using Self Host Blocks, in this case you can use the In the above snippet, `machine1` will use the `nixpkgs` version from your inputs while `machine2` will use the `nixpkgs` version from `selfhostblocks`. -## Example Deployment with deploy-rs {#usage-example-deployrs} +### With Deploy-rs {#usage-examples-deploy-rs} -The following snippets show how to deploy Self Host Blocks using the deployment +The following snippets show how to deploy SHB using the deployment system [deploy-rs][deploy-rs]. [deploy-rs]: https://github.com/serokell/deploy-rs @@ -297,11 +397,10 @@ system [deploy-rs][deploy-rs]. outputs = { self, selfhostblocks }: { let system = "x86_64-linux"; - lib = selfhostblocks.lib.${system}; - - nixpkgs' = lib.shb.patchedNixpkgs; - - shbPkgs = import shbNixpkgs { inherit system; }; + nixpkgs' = selfhostblocks.lib.${system}.patchedNixpkgs; + pkgs' = import nixpkgs' { + inherit system; + }; deployPkgs = import selfhostblocks.inputs.nixpkgs { inherit system; @@ -309,7 +408,7 @@ system [deploy-rs][deploy-rs]. deploy-rs.overlay (self: super: { deploy-rs = { - inherit (shbPkgs) deploy-rs; + inherit (pkgs') deploy-rs; lib = super.deploy-rs.lib; }; }) @@ -322,7 +421,7 @@ system [deploy-rs][deploy-rs]. ]; }; - nixosConfigurations.machine = shbNixpkgs.lib.nixosSystem { + nixosConfigurations.machine = nixpkgs'.nixosSystem { inherit system; modules = [ self.nixosModules.machine @@ -349,7 +448,7 @@ system [deploy-rs][deploy-rs]. The above snippet assumes one machine to deploy to, so `nixpkgs` is defined exclusively by the `selfhostblocks` input. It is more likely that you have -multiple machines, some not using Self Host Blocks, in this case you can do: +multiple machines, some not using SHB, in this case you can do: ```nix { @@ -362,11 +461,10 @@ multiple machines, some not using Self Host Blocks, in this case you can do: outputs = { self, selfhostblocks }: { let system = "x86_64-linux"; - lib = selfhostblocks.lib.${system}; - - nixpkgs' = lib.shb.patchedNixpkgs; - - shbPkgs = import nixpkgs' { inherit system; }; + nixpkgs' = selfhostblocks.lib.${system}.patchedNixpkgs; + pkgs' = import nixpkgs' { + inherit system; + }; deployPkgs = import selfhostblocks.inputs.nixpkgs { inherit system; @@ -374,7 +472,7 @@ multiple machines, some not using Self Host Blocks, in this case you can do: deploy-rs.overlay (self: super: { deploy-rs = { - inherit (shbPkgs) deploy-rs; + inherit (pkgs') deploy-rs; lib = super.deploy-rs.lib; }; }) @@ -398,7 +496,7 @@ multiple machines, some not using Self Host Blocks, in this case you can do: ]; }; - nixosConfigurations.machine2 = shbNixpkgs.lib.nixosSystem { + nixosConfigurations.machine2 = nixpkgs'.nixosSystem { inherit system; modules = [ self.nixosModules.machine2 @@ -524,12 +622,11 @@ One way to setup secrets management using `sops-nix`: 5. Use `sops-nix` module in nix: ```bash imports = [ - - inputs.sops-nix.nixosModules.default - inputs.selfhostblocks.nixosModules.sops - + inputs.sops-nix.nixosModules.default + inputs.selfhostblocks.nixosModules.sops ]; ``` + Import also the `sops` module provided by SHB. 6. Set default sops file: ```bash sops.defaultSopsFile = ./secrets.yaml; @@ -542,1014 +639,3 @@ One way to setup secrets management using `sops-nix`: ``` The above snippet uses the [secrets contract](./contracts-secret.html) and [sops block](./blocks-sops.html) to ease the configuration. - -## Complete Example {#usage-complete-example} - -This is my own config, which is using Self Host Blocks as well as -[Skarabox][Skarabox], my sibling project used to bootstrap a server. - -[Skarabox]: https://github.com/ibizaman/skarabox - -`flake.nix` - -```nix -{ - description = "Ibizaman's config."; - - inputs = { - selfhostblocks.url = "github:ibizaman/selfhostblocks"; - - skarabox.url = "github:ibizaman/skarabox"; - skarabox.inputs.nixpkgs.follows = "selfhostblocks/nixpkgs"; - - deploy-rs.url = "github:serokell/deploy-rs"; - - sops-nix.url = "github:Mic92/sops-nix"; - }; - - outputs = { self, skarabox, selfhostblocks, sops-nix, deploy-rs }: - let - system = "x86_64-linux"; - lib = selfhostblocks.lib.${system}; - - nixpkgs' = lib.shb.patchedNixpkgs; - - shbPkgs = import nixpkgs' { inherit system; }; - - # Taken from https://github.com/serokell/deploy-rs?tab=readme-ov-file#overall-usage - deployPkgs = import selfhostblocks.inputs.nixpkgs { - inherit system; - overlays = [ - deploy-rs.overlay - (self: super: { - deploy-rs = { - inherit (shbPkgs) deploy-rs; - lib = super.deploy-rs.lib; - }; - }) - ]; - }; - - domain = # My domain here - in - { - nixosModules.skarabox = { - imports = [ - skarabox.nixosModules.skarabox - selfhostblocks.nixosModules.default - sops-nix.nixosModules.default - ({ config, ... }: { - skarabox.hostname = "skarabox"; - skarabox.username = "skarabox"; - skarabox.disks.rootDisk = "/dev/nvme0n1"; - # 10% of size SSD. Default value assumes drive size is 1 Tb. - skarabox.disks.rootReservation = "100G"; - skarabox.disks.dataDisk1 = "/dev/sda"; - skarabox.disks.dataDisk2 = "/dev/sdb"; - # 5% of size Hard Drives. Default value assumes drive size is 10 Tb. - skarabox.disks.dataReservation = "500G"; - skarabox.sshAuthorizedKeyFile = ./ssh_skarabox.pub; - skarabox.hostId = builtins.readFile ./hostid; - # Needed to be able to ssh to decrypt the SSD. - boot.initrd.availableKernelModules = [ - "rtw88_8821ce" - "r8169" - ]; - sops.defaultSopsFile = ./secrets.yaml; - sops.age = { - sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]; - }; - }) - { - me.domain = domain; - } - - ./configuration.nix - ]; - }; - - # Used with nixos-anywere for installation. - nixosConfigurations.skarabox = shbNixpkgs.lib.nixosSystem { - inherit system; - modules = [ - self.nixosModules.skarabox - { - nix.settings.trusted-public-keys = [ - "selfhostblocks.cachix.org-1:H5h6Uj188DObUJDbEbSAwc377uvcjSFOfpxyCFP7cVs=" - ]; - - nix.settings.substituters = [ - "https://selfhostblocks.cachix.org" - ]; - } - ]; - }; - - # Used with deploy-rs for updates. - deploy.nodes.skarabox = { - hostname = domain; - sshUser = "skarabox"; - sshOpts = [ "-o" "IdentitiesOnly=yes" "-i" "ssh_skarabox" ]; - activationTimeout = 600; - profiles = { - system = { - user = "root"; - path = deployPkgs.deploy-rs.lib.activate.nixos self.nixosConfigurations.skarabox; - }; - }; - }; - # From https://github.com/serokell/deploy-rs?tab=readme-ov-file#overall-usage - checks = builtins.mapAttrs (system: deployLib: deployLib.deployChecks self.deploy) deploy-rs.lib; - }; -} -``` - -`configuration.nix` - -```nix -{ config, lib, pkgs, ... }: -let - inherit (lib) optionals optionalAttrs; - inherit (config.me) domain; - - backupCfg = { enable ? true, shbOpt ? null }: name: let - bck = (if shbOpt != null then shbOpt else config.shb.${name}.backup.request); - in { - shb.restic.instances.${name} = { - request = bck; - settings = { - enable = enable; - - passphrase.result = config.shb.sops.secret."${name}/backup/passphrase".result; - - repository = { - path = "/srv/backup/restic/skarabox/${name}"; - timerConfig = { - OnBootSec = "15min"; - OnUnitActiveSec = "1h"; - RandomizedDelaySec = "7min"; - }; - }; - - retention = { - keep_within = "1d"; - keep_hourly = 24; - keep_daily = 7; - keep_weekly = 4; - keep_monthly = 6; - }; - }; - }; - shb.sops.secret."${name}/backup/passphrase" = { - request = config.shb.restic.instances.${name}.settings.passphrase.request; - }; - shb.sops.secret."${name}/backup/b2_access_key_id" = { - request = config.shb.restic.instances.${name}.settings.passphrase.request; - settings.key = "backup/b2/access_key_id"; - }; - shb.sops.secret."${name}/backup/b2_secret_access_key" = { - request = config.shb.restic.instances.${name}.settings.passphrase.request; - settings.key = "backup/b2/secret_access_key"; - }; - }; -in -{ - options = { - me.domain = lib.mkOption { - type = lib.types.str; - }; - }; - - config = lib.mkMerge [ - { - shb.zfs.defaultPoolName = "root"; - sops.defaultSopsFile = ./secrets.yaml; - } - { - services.openssh.listenAddresses = [ - { - addr = "0.0.0.0"; # Needs to be 0.0.0.0 otherwise it cannot bind on boot. - port = 22; - } - { - addr = "0.0.0.0"; - port = 2222; - } - ]; - networking.firewall.allowedTCPPorts = [ 2222 ]; - } - { - networking.firewall.allowedUDPPorts = [ 53 ]; - services.dnsmasq = { - enable = true; - settings = { - # When switching DNS server, accept old leases from previous server. - dhcp-authoritative = true; - - dhcp-range = "192.168.1.101,192.168.1.150,255.255.255.0,6h"; - - dhcp-host = [ - "aa:bb:cc:dd:ee:ff,skarabox,192.168.1.30,infinite" - ]; - - dhcp-option = [ - "3,192.168.1.1" - ]; - - server = [ - # Stubby - # Also https://wiki.archlinux.org/title/Stubby#Change_port - "127.0.0.1#53000" - "::1#53000" - ]; - - log-queries = false; - - # For stubby - proxy-dnssec = true; - - inherit domain; - no-resolv = true; - bogus-priv = true; - strict-order = true; - # Got issues with bind-interface on startup, needing to restart dnsmasq for it to listen correctly. - # bind-interfaces = true; - # add-cpe-id = 858972; - address = (map (hostname: "/${hostname}.${domain}/192.168.1.30") [ - "authelia" - "ldap" - - "forgejo" - "grafana" - "ha" - "hledger" - "jellyfin" - "n" - "vaultwarden" - - "deluge" - "radarr" - "sonarr" - "jackett" - ]) - ++ (map (hostname: "/${hostname}.${domain}/192.168.1.1") [ - "router" - ]); - }; - }; - - services.stubby = { - enable = true; - # https://github.com/getdnsapi/stubby/blob/develop/stubby.yml.example - settings = pkgs.stubby.passthru.settingsExample // { - listen_addresses = [ - "127.0.0.1@53000" - "0::1@53000" - ]; - # https://dnsprivacy.org/public_resolvers/ - # digest from https://nixos.wiki/wiki/Encrypted_DNS#Stubby - upstream_recursive_servers = [{ - address_data = "9.9.9.9"; - tls_auth_name = "dns.quad9.net"; - tls_pubkey_pinset = [{ - digest = "sha256"; - value = "i2kObfz0qIKCGNWt7MjBUeSrh0Dyjb0/zWINImZES+I="; - }]; - } { - address_data = "149.112.112.112"; - tls_auth_name = "dns.quad9.net"; - tls_pubkey_pinset = [{ - digest = "sha256"; - value = "i2kObfz0qIKCGNWt7MjBUeSrh0Dyjb0/zWINImZES+I="; - }]; - }]; - }; - }; - } - { - services.nginx.enable = true; - shb.nginx.accessLog = true; - networking.firewall.allowedTCPPorts = [ 80 443 ]; - - # Need to wait on auth endpoint to be available otherwise nginx can fail to start. - systemd.services.nginx = { - wants = optionals config.services.dnsmasq.enable [ "dnsmasq.service" ]; - after = optionals config.services.dnsmasq.enable [ "dnsmasq.service" ]; - }; - } - - (optionalAttrs true { - shb.user.acme = { - uid = 995; - gid = 994; - }; - - shb.certs.certs.letsencrypt.${domain} = { - inherit domain; - group = "nginx"; - reloadServices = [ "nginx.service" ]; - adminEmail = "ibizaman@${domain}"; - afterAndWants = optionals config.services.dnsmasq.enable [ "dnsmasq.service" ]; - }; - }) - - (optionalAttrs true { - shb.user.lldap = { - uid = 991; - gid = 989; - }; - - shb.certs.certs.letsencrypt.${domain}.extraDomains = [ "ldap.${domain}" ]; - shb.lldap = { - enable = true; - inherit domain; - subdomain = "ldap"; - ssl = config.shb.certs.certs.letsencrypt.${domain}; - ldapPort = 3890; - webUIListenPort = 17170; - dcdomain = "dc=mydomain,dc=com"; - ldapUserPassword.result = config.shb.sops.secret."ldap/user_password".result; - jwtSecret.result = config.shb.sops.secret."ldap/jwt_secret".result; - # restrictAccessIPRange = "192.168.50.0/24"; - debug = false; - }; - shb.sops.secret."ldap/user_password".request = config.shb.lldap.ldapUserPassword.request; - shb.sops.secret."ldap/jwt_secret".request = config.shb.lldap.jwtSecret.request; - - shb.zfs.datasets."safe/ldap2".path = "/var/lib/private/lldap"; - - }) - (backupCfg { - shbOpt = { - user = "root"; - sourceDirectories = [ - "/var/lib/private/lldap/" - ]; - }; } "ldap") - - (optionalAttrs true { - shb.user.authelia = { - uid = 993; - gid = 992; - }; - - shb.certs.certs.letsencrypt.${domain}.extraDomains = [ "authelia.${domain}" ]; - shb.authelia = { - enable = true; - inherit domain; - subdomain = "authelia"; - ssl = config.shb.certs.certs.letsencrypt.${domain}; - - ldapHostname = "127.0.0.1"; - ldapPort = config.shb.lldap.ldapPort; - dcdomain = config.shb.lldap.dcdomain; - - smtp = { - host = "smtp.eu.mailgun.org"; - port = 587; - username = "postmaster@mg.${domain}"; - from_address = "authelia@${domain}"; - password.result = config.shb.sops.secret."authelia/smtp_password".result; - }; - - secrets = { - jwtSecret.result = config.shb.sops.secret."authelia/jwt_secret".result; - ldapAdminPassword.result = config.shb.sops.secret."authelia/ldap_admin_password".result; - sessionSecret.result = config.shb.sops.secret."authelia/session_secret".result; - storageEncryptionKey.result = config.shb.sops.secret."authelia/storage_encryption_key".result; - identityProvidersOIDCHMACSecret.result = config.shb.sops.secret."authelia/hmac_secret".result; - identityProvidersOIDCIssuerPrivateKey.result = config.shb.sops.secret."authelia/private_key".result; - }; - }; - shb.sops.secret."authelia/jwt_secret".request = config.shb.authelia.secrets.jwtSecret.request; - shb.sops.secret."authelia/ldap_admin_password".request = config.shb.authelia.secrets.ldapAdminPassword.request; - shb.sops.secret."authelia/session_secret".request = config.shb.authelia.secrets.sessionSecret.request; - shb.sops.secret."authelia/storage_encryption_key".request = config.shb.authelia.secrets.storageEncryptionKey.request; - shb.sops.secret."authelia/hmac_secret".request = config.shb.authelia.secrets.identityProvidersOIDCHMACSecret.request; - shb.sops.secret."authelia/private_key".request = config.shb.authelia.secrets.identityProvidersOIDCIssuerPrivateKey.request; - shb.sops.secret."authelia/smtp_password".request = config.shb.authelia.smtp.password.request; - - # Need to wait on auth endpoint to be available otherwise nginx can fail to start. - systemd.services."authelia-${domain}" = { - wants = optionals config.services.dnsmasq.enable [ "dnsmasq.service" "nginx.service" ]; - after = optionals config.services.dnsmasq.enable [ "dnsmasq.service" "nginx.service" ]; - }; - - shb.zfs.datasets."safe/authelia-${domain}" = config.shb.authelia.mount; - shb.zfs.datasets."safe/authelia-redis" = config.shb.authelia.mountRedis; - }) - - (optionalAttrs true { - shb.certs.certs.letsencrypt.${domain}.extraDomains = [ "forgejo.${domain}" ]; - shb.forgejo = { - enable = true; - subdomain = "forgejo"; - inherit domain; - ssl = config.shb.certs.certs.letsencrypt."${domain}"; - adminPassword.result = config.shb.sops.secret."forgejo/adminPassword".result; - databasePassword.result = config.shb.sops.secret."forgejo/databasePassword".result; - repositoryRoot = "/srv/projects"; - - smtp = { - host = "smtp.eu.mailgun.org"; - port = 587; - username = "postmaster@mg.${domain}"; - from_address = "authelia@${domain}"; - passwordFile = config.shb.sops.secret."forgejo/smtpPassword".result.path; - }; - - ldap = { - enable = true; - host = "127.0.0.1"; - port = config.shb.lldap.ldapPort; - dcdomain = config.shb.lldap.dcdomain; - adminPassword.result = config.shb.sops.secret."forgejo/ldap_admin_password".result; - }; - - sso = { - enable = true; - endpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}"; - clientID = "forgejo"; - - sharedSecret.result = config.shb.sops.secret."forgejo/ssoSecret".result; - sharedSecretForAuthelia.result = config.shb.sops.secret."forgejo/authelia/ssoSecret".result; - }; - }; - services.forgejo.settings.repository.ENABLE_PUSH_CREATE_USER = true; - - # Need to wait on auth endpoint to be available otherwise nginx can fail to start. - systemd.services."forgejo" = { - wants = optionals config.services.dnsmasq.enable [ "dnsmasq.service" "nginx.service" ]; - after = optionals config.services.dnsmasq.enable [ "dnsmasq.service" "nginx.service" ]; - }; - - nix.settings.trusted-users = [ "forgejo" ]; - users.users.forgejo.openssh.authorizedKeys.keys = [ - "ssh-ed25519 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - ]; - - shb.sops.secret."forgejo/adminPassword" = { - request = config.shb.forgejo.adminPassword.request; - }; - shb.sops.secret."forgejo/databasePassword" = { - request = config.shb.forgejo.databasePassword.request; - }; - shb.sops.secret."forgejo/smtpPassword".request = { - mode = "0400"; - owner = config.services.forgejo.user; - restartUnits = [ "forgejo.service" ]; - }; - shb.sops.secret."forgejo/ldap_admin_password" = { - request = config.shb.forgejo.ldap.adminPassword.request; - settings.key = "ldap/user_password"; - }; - shb.sops.secret."forgejo/ssoSecret" = { - request = config.shb.forgejo.sso.sharedSecret.request; - }; - shb.sops.secret."forgejo/authelia/ssoSecret" = { - request = config.shb.forgejo.sso.sharedSecretForAuthelia.request; - settings.key = "forgejo/ssoSecret"; - }; - - shb.zfs.datasets."safe/forgejo" = config.shb.forgejo.mount; - }) - (optionalAttrs true (backupCfg {} "forgejo")) - - (optionalAttrs true { - shb.user.vaultwarden = { - uid = 989; - gid = 987; - }; - - shb.certs.certs.letsencrypt.${domain}.extraDomains = [ "vaultwarden.${domain}" ]; - shb.vaultwarden = { - enable = true; - inherit domain; - subdomain = "vaultwarden"; - ssl = config.shb.certs.certs.letsencrypt.${domain}; - port = 8222; - authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}"; - databasePassword.result = config.shb.sops.secret."vaultwarden/db".result; - smtp = { - host = "smtp.eu.mailgun.org"; - port = 587; - username = "postmaster@mg.${domain}"; - from_address = "authelia@${domain}"; - password.result = config.shb.sops.secret."vaultwarden/smtp".result; - }; - }; - shb.sops.secret."vaultwarden/db" = { - request = config.shb.vaultwarden.databasePassword.request; - }; - shb.sops.secret."vaultwarden/smtp" = { - request = config.shb.vaultwarden.smtp.password.request; - }; - - shb.zfs.datasets."safe/vaultwarden" = config.shb.vaultwarden.mount; - shb.zfs.datasets."safe/postgresql".path = "/var/lib/postgresql"; - systemd.services."restic-backups-vaultwarden_s3_s3.us-west-000.backblazeb2.com_skarabox-backup_vaultwarden.service" = { - wants = optionals config.services.dnsmasq.enable [ "dnsmasq.service" ]; - after = optionals config.services.dnsmasq.enable [ "dnsmasq.service" ]; - }; - systemd.services."restic-backups-vaultwarden_srv_backup_restic_skarabox_vaultwarden.service" = { - wants = optionals config.services.dnsmasq.enable [ "dnsmasq.service" ]; - after = optionals config.services.dnsmasq.enable [ "dnsmasq.service" ]; - }; - - }) - (optionalAttrs true (backupCfg {} "vaultwarden")) - - (optionalAttrs true { - shb.zfs.datasets."safe/nextcloud".path = "/var/lib/nextcloud"; - shb.zfs.datasets."safe/redis-nextcloud".path = "/var/lib/redis-nextcloud"; - shb.zfs.datasets."nextcloud" = { - poolName = "zdata"; - path = "/srv/nextcloud/data"; - }; - shb.user.nextcloud.uid = 10020; - - shb.certs.certs.letsencrypt.${domain}.extraDomains = [ "n.${domain}" ]; - shb.nextcloud = { - enable = true; - debug = false; - inherit domain; - subdomain = "n"; - ssl = config.shb.certs.certs.letsencrypt.${domain}; - defaultPhoneRegion = "US"; - - version = 29; - dataDir = "/var/lib/nextcloud"; - adminPass.result = config.shb.sops.secret."nextcloud/adminpass".result; - apps = { - previewgenerator.enable = true; - externalStorage = { - enable = true; - userLocalMount.directory = "/srv/nextcloud/data/$user/files"; - userLocalMount.mountName = "/"; - }; - ldap = { - enable = true; - host = "127.0.0.1"; - port = config.shb.lldap.ldapPort; - dcdomain = config.shb.lldap.dcdomain; - adminName = "admin"; - adminPassword.result = config.shb.sops.secret."nextcloud/ldap_admin_password".result; - userGroup = "nextcloud_user"; - }; - sso = { - enable = true; - endpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}"; - clientID = "nextcloud"; - - secret.result = config.shb.sops.secret."nextcloud/sso/secret".result; - secretForAuthelia.result = config.shb.sops.secret."authelia/nextcloud_sso_secret".result; - - fallbackDefaultAuth = false; - }; - }; - extraApps = apps: { - inherit (apps) - bookmarks - calendar - contacts - groupfolders - mail - ; - }; - postgresSettings = { - # From https://pgtune.leopard.in.ua/ with: - - # DB Version: 14 - # OS Type: linux - # DB Type: dw - # Total Memory (RAM): 12 GB - # CPUs num: 4 - # Connections num: - # Data Storage: ssd - - max_connections = "400"; - shared_buffers = "3GB"; - effective_cache_size = "9GB"; - maintenance_work_mem = "768MB"; - checkpoint_completion_target = "0.9"; - wal_buffers = "16MB"; - default_statistics_target = "100"; - random_page_cost = "1.1"; - effective_io_concurrency = "200"; - work_mem = "7864kB"; - huge_pages = "off"; - min_wal_size = "1GB"; - max_wal_size = "4GB"; - max_worker_processes = "4"; - max_parallel_workers_per_gather = "2"; - max_parallel_workers = "4"; - max_parallel_maintenance_workers = "2"; - }; - # Chose static and small number of children to avoid too much I/O strain on hard drives. - phpFpmPoolSettings = { - "pm" = "static"; - "pm.max_children" = 150; - }; - }; - systemd.services.postgresql.serviceConfig.Restart = "always"; - # Secret needed for services.nextcloud.config.adminpassFile. - shb.sops.secret."nextcloud/adminpass" = { - request = config.shb.nextcloud.adminPass.request; - }; - shb.sops.secret."nextcloud/ldap_admin_password" = { - request = config.shb.nextcloud.apps.ldap.adminPassword.request; - settings.key = "ldap/user_password"; - }; - - shb.sops.secret."nextcloud/sso/secret" = { - request = config.shb.nextcloud.apps.sso.secret.request; - }; - shb.sops.secret."authelia/nextcloud_sso_secret" = { - request = config.shb.nextcloud.apps.sso.secretForAuthelia.request; - settings.key = "nextcloud/sso/secret"; - }; - }) - (optionalAttrs true (backupCfg {} "nextcloud")) - (optionalAttrs true (backupCfg { - shbOpt = { - user = "nextcloud"; - sourceDirectories = [ - "/srv/nextcloud/data" - ]; - }; - } "nextcloud-data")) - - (optionalAttrs true { - shb.user.jellyfin = { - uid = 984; - gid = 981; - extraGroups = [ "media" ]; - }; - - shb.certs.certs.letsencrypt.${domain}.extraDomains = [ "jellyfin.${domain}" ]; - shb.jellyfin = { - enable = true; - inherit domain; - subdomain = "jellyfin"; - ssl = config.shb.certs.certs.letsencrypt.${domain}; - ldap = { - enable = true; - host = "127.0.0.1"; - port = config.shb.lldap.ldapPort; - dcdomain = config.shb.lldap.dcdomain; - adminPassword.result = config.shb.sops.secret."jellyfin/ldap_password".result; - userGroup = "jellyfin_user"; - }; - sso = { - enable = true; - endpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}"; - clientID = "jellyfin"; - sharedSecret.result = config.shb.sops.secret."jellyfin/sso_secret".result; - sharedSecretForAuthelia.result = config.shb.sops.secret."jellyfin/authelia/sso_secret".result; - userGroup = "jellyfin_user"; - adminUserGroup = "jellyfin_admin"; - }; - }; - shb.sops.secret."jellyfin/ldap_password" = { - request = config.shb.jellyfin.ldap.adminPassword.request; - settings.key = "ldap/user_password"; - }; - shb.sops.secret."jellyfin/sso_secret" = { - request = config.shb.jellyfin.sso.sharedSecret.request; - }; - shb.sops.secret."jellyfin/authelia/sso_secret" = { - request = config.shb.jellyfin.sso.sharedSecretForAuthelia.request; - settings.key = "jellyfin/sso_secret"; - }; - - shb.zfs.datasets."safe/jellyfin".path = "/var/lib/jellyfin"; - }) - (backupCfg {} "jellyfin") - - (optionalAttrs true { - shb.user.hass = { - uid = 286; - gid = 286; - }; - - shb.certs.certs.letsencrypt.${domain}.extraDomains = [ "ha.${domain}" ]; - shb.home-assistant = { - enable = true; - inherit domain; - subdomain = "ha"; - ssl = config.shb.certs.certs.letsencrypt.${domain}; - - config = { - name = "Skarabox"; - country.source = config.shb.sops.secret."home-assistant/country".result.path; - latitude.source = config.shb.sops.secret."home-assistant/latitude_home".result.path; - longitude.source = config.shb.sops.secret."home-assistant/longitude_home".result.path; - time_zone.source = config.shb.sops.secret."home-assistant/time_zone".result.path; - unit_system = "metric"; - }; - - ldap = { - enable = true; - host = "127.0.0.1"; - port = config.shb.lldap.webUIListenPort; - userGroup = "homeassistant_user"; - }; - }; - shb.sops.secret."home-assistant/country".request = { - mode = "0440"; - owner = "hass"; - group = "hass"; - restartUnits = [ "home-assistant.service" ]; - }; - shb.sops.secret."home-assistant/latitude_home".request = { - mode = "0440"; - owner = "hass"; - group = "hass"; - restartUnits = [ "home-assistant.service" ]; - }; - shb.sops.secret."home-assistant/longitude_home".request = { - mode = "0440"; - owner = "hass"; - group = "hass"; - restartUnits = [ "home-assistant.service" ]; - }; - shb.sops.secret."home-assistant/time_zone".request = { - mode = "0440"; - owner = "hass"; - group = "hass"; - restartUnits = [ "home-assistant.service" ]; - }; - services.home-assistant = { - extraComponents = [ - "accuweather" - "apple_tv" - "asuswrt" - "backup" - "bluetooth" - "cast" - "deluge" - "esphome" - "ibeacon" - "icloud" - "ipp" - "jellyfin" - "kegtron" - "kodi" - "nest" - "nmap_tracker" - "openweathermap" - "oralb" - "overkiz" - "philips_js" - "radarr" - "simplisafe" - "somfy" - "somfy_mylink" - "sonarr" - "sonos" - "subaru" - "tradfri" - "wled" - "zha" - - "assist_pipeline" - "conversation" - "piper" - "wake_word" - "whisper" - "wyoming" - ]; - - # Need to add them manually by enabling advanced mode in user profile - # then adding in Settings > Dashboards > Resources: - # - /local/nixos-lovelace-modules/mini-graph-card-bundle.js - # - /local/nixos-lovelace-modules/mini-media-player-bundle.js - customLovelaceModules = with pkgs.home-assistant-custom-lovelace-modules; [ - mini-graph-card - mini-media-player - ]; - extraPackages = python3Packages: [ - python3Packages.grpcio # Needed for nest - ]; - }; - users.users.hass.extraGroups = [ "dialout" ]; - nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (pkgs.lib.getName pkg) [ - "python-nest" - ]; - - shb.zfs.datasets."safe/home-assistant".path = "/var/lib/hass"; - }) - (backupCfg {} "home-assistant") - - (optionalAttrs true { - shb.user.grafana = { - uid = 196; - gid = 986; - }; - shb.user.loki = { - uid = 988; - gid = 985; - }; - shb.user.netdata = { - uid = 987; - gid = 984; - }; - - shb.certs.certs.letsencrypt.${domain}.extraDomains = [ "grafana.${domain}" ]; - shb.monitoring = { - enable = true; - inherit domain; - subdomain = "grafana"; - ssl = config.shb.certs.certs.letsencrypt.${domain}; - - contactPoints = [ "ibizaman@${domain}" ]; - adminPassword.result = config.shb.sops.secret."monitoring/admin_password".result; - secretKey.result = config.shb.sops.secret."monitoring/secret_key".result; - smtp = { - from_address = "grafana@${domain}"; - from_name = "Grafana"; - host = "smtp.mailgun.org"; - port = 587; - username = "postmaster@mg.${domain}"; - passwordFile = config.shb.sops.secret."monitoring/smtp".result.path; - }; - }; - shb.sops.secret."monitoring/smtp".request = { - mode = "0400"; - owner = "grafana"; - group = "grafana"; - restartUnits = [ "grafana.service" ]; - }; - shb.sops.secret."monitoring/admin_password".request = config.shb.monitoring.adminPassword.request; - shb.sops.secret."monitoring/secret_key".request = config.shb.monitoring.secretKey.request; - - services.prometheus.scrapeConfigs = [ - { - job_name = "netdata"; - metrics_path = "/api/v1/allmetrics?format=prometheus&help=yes&source=as-collected"; - static_configs = [ - { - targets = ["192.168.50.168:19999"]; - } - ]; - } - ]; - - shb.zfs.datasets."safe/grafana".path = "/var/lib/grafana"; - shb.zfs.datasets."safe/loki".path = "/var/lib/loki"; - shb.zfs.datasets."safe/netdata".path = "/var/lib/netdata"; - }) - - (optionalAttrs true { - shb.user.hledger.uid = 990; - - shb.certs.certs.letsencrypt.${domain}.extraDomains = [ "hledger.${domain}" ]; - shb.hledger = { - enable = true; - inherit domain; - subdomain = "hledger"; - ssl = config.shb.certs.certs.letsencrypt.${domain}; - authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}"; - localNetworkIPRange = "192.168.1.0/24"; - }; - - shb.zfs.datasets."safe/hledger".path = "/var/lib/hledger"; - }) - (backupCfg {} "hledger") - - (optionalAttrs true { - shb.vpn.nordvpnfr = { - enable = true; - provider = "nordvpn"; - dev = "tun2"; - routingNumber = 11; - remoteServerIP = # One of the servers - authFile = config.shb.sops.secret."nordvpnfr/auth".result.path; - proxyPort = 12001; - }; - shb.sops.secret."nordvpnfr/auth".request = { - mode = "0440"; - restartUnits = [ "openvpn-nordvpnfr.service" ]; - }; - - shb.user.deluge.uid = 10001; - - shb.certs.certs.letsencrypt.${domain}.extraDomains = [ "deluge.${domain}" ]; - shb.deluge = { - enable = true; - inherit domain; - subdomain = "deluge"; - ssl = config.shb.certs.certs.letsencrypt.${domain}; - - daemonPort = 58846; - daemonListenPorts = [ 6881 6889 ]; - webPort = 8112; - # Some things do not work with the proxy, so instead bind to the interface directly - # proxyPort = config.shb.vpn.nordvpnus.proxyPort; - outgoingInterface = config.shb.vpn.nordvpnfr.dev; - authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}"; - localclientPassword.result = config.shb.sops.secret."deluge/auth/localclient".result; - extraUsers = { - ibizaman.password.source = config.shb.sops.secret."deluge/auth/ibizaman".result.path; - }; - prometheusScraperPassword.result = config.shb.sops.secret."deluge/auth/prometheus".result; - settings = { - downloadLocation = "/srv/downloads"; - }; - extraServiceConfig = { - MemoryHigh = "5G"; - MemoryMax = "6G"; - }; - logLevel = "info"; - }; - shb.sops.secret."deluge/auth/localclient".request = config.shb.deluge.localclientPassword.request; - shb.sops.secret."deluge/auth/ibizaman".request = { - mode = "0440"; - owner = config.services.deluge.user; - group = config.services.deluge.group; - restartUnits = [ "deluged.service" "delugeweb.service" ]; - }; - shb.sops.secret."deluge/auth/prometheus".request = config.shb.deluge.prometheusScraperPassword.request; - - shb.zfs.datasets."safe/deluge".path = "/var/lib/deluge"; - }) - (backupCfg {} "deluge") - - (optionalAttrs true { - shb.user.radarr.uid = 10010; - shb.user.radarr.extraGroups = [ "media" ]; - shb.user.sonarr.uid = 10011; - shb.user.sonarr.extraGroups = [ "media" ]; - shb.user.jackett.uid = 10015; - - shb.certs.certs.letsencrypt.${domain}.extraDomains = [ - "moviesdl.${domain}" - "seriesdl.${domain}" - "subtitlesdl.${domain}" - "booksdl.${domain}" - "musicdl.${domain}" - "indexer.${domain}" - ]; - shb.arr = { - radarr = { - subdomain = "radarr"; - inherit domain; - enable = true; - ssl = config.shb.certs.certs.letsencrypt.${domain}; - authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}"; - settings = { - ApiKey.source = config.shb.sops.secret."radarr/apikey".result.path; - }; - }; - sonarr = { - subdomain = "sonarr"; - inherit domain; - enable = true; - ssl = config.shb.certs.certs.letsencrypt."${domain}"; - authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}"; - settings = { - ApiKey.source = config.shb.sops.secret."sonarr/apikey".result.path; - }; - }; - jackett = { - subdomain = "jackett"; - inherit domain; - enable = true; - ssl = config.shb.certs.certs.letsencrypt."${domain}"; - authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}"; - settings = { - ApiKey.source = config.shb.sops.secret."jackett/apikey".result.path; - ProxyType = "0"; - ProxyUrl = "127.0.0.1:${toString config.shb.vpn.nordvpnfr.proxyPort}"; - }; - }; - }; - shb.sops.secret."radarr/apikey".request = { - mode = "0440"; - owner = "radarr"; - group = "radarr"; - restartUnits = [ "radarr.service" ]; - }; - shb.sops.secret."sonarr/apikey".request = { - mode = "0440"; - owner = "sonarr"; - group = "sonarr"; - restartUnits = [ "sonarr.service" ]; - }; - shb.sops.secret."jackett/apikey".request = { - mode = "0440"; - owner = "jackett"; - group = "jackett"; - restartUnits = [ "jackett.service" ]; - }; - - shb.zfs.datasets."safe/radarr".path = "/var/lib/radarr"; - shb.zfs.datasets."safe/sonarr".path = "/var/lib/sonarr"; - shb.zfs.datasets."safe/jackett".path = "/var/lib/jackett"; - }) - (backupCfg { shbOpt = config.shb.arr.radarr; } "radarr") - (backupCfg { shbOpt = config.shb.arr.sonarr; } "sonarr") - (backupCfg { shbOpt = config.shb.arr.jackett; } "jackett") - ]; -} -```