This commit is contained in:
Chris Kruining 2025-12-01 14:14:32 +01:00
parent 331a912c82
commit 9f1a6e85ee
No known key found for this signature in database
GPG key ID: EB894A3560CCCAD2
16 changed files with 541 additions and 467 deletions

View file

@ -1,11 +1,11 @@
@_default: list @_default: list
[doc('List machines')] [doc('List machines')]
@list: @list:
ls -1 ../systems/x86_64-linux/ ls -1 ../systems/x86_64-linux/
[no-exit-message] [no-exit-message]
[doc('Update the target machine')] [doc('Update the target machine')]
@update machine: @update machine:
just assert '-d "../systems/x86_64-linux/{{ machine }}"' "Machine {{ machine }} does not exist, must be one of: $(ls ../systems/x86_64-linux/ | tr '\n' ' ')" just assert '-d "../systems/x86_64-linux/{{ machine }}"' "Machine {{ machine }} does not exist, must be one of: $(ls ../systems/x86_64-linux/ | tr '\n' ' ')"
nixos-rebuild switch --use-remote-sudo --target-host {{ machine }} --flake ..#{{ machine }} nixos-rebuild switch --use-remote-sudo --target-host {{ machine }} --flake ..#{{ machine }}

View file

@ -1,36 +1,36 @@
set unstable set unstable
base_path := invocation_directory() / "systems/x86_64-linux" base_path := invocation_directory() / "systems/x86_64-linux"
# sops := "nix shell nixpkgs#sops --command sops" # sops := "nix shell nixpkgs#sops --command sops"
# yq := "nix shell nixpkgs#yq --command yq" # yq := "nix shell nixpkgs#yq --command yq"
sops := "sops" sops := "sops"
yq := "yq" yq := "yq"
@_default: @_default:
just --list just --list
[doc('list all vars of the target machine')] [doc('list all vars of the target machine')]
list machine: list machine:
sops decrypt {{ base_path }}/{{ machine }}/secrets.yml sops decrypt {{ base_path }}/{{ machine }}/secrets.yml
@edit machine: @edit machine:
sops edit {{ base_path }}/{{ machine }}/secrets.yml sops edit {{ base_path }}/{{ machine }}/secrets.yml
@set machine key value: @set machine key value:
sops set {{ base_path }}/{{ machine }}/secrets.yml "$(printf '%s\n' '["{{ key }}"]' | sed -E 's#/#"]["#g; s/\["([0-9]+)"\]/[\1]/g')" "\"$(echo '{{ value }}' | sed 's/\"/\\\"/g')\"" sops set {{ base_path }}/{{ machine }}/secrets.yml "$(printf '%s\n' '["{{ key }}"]' | sed -E 's#/#"]["#g; s/\["([0-9]+)"\]/[\1]/g')" "\"$(echo '{{ value }}' | sed 's/\"/\\\"/g')\""
git add {{ base_path }}/{{ machine }}/secrets.yml git add {{ base_path }}/{{ machine }}/secrets.yml
git commit -m 'chore(secrets): set secret "{{ key }}" for machine "{{ machine}}"' -- {{ base_path }}/{{ machine }}/secrets.yml > /dev/null git commit -m 'chore(secrets): set secret "{{ key }}" for machine "{{ machine}}"' -- {{ base_path }}/{{ machine }}/secrets.yml > /dev/null
echo "Done" echo "Done"
@get machine key: @get machine key:
sops decrypt {{ base_path }}/{{ machine }}/secrets.yml | yq ".$(echo "{{ key }}" | sed -E 's/\//./g')" sops decrypt {{ base_path }}/{{ machine }}/secrets.yml | yq ".$(echo "{{ key }}" | sed -E 's/\//./g')"
@remove machine key: @remove machine key:
sops unset {{ base_path }}/{{ machine }}/secrets.yml "$(printf '%s\n' '["{{ key }}"]' | sed -E 's#/#"]["#g; s/\["([0-9]+)"\]/[\1]/g')" sops unset {{ base_path }}/{{ machine }}/secrets.yml "$(printf '%s\n' '["{{ key }}"]' | sed -E 's#/#"]["#g; s/\["([0-9]+)"\]/[\1]/g')"
git add {{ base_path }}/{{ machine }}/secrets.yml git add {{ base_path }}/{{ machine }}/secrets.yml
git commit -m 'chore(secrets): removed secret "{{ key }}" from machine "{{ machine}}"' -- {{ base_path }}/{{ machine }}/secrets.yml > /dev/null git commit -m 'chore(secrets): removed secret "{{ key }}" from machine "{{ machine}}"' -- {{ base_path }}/{{ machine }}/secrets.yml > /dev/null
echo "Done" echo "Done"

View file

@ -1,33 +1,33 @@
@_default: @_default:
just --list --list-submodules just --list --list-submodules
[doc('Manage vars')] [doc('Manage vars')]
mod vars '.just/vars.just' mod vars '.just/vars.just'
[doc('Manage machines')] [doc('Manage machines')]
mod machine '.just/machine.just' mod machine '.just/machine.just'
[doc('Show information about project')] [doc('Show information about project')]
@show: @show:
echo "show" echo "show"
[doc('update the flake dependencies')] [doc('update the flake dependencies')]
@update: @update:
nix flake update nix flake update
git commit -m 'chore: update dependencies' -- ./flake.lock > /dev/null git commit -m 'chore: update dependencies' -- ./flake.lock > /dev/null
echo "Done" echo "Done"
[doc('Introspection on flake output')] [doc('Introspection on flake output')]
@select key: @select key:
nix eval --json .#{{ key }} | jq . nix eval --json .#{{ key }} | jq .
#=============================================================================================== #===============================================================================================
# Utils # Utils
#=============================================================================================== #===============================================================================================
[no-exit-message] [no-exit-message]
[no-cd] [no-cd]
[private] [private]
@assert condition message: @assert condition message:
[ {{ condition }} ] || { echo -e 1>&2 "\n\x1b[1;41m Error \x1b[0m {{ message }}\n"; exit 1; } [ {{ condition }} ] || { echo -e 1>&2 "\n\x1b[1;41m Error \x1b[0m {{ message }}\n"; exit 1; }

129
flake.lock generated
View file

@ -402,7 +402,7 @@
}, },
"flake-utils-plus": { "flake-utils-plus": {
"inputs": { "inputs": {
"flake-utils": "flake-utils_4" "flake-utils": "flake-utils_5"
}, },
"locked": { "locked": {
"lastModified": 1715533576, "lastModified": 1715533576,
@ -457,7 +457,25 @@
}, },
"flake-utils_4": { "flake-utils_4": {
"inputs": { "inputs": {
"systems": "systems_6" "systems": "systems_5"
},
"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_5": {
"inputs": {
"systems": "systems_7"
}, },
"locked": { "locked": {
"lastModified": 1694529238, "lastModified": 1694529238,
@ -662,6 +680,25 @@
"type": "github" "type": "github"
} }
}, },
"mydia": {
"inputs": {
"flake-utils": "flake-utils_3",
"nixpkgs": "nixpkgs_5"
},
"locked": {
"lastModified": 1764568388,
"narHash": "sha256-kl8165eI0lUz9E96sdreZ48/nApydDfJP8IksjBveAw=",
"owner": "getmydia",
"repo": "mydia",
"rev": "74f0cf9a8ca782581ec0a35acf6526fccfbb6e2a",
"type": "github"
},
"original": {
"owner": "getmydia",
"repo": "mydia",
"type": "github"
}
},
"nix-darwin": { "nix-darwin": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@ -708,8 +745,8 @@
"nix-minecraft": { "nix-minecraft": {
"inputs": { "inputs": {
"flake-compat": "flake-compat_3", "flake-compat": "flake-compat_3",
"flake-utils": "flake-utils_3", "flake-utils": "flake-utils_4",
"nixpkgs": "nixpkgs_5" "nixpkgs": "nixpkgs_6"
}, },
"locked": { "locked": {
"lastModified": 1763171892, "lastModified": 1763171892,
@ -856,6 +893,22 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs_10": {
"locked": {
"lastModified": 1762977756,
"narHash": "sha256-4PqRErxfe+2toFJFgcRKZ0UI9NSIOJa+7RXVtBhy4KE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "c5ae371f1a6a7fd27823bc500d9390b38c05fa55",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1763469780, "lastModified": 1763469780,
@ -905,6 +958,22 @@
} }
}, },
"nixpkgs_5": { "nixpkgs_5": {
"locked": {
"lastModified": 1764242076,
"narHash": "sha256-sKoIWfnijJ0+9e4wRvIgm/HgE27bzwQxcEmo2J/gNpI=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "2fad6eac6077f03fe109c4d4eb171cf96791faa4",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_6": {
"locked": { "locked": {
"lastModified": 1748929857, "lastModified": 1748929857,
"narHash": "sha256-lcZQ8RhsmhsK8u7LIFsJhsLh/pzR9yZ8yqpTzyGdj+Q=", "narHash": "sha256-lcZQ8RhsmhsK8u7LIFsJhsLh/pzR9yZ8yqpTzyGdj+Q=",
@ -920,7 +989,7 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs_6": { "nixpkgs_7": {
"locked": { "locked": {
"lastModified": 1763421233, "lastModified": 1763421233,
"narHash": "sha256-Stk9ZYRkGrnnpyJ4eqt9eQtdFWRRIvMxpNRf4sIegnw=", "narHash": "sha256-Stk9ZYRkGrnnpyJ4eqt9eQtdFWRRIvMxpNRf4sIegnw=",
@ -936,7 +1005,7 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs_7": { "nixpkgs_8": {
"locked": { "locked": {
"lastModified": 1761880412, "lastModified": 1761880412,
"narHash": "sha256-QoJjGd4NstnyOG4mm4KXF+weBzA2AH/7gn1Pmpfcb0A=", "narHash": "sha256-QoJjGd4NstnyOG4mm4KXF+weBzA2AH/7gn1Pmpfcb0A=",
@ -952,7 +1021,7 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs_8": { "nixpkgs_9": {
"locked": { "locked": {
"lastModified": 1763191728, "lastModified": 1763191728,
"narHash": "sha256-esRhOS0APE6k40Hs/jjReXg+rx+J5LkWw7cuWFKlwYA=", "narHash": "sha256-esRhOS0APE6k40Hs/jjReXg+rx+J5LkWw7cuWFKlwYA=",
@ -968,22 +1037,6 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs_9": {
"locked": {
"lastModified": 1762977756,
"narHash": "sha256-4PqRErxfe+2toFJFgcRKZ0UI9NSIOJa+7RXVtBhy4KE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "c5ae371f1a6a7fd27823bc500d9390b38c05fa55",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nur": { "nur": {
"inputs": { "inputs": {
"flake-parts": [ "flake-parts": [
@ -1014,8 +1067,8 @@
"flake-compat": "flake-compat_4", "flake-compat": "flake-compat_4",
"flake-parts": "flake-parts_2", "flake-parts": "flake-parts_2",
"mnw": "mnw", "mnw": "mnw",
"nixpkgs": "nixpkgs_7", "nixpkgs": "nixpkgs_8",
"systems": "systems_5" "systems": "systems_6"
}, },
"locked": { "locked": {
"lastModified": 1762622004, "lastModified": 1762622004,
@ -1065,11 +1118,12 @@
"himmelblau": "himmelblau", "himmelblau": "himmelblau",
"home-manager": "home-manager", "home-manager": "home-manager",
"jovian": "jovian", "jovian": "jovian",
"mydia": "mydia",
"nix-minecraft": "nix-minecraft", "nix-minecraft": "nix-minecraft",
"nixos-boot": "nixos-boot", "nixos-boot": "nixos-boot",
"nixos-generators": "nixos-generators", "nixos-generators": "nixos-generators",
"nixos-wsl": "nixos-wsl", "nixos-wsl": "nixos-wsl",
"nixpkgs": "nixpkgs_6", "nixpkgs": "nixpkgs_7",
"nvf": "nvf", "nvf": "nvf",
"plasma-manager": "plasma-manager", "plasma-manager": "plasma-manager",
"snowfall-lib": "snowfall-lib", "snowfall-lib": "snowfall-lib",
@ -1162,7 +1216,7 @@
}, },
"sops-nix_2": { "sops-nix_2": {
"inputs": { "inputs": {
"nixpkgs": "nixpkgs_8" "nixpkgs": "nixpkgs_9"
}, },
"locked": { "locked": {
"lastModified": 1763509310, "lastModified": 1763509310,
@ -1187,9 +1241,9 @@
"firefox-gnome-theme": "firefox-gnome-theme", "firefox-gnome-theme": "firefox-gnome-theme",
"flake-parts": "flake-parts_3", "flake-parts": "flake-parts_3",
"gnome-shell": "gnome-shell", "gnome-shell": "gnome-shell",
"nixpkgs": "nixpkgs_9", "nixpkgs": "nixpkgs_10",
"nur": "nur", "nur": "nur",
"systems": "systems_7", "systems": "systems_8",
"tinted-foot": "tinted-foot", "tinted-foot": "tinted-foot",
"tinted-kitty": "tinted-kitty", "tinted-kitty": "tinted-kitty",
"tinted-schemes": "tinted-schemes", "tinted-schemes": "tinted-schemes",
@ -1330,13 +1384,28 @@
"type": "github" "type": "github"
} }
}, },
"systems_9": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"terranix": { "terranix": {
"inputs": { "inputs": {
"flake-parts": "flake-parts_4", "flake-parts": "flake-parts_4",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
], ],
"systems": "systems_8" "systems": "systems_9"
}, },
"locked": { "locked": {
"lastModified": 1762472226, "lastModified": 1762472226,

View file

@ -88,49 +88,54 @@
url = "https://git.clan.lol/clan/clan-core/archive/main.tar.gz"; url = "https://git.clan.lol/clan/clan-core/archive/main.tar.gz";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
mydia = {
url = "github:getmydia/mydia";
};
}; };
outputs = inputs: inputs.snowfall-lib.mkFlake { outputs = inputs:
inherit inputs; inputs.snowfall-lib.mkFlake {
src = ./.; inherit inputs;
src = ./.;
snowfall = { snowfall = {
namespace = "sneeuwvlok"; namespace = "sneeuwvlok";
meta = { meta = {
name = "sneeuwvlok"; name = "sneeuwvlok";
title = "Sneeuwvlok"; title = "Sneeuwvlok";
};
}; };
};
channels-config = { channels-config = {
allowUnfree = true; allowUnfree = true;
permittedInsecurePackages = [ permittedInsecurePackages = [
# Due to *arr stack # Due to *arr stack
"dotnet-sdk-6.0.428" "dotnet-sdk-6.0.428"
"aspnetcore-runtime-6.0.36" "aspnetcore-runtime-6.0.36"
# I think this is because of zen # I think this is because of zen
"qtwebengine-5.15.19" "qtwebengine-5.15.19"
# For Nheko, the matrix client # For Nheko, the matrix client
"olm-3.2.16" "olm-3.2.16"
];
};
overlays = with inputs; [
fenix.overlays.default
nix-minecraft.overlay
flux.overlays.default
];
systems.modules = with inputs; [
clan-core.nixosModules.default
];
homes.modules = with inputs; [
stylix.homeModules.stylix
plasma-manager.homeModules.plasma-manager
]; ];
}; };
overlays = with inputs; [
fenix.overlays.default
nix-minecraft.overlay
flux.overlays.default
];
systems.modules = with inputs; [
clan-core.nixosModules.default
];
homes.modules = with inputs; [
stylix.homeModules.stylix
plasma-manager.homeModules.plasma-manager
];
};
} }

View file

@ -1,55 +1,55 @@
{ inputs, config, lib, pkgs, namespace, ... }: { inputs, config, lib, pkgs, namespace, ... }:
let let
inherit (lib) mkIf mkEnableOption; inherit (lib) mkIf mkEnableOption;
cfg = config.${namespace}.application.steam; cfg = config.${namespace}.application.steam;
in in
{ {
options.${namespace}.application.steam = { options.${namespace}.application.steam = {
enable = mkEnableOption "enable steam"; enable = mkEnableOption "enable steam";
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
home.packages = with pkgs; [ protonup-ng ]; home.packages = with pkgs; [ protonup-ng ];
home.sessionVariables = { home.sessionVariables = {
STEAM_EXTRA_COMPAT_TOOLS_PATHS = "\${HOME}/.steam/root/compatibilitytools.d"; STEAM_EXTRA_COMPAT_TOOLS_PATHS = "\${HOME}/.steam/root/compatibilitytools.d";
}; };
programs = { programs = {
# steam = { # steam = {
# enable = true; # enable = true;
# package = pkgs.steam-small.override { # package = pkgs.steam-small.override {
# extraEnv = { # extraEnv = {
# DXVK_HUD = "compiler"; # DXVK_HUD = "compiler";
# MANGOHUD = true; # MANGOHUD = true;
# }; # };
# }; # };
# gamescopeSession = { # gamescopeSession = {
# enable = true; # enable = true;
# args = ["--immediate-flips"]; # args = ["--immediate-flips"];
# }; # };
# }; # };
# https://github.com/FeralInteractive/gamemode # https://github.com/FeralInteractive/gamemode
# gamemode = { # gamemode = {
# enable = true; # enable = true;
# enableRenice = true; # enableRenice = true;
# settings = {}; # settings = {};
# }; # };
# gamescope = { # gamescope = {
# enable = true; # enable = true;
# capSysNice = true; # capSysNice = true;
# env = { # env = {
# DXVK_HDR = "1"; # DXVK_HDR = "1";
# ENABLE_GAMESCOPE_WSI = "1"; # ENABLE_GAMESCOPE_WSI = "1";
# WINE_FULLSCREEN_FSR = "1"; # WINE_FULLSCREEN_FSR = "1";
# WLR_RENDERER = "vulkan"; # WLR_RENDERER = "vulkan";
# }; # };
# args = ["--hdr-enabled"]; # args = ["--hdr-enabled"];
# }; # };
}; };
}; };
} }

View file

@ -1,15 +1,15 @@
{ inputs, config, lib, pkgs, namespace, ... }: { inputs, config, lib, pkgs, namespace, ... }:
let let
inherit (lib) mkIf mkEnableOption; inherit (lib) mkIf mkEnableOption;
cfg = config.${namespace}.application.teamspeak; cfg = config.${namespace}.application.teamspeak;
in in
{ {
options.${namespace}.application.teamspeak = { options.${namespace}.application.teamspeak = {
enable = mkEnableOption "enable teamspeak"; enable = mkEnableOption "enable teamspeak";
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
home.packages = with pkgs; [ teamspeak3 teamspeak6-client ]; home.packages = with pkgs; [ teamspeak3 teamspeak6-client ];
}; };
} }

View file

@ -13,7 +13,7 @@ in
organization = mkOption { organization = mkOption {
type = types.attrsOf (types.submodule ({ name, ... }: { type = types.attrsOf (types.submodule ({ name, ... }: {
options = options =
let let
org = name; org = name;
in in
@ -23,11 +23,11 @@ in
default = false; default = false;
example = "true"; example = "true";
description = '' description = ''
True sets the org as default org for the instance. Only one org can be default org. True sets the '${org}' org as default org for the instance. Only one org can be default org.
Nothing happens if you set it to false until you set another org as default org. Nothing happens if you set it to false until you set another org as default org.
''; '';
}; };
project = mkOption { project = mkOption {
default = {}; default = {};
type = types.attrsOf (types.submodule { type = types.attrsOf (types.submodule {
@ -46,7 +46,7 @@ in
default = null; default = null;
example = "enforceProjectResourceOwnerPolicy"; example = "enforceProjectResourceOwnerPolicy";
description = '' description = ''
Defines from where the private labeling should be triggered, Defines from where the private labeling should be triggered,
supported values: supported values:
- unspecified - unspecified
@ -54,7 +54,7 @@ in
- allowLoginUserResourceOwnerPolicy - allowLoginUserResourceOwnerPolicy
''; '';
}; };
projectRoleAssertion = mkOption { projectRoleAssertion = mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
@ -63,7 +63,7 @@ in
Describes if roles of user should be added in token. Describes if roles of user should be added in token.
''; '';
}; };
projectRoleCheck = mkOption { projectRoleCheck = mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
@ -72,11 +72,11 @@ in
ZITADEL checks if the user has at least one on this project. ZITADEL checks if the user has at least one on this project.
''; '';
}; };
role = mkOption { role = mkOption {
default = {}; default = {};
type = types.attrsOf (types.submodule ({ name, ... }: { type = types.attrsOf (types.submodule ({ name, ... }: {
options = options =
let let
roleName = name; roleName = name;
in in
@ -101,12 +101,12 @@ in
}; };
})); }));
}; };
assign = mkOption { assign = mkOption {
default = {}; default = {};
type = types.attrsOf (types.listOf types.str); type = types.attrsOf (types.listOf types.str);
}; };
application = mkOption { application = mkOption {
default = {}; default = {};
type = types.attrsOf (types.submodule { type = types.attrsOf (types.submodule {
@ -141,8 +141,8 @@ in
''; '';
}; };
exportMap = exportMap =
let let
strOpt = mkOption { type = types.nullOr types.str; default = null; }; strOpt = mkOption { type = types.nullOr types.str; default = null; };
in in
mkOption { mkOption {
@ -164,11 +164,11 @@ in
}; };
}); });
}; };
user = mkOption { user = mkOption {
default = {}; default = {};
type = types.attrsOf (types.submodule ({ name, ... }: { type = types.attrsOf (types.submodule ({ name, ... }: {
options = options =
let let
username = name; username = name;
in in
@ -226,7 +226,7 @@ in
}; };
})); }));
}; };
action = mkOption { action = mkOption {
default = {}; default = {};
type = types.attrsOf (types.submodule ({ name, ... }: { type = types.attrsOf (types.submodule ({ name, ... }: {
@ -263,7 +263,7 @@ in
}; };
})); }));
}; };
triggers = mkOption { triggers = mkOption {
default = []; default = [];
type = types.listOf (types.submodule { type = types.listOf (types.submodule {
@ -321,26 +321,26 @@ in
accessTokenType = mapEnum "OIDC_TOKEN_TYPE" value; accessTokenType = mapEnum "OIDC_TOKEN_TYPE" value;
}."${type}" or value); }."${type}" or value);
toResource = name: value: nameValuePair toResource = name: value: nameValuePair
(toSnakeCase name) (toSnakeCase name)
(lib.mapAttrs' (k: v: nameValuePair (toSnakeCase k) (mapValue k v)) value); (lib.mapAttrs' (k: v: nameValuePair (toSnakeCase k) (mapValue k v)) value);
withRef = type: name: attrs: attrs // (mapRef type name); withRef = type: name: attrs: attrs // (mapRef type name);
select = keys: callback: set: select = keys: callback: set:
if (length keys) == 0 then if (length keys) == 0 then
mapAttrs' callback set mapAttrs' callback set
else let key = head keys; in else let key = head keys; in
concatMapAttrs (k: v: select (drop 1 keys) (callback k) (v.${key} or {})) set concatMapAttrs (k: v: select (drop 1 keys) (callback k) (v.${key} or {})) set
; ;
append = attrList: set: set // (listToAttrs attrList); append = attrList: set: set // (listToAttrs attrList);
forEach = src: key: set: forEach = src: key: set:
let let
_key = concatMapStringsSep "_" (k: "\${item.${k}}") key; _key = concatMapStringsSep "_" (k: "\${item.${k}}") key;
in in
{ {
forEach = "{ for item in ${src} : \"${_key}\" => item }"; forEach = "{ for item in ${src} : \"${_key}\" => item }";
} }
// set; // set;
@ -376,18 +376,18 @@ in
} }
] ]) ] ])
"; ";
orgs = cfg.organization |> mapAttrs (org: _: lib.tfRef "resource.zitadel_org.${org}.id"); orgs = cfg.organization |> mapAttrs (org: _: lib.tfRef "resource.zitadel_org.${org}.id");
}; };
resource = { resource = {
# Organizations # Organizations
zitadel_org = cfg.organization |> select [] (name: { isDefault, ... }: zitadel_org = cfg.organization |> select [] (name: { isDefault, ... }:
{ inherit name isDefault; } { inherit name isDefault; }
|> toResource name |> toResource name
); );
# Projects per organization # Projects per organization
zitadel_project = cfg.organization |> select [ "project" ] (org: name: { hasProjectCheck, privateLabelingSetting, projectRoleAssertion, projectRoleCheck, ... }: zitadel_project = cfg.organization |> select [ "project" ] (org: name: { hasProjectCheck, privateLabelingSetting, projectRoleAssertion, projectRoleCheck, ... }:
{ {
inherit name hasProjectCheck privateLabelingSetting projectRoleAssertion projectRoleCheck; inherit name hasProjectCheck privateLabelingSetting projectRoleAssertion projectRoleCheck;
} }
@ -396,7 +396,7 @@ in
); );
# Each OIDC app per project # Each OIDC app per project
zitadel_application_oidc = cfg.organization |> select [ "project" "application" ] (org: project: name: { redirectUris, grantTypes, responseTypes, ...}: zitadel_application_oidc = cfg.organization |> select [ "project" "application" ] (org: project: name: { redirectUris, grantTypes, responseTypes, ...}:
{ {
inherit name redirectUris grantTypes responseTypes; inherit name redirectUris grantTypes responseTypes;
@ -404,41 +404,41 @@ in
idTokenRoleAssertion = true; idTokenRoleAssertion = true;
accessTokenType = "JWT"; accessTokenType = "JWT";
} }
|> withRef "org" org |> withRef "org" org
|> withRef "project" "${org}_${project}" |> withRef "project" "${org}_${project}"
|> toResource "${org}_${project}_${name}" |> toResource "${org}_${project}_${name}"
); );
# Each project role # Each project role
zitadel_project_role = cfg.organization |> select [ "project" "role" ] (org: project: name: value: zitadel_project_role = cfg.organization |> select [ "project" "role" ] (org: project: name: value:
{ inherit (value) displayName group; roleKey = name; } { inherit (value) displayName group; roleKey = name; }
|> withRef "org" org |> withRef "org" org
|> withRef "project" "${org}_${project}" |> withRef "project" "${org}_${project}"
|> toResource "${org}_${project}_${name}" |> toResource "${org}_${project}_${name}"
); );
# Each project role assignment # Each project role assignment
zitadel_user_grant = cfg.organization |> select [ "project" "assign" ] (org: project: user: roles: zitadel_user_grant = cfg.organization |> select [ "project" "assign" ] (org: project: user: roles:
{ roleKeys = roles; } { roleKeys = roles; }
|> withRef "org" org |> withRef "org" org
|> withRef "project" "${org}_${project}" |> withRef "project" "${org}_${project}"
|> withRef "user" "${org}_${user}" |> withRef "user" "${org}_${user}"
|> toResource "${org}_${project}_${user}" |> toResource "${org}_${project}_${user}"
); );
# Users # Users
zitadel_human_user = zitadel_human_user =
cfg.organization cfg.organization
|> select [ "user" ] (org: name: { email, userName, firstName, lastName, ... }: |> select [ "user" ] (org: name: { email, userName, firstName, lastName, ... }:
{ {
inherit email userName firstName lastName; inherit email userName firstName lastName;
isEmailVerified = true; isEmailVerified = true;
} }
|> withRef "org" org |> withRef "org" org
|> toResource "${org}_${name}" |> toResource "${org}_${name}"
) )
|> append |> append
[ [
(forEach "local.extra_users" [ "org" "name" ] { (forEach "local.extra_users" [ "org" "name" ] {
orgId = lib.tfRef "local.orgs[each.value.org]"; orgId = lib.tfRef "local.orgs[each.value.org]";
@ -446,7 +446,7 @@ in
email = lib.tfRef "each.value.email"; email = lib.tfRef "each.value.email";
firstName = lib.tfRef "each.value.firstName"; firstName = lib.tfRef "each.value.firstName";
lastName = lib.tfRef "each.value.lastName"; lastName = lib.tfRef "each.value.lastName";
isEmailVerified = true; isEmailVerified = true;
} }
|> toResource "extraUsers") |> toResource "extraUsers")
@ -454,20 +454,20 @@ in
; ;
# Global user roles # Global user roles
zitadel_instance_member = zitadel_instance_member =
cfg.organization cfg.organization
|> filterAttrsRecursive (n: v: !(v ? "instanceRoles" && (length v.instanceRoles) == 0)) |> filterAttrsRecursive (n: v: !(v ? "instanceRoles" && (length v.instanceRoles) == 0))
|> select [ "user" ] (org: name: { instanceRoles, ... }: |> select [ "user" ] (org: name: { instanceRoles, ... }:
{ roles = instanceRoles; } { roles = instanceRoles; }
|> withRef "user" "${org}_${name}" |> withRef "user" "${org}_${name}"
|> toResource "${org}_${name}" |> toResource "${org}_${name}"
); );
# Organazation specific roles # Organazation specific roles
zitadel_org_member = zitadel_org_member =
cfg.organization cfg.organization
|> filterAttrsRecursive (n: v: !(v ? "roles" && (length v.roles) == 0)) |> filterAttrsRecursive (n: v: !(v ? "roles" && (length v.roles) == 0))
|> select [ "user" ] (org: name: { roles, ... }: |> select [ "user" ] (org: name: { roles, ... }:
{ inherit roles; } { inherit roles; }
|> withRef "org" org |> withRef "org" org
|> withRef "user" "${org}_${name}" |> withRef "user" "${org}_${name}"
@ -475,9 +475,9 @@ in
); );
# Organazation's actions # Organazation's actions
zitadel_action = cfg.organization |> select [ "action" ] (org: name: { timeout, allowedToFail, script, ...}: zitadel_action = cfg.organization |> select [ "action" ] (org: name: { timeout, allowedToFail, script, ...}:
{ {
inherit allowedToFail name; inherit allowedToFail name;
timeout = "${toString timeout}s"; timeout = "${toString timeout}s";
script = "const ${name} = ${script}"; script = "const ${name} = ${script}";
} }
@ -486,20 +486,20 @@ in
); );
# Organazation's action assignments # Organazation's action assignments
zitadel_trigger_actions = zitadel_trigger_actions =
cfg.organization cfg.organization
|> concatMapAttrs (org: { triggers, ... }: |> concatMapAttrs (org: { triggers, ... }:
triggers triggers
|> imap0 (i: { flowType, triggerType, actions, ... }: (let name = "trigger_${toString i}"; in |> imap0 (i: { flowType, triggerType, actions, ... }: (let name = "trigger_${toString i}"; in
{ {
inherit flowType triggerType; inherit flowType triggerType;
actionIds = actionIds =
actions actions
|> map (action: (lib.tfRef "zitadel_action.${org}_${toSnakeCase action}.id")); |> map (action: (lib.tfRef "zitadel_action.${org}_${toSnakeCase action}.id"));
} }
|> withRef "org" org |> withRef "org" org
|> toResource "${org}_${name}" |> toResource "${org}_${name}"
)) ))
|> listToAttrs |> listToAttrs
); );
@ -516,7 +516,7 @@ in
}; };
# Client credentials per app # Client credentials per app
local_sensitive_file = cfg.organization |> select [ "project" "application" ] (org: project: name: { exportMap, ... }: local_sensitive_file = cfg.organization |> select [ "project" "application" ] (org: project: name: { exportMap, ... }:
nameValuePair "${org}_${project}_${name}" { nameValuePair "${org}_${project}_${name}" {
content = '' content = ''
${if exportMap.client_id != null then exportMap.client_id else "CLIENT_ID"}=${lib.tfRef "resource.zitadel_application_oidc.${org}_${project}_${name}.client_id"} ${if exportMap.client_id != null then exportMap.client_id else "CLIENT_ID"}=${lib.tfRef "resource.zitadel_application_oidc.${org}_${project}_${name}.client_id"}
@ -530,7 +530,7 @@ in
}) })
]; ];
}; };
in in
mkIf cfg.enable { mkIf cfg.enable {
${namespace}.services.persistance.postgresql.enable = true; ${namespace}.services.persistance.postgresql.enable = true;
@ -548,7 +548,7 @@ in
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
wants = [ "zitadel.service" ]; wants = [ "zitadel.service" ];
script = '' script = ''
#!/usr/bin/env bash #!/usr/bin/env bash
@ -628,7 +628,7 @@ in
Org = { Org = {
Name = "kruining"; Name = "kruining";
Human = { Human = {
UserName = "chris"; UserName = "chris";
FirstName = "Chris"; FirstName = "Chris";
@ -639,7 +639,7 @@ in
}; };
Password = "KaasIsAwesome1!"; Password = "KaasIsAwesome1!";
}; };
Machine = { Machine = {
Machine = { Machine = {
Username = "terraform-service-user"; Username = "terraform-service-user";
@ -648,7 +648,7 @@ in
MachineKey = { ExpirationDate = "2026-01-01T00:00:00Z"; Type = 1; }; MachineKey = { ExpirationDate = "2026-01-01T00:00:00Z"; Type = 1; };
# Pat = { ExpirationDate = "2026-01-01T00:00:00Z"; }; # Pat = { ExpirationDate = "2026-01-01T00:00:00Z"; };
}; };
# LoginClient.Machine = { # LoginClient.Machine = {
# Username = "terraform-service-user"; # Username = "terraform-service-user";
# Name = "Terraform"; # Name = "Terraform";
@ -689,7 +689,7 @@ in
''; '';
}; };
}; };
networking.firewall.allowedTCPPorts = [ 80 443 ]; networking.firewall.allowedTCPPorts = [ 80 443 ];
# Secrets # Secrets

View file

@ -1,5 +1,10 @@
{ config, lib, pkgs, namespace, ... }: {
let config,
lib,
pkgs,
namespace,
...
}: let
inherit (builtins) toString toJSON; inherit (builtins) toString toJSON;
inherit (lib) mkIf mkEnableOption; inherit (lib) mkIf mkEnableOption;
@ -10,8 +15,7 @@ let
port = 4001; port = 4001;
database = "synapse"; database = "synapse";
in in {
{
options.${namespace}.services.communication.matrix = { options.${namespace}.services.communication.matrix = {
enable = mkEnableOption "Matrix server (Synapse)"; enable = mkEnableOption "Matrix server (Synapse)";
}; };
@ -22,13 +26,13 @@ in
# virtualisation.podman.enable = true; # virtualisation.podman.enable = true;
}; };
networking.firewall.allowedTCPPorts = [ 4001 ]; networking.firewall.allowedTCPPorts = [4001];
services = { services = {
matrix-synapse = { matrix-synapse = {
enable = true; enable = true;
extras = [ "oidc" ]; extras = ["oidc"];
extraConfigFiles = [ extraConfigFiles = [
config.sops.templates."synapse-oidc.yaml".path config.sops.templates."synapse-oidc.yaml".path
@ -52,7 +56,7 @@ in
backchannel_logout_enabled = true; backchannel_logout_enabled = true;
sso = { sso = {
client_whitelist = [ "http://[::1]:9092" ]; client_whitelist = ["http://[::1]:9092"];
update_profile_information = true; update_profile_information = true;
}; };
@ -75,7 +79,7 @@ in
resources = [ resources = [
{ {
names = [ "client" "federation" "openid" "metrics" "media" "health" ]; names = ["client" "federation" "openid" "metrics" "media" "health"];
compress = true; compress = true;
} }
]; ];
@ -132,7 +136,7 @@ in
postgresql = { postgresql = {
enable = true; enable = true;
ensureDatabases = [ database ]; ensureDatabases = [database];
ensureUsers = [ ensureUsers = [
{ {
name = database; name = database;
@ -192,7 +196,7 @@ in
localpart_template: "{{ user.preferred_username }}" localpart_template: "{{ user.preferred_username }}"
display_name_template: "{{ user.name }}" display_name_template: "{{ user.name }}"
''; '';
restartUnits = [ "matrix-synapse.service" ]; restartUnits = ["matrix-synapse.service"];
}; };
}; };
}; };

View file

@ -1,12 +1,16 @@
{ config, lib, pkgs, namespace, ... }: {
let config,
lib,
pkgs,
namespace,
...
}: let
inherit (builtins) toString; inherit (builtins) toString;
inherit (lib) mkIf mkEnableOption mkOption; inherit (lib) mkIf mkEnableOption mkOption;
cfg = config.${namespace}.services.development.forgejo; cfg = config.${namespace}.services.development.forgejo;
domain = "git.amarth.cloud"; domain = "git.amarth.cloud";
in in {
{
options.${namespace}.services.development.forgejo = { options.${namespace}.services.development.forgejo = {
enable = mkEnableOption "Forgejo"; enable = mkEnableOption "Forgejo";
@ -26,7 +30,7 @@ in
virtualisation.podman.enable = true; virtualisation.podman.enable = true;
}; };
environment.systemPackages = with pkgs; [ forgejo ]; environment.systemPackages = with pkgs; [forgejo];
services = { services = {
forgejo = { forgejo = {
@ -141,7 +145,7 @@ in
}; };
}; };
openssh.settings.AllowUsers = [ "forgejo" ]; openssh.settings.AllowUsers = ["forgejo"];
gitea-actions-runner = { gitea-actions-runner = {
package = pkgs.forgejo-runner; package = pkgs.forgejo-runner;
@ -184,14 +188,14 @@ in
"forgejo/action_runner_token" = { "forgejo/action_runner_token" = {
owner = "gitea-runner"; owner = "gitea-runner";
group = "gitea-runner"; group = "gitea-runner";
restartUnits = [ "gitea-runner-default.service" ]; restartUnits = ["gitea-runner-default.service"];
}; };
"forgejo/email" = { "forgejo/email" = {
owner = "forgejo"; owner = "forgejo";
group = "forgejo"; group = "forgejo";
key = "email/chris_kruining_eu"; key = "email/chris_kruining_eu";
restartUnits = [ "forgejo.service" ]; restartUnits = ["forgejo.service"];
}; };
}; };
}; };

View file

@ -0,0 +1,51 @@
{
config,
lib,
namespace,
inputs,
system,
...
}: let
inherit (lib) mkIf mkEnableOption;
cfg = config.${namespace}.services.media.mydia;
in {
imports = [
inputs.mydia.nixosModules.default
];
options.${namespace}.services.media.mydia = {
enable = mkEnableOption "Enable Mydia";
};
config = mkIf cfg.enable {
services.mydia = {
enable = true;
package = inputs.mydia.packages.${system}.default;
port = 2010;
openFirewall = true;
secretKeyBaseFile = config.sops.secrets."mydia/secret_key_base".path;
guardianSecretKeyFile = config.sops.secrets."mydia/guardian_secret".path;
oidc = {
enable = true;
issuer = "https://auth.kruining.eu";
clientIdFile = config.sops.secrets."mydia/oidc_id".path;
clientSecretFile = config.sops.secrets."mydia/oidc_secret".path;
scopes = ["openid" "profile" "email"];
};
};
sops.secrets =
["secret_key_base" "guardian_secret" "oidc_id" "oidc_secret"]
|> lib.map (name:
lib.nameValuePair "mydia/${name}" {
owner = config.services.mydia.user;
group = config.services.mydia.group;
restartUnits = ["mydia.service"];
})
|> lib.listToAttrs;
};
}

View file

@ -1,14 +1,20 @@
{ pkgs, config, lib, namespace, inputs, system, ... }: {
let pkgs,
config,
lib,
namespace,
inputs,
system,
...
}: let
inherit (builtins) toString; inherit (builtins) toString;
inherit (lib) mkIf mkEnableOption mkOption types; inherit (lib) mkIf mkEnableOption mkOption types;
cfg = config.${namespace}.services.media.servarr; cfg = config.${namespace}.services.media.servarr;
in in {
{
options.${namespace}.services.media = { options.${namespace}.services.media = {
servarr = mkOption { servarr = mkOption {
type = types.attrsOf (types.submodule ({ name, ... }: { type = types.attrsOf (types.submodule ({name, ...}: {
options = { options = {
enable = mkEnableOption "Enable ${name}"; enable = mkEnableOption "Enable ${name}";
debug = mkEnableOption "Use tofu plan instead of tofu apply for ${name} "; debug = mkEnableOption "Use tofu plan instead of tofu apply for ${name} ";
@ -28,9 +34,13 @@ in
}; };
config = { config = {
services = services =
cfg cfg
|> lib.mapAttrsToList (service: { enable, port, ... }: (mkIf enable { |> lib.mapAttrsToList (service: {
enable,
port,
...
}: (mkIf enable {
"${service}" = { "${service}" = {
enable = true; enable = true;
openFirewall = true; openFirewall = true;
@ -58,31 +68,44 @@ in
}; };
})) }))
|> lib.mergeAttrsList |> lib.mergeAttrsList
|> (set: set // { |> (set:
postgresql = { set
ensureDatabases = cfg |> lib.attrNames; // {
ensureUsers = cfg |> lib.attrNames |> lib.map (service: { postgresql = {
name = service; ensureDatabases = cfg |> lib.attrNames;
ensureDBOwnership = true; ensureUsers =
}); cfg
}; |> lib.attrNames
}) |> lib.map (service: {
; name = service;
ensureDBOwnership = true;
});
};
});
systemd = systemd =
cfg cfg
|> lib.mapAttrsToList (service: { enable, debug, port, rootFolders, ... }: (mkIf enable { |> lib.mapAttrsToList (service: {
enable,
debug,
port,
rootFolders,
...
}: (mkIf enable {
tmpfiles.rules = [ tmpfiles.rules = [
"d /var/lib/${service}ApplyTerraform 0755 ${service} ${service} -" "d /var/lib/${service}ApplyTerraform 0755 ${service} ${service} -"
]; ];
services."${service}ApplyTerraform" = services."${service}ApplyTerraform" = let
let
terraformConfiguration = inputs.terranix.lib.terranixConfiguration { terraformConfiguration = inputs.terranix.lib.terranixConfiguration {
inherit system; inherit system;
modules = [ modules = [
({ config, lib, ... }: { ({
config,
lib,
...
}: {
config = { config = {
variable = { variable = {
api_key = { api_key = {
@ -102,23 +125,21 @@ in
}; };
resource = { resource = {
"${service}_root_folder" = "${service}_root_folder" =
rootFolders rootFolders
|> lib.imap (i: f: lib.nameValuePair "local${toString i}" { path = f; }) |> lib.imap (i: f: lib.nameValuePair "local${toString i}" {path = f;})
|> lib.listToAttrs |> lib.listToAttrs;
;
}; };
}; };
}) })
]; ];
}; };
in in {
{
description = "${service} terraform apply"; description = "${service} terraform apply";
wantedBy = [ "multi-user.target" ]; wantedBy = ["multi-user.target"];
wants = [ "${service}.service" ]; wants = ["${service}.service"];
script = '' script = ''
#!/usr/bin/env bash #!/usr/bin/env bash
@ -141,7 +162,11 @@ in
# Run the infrastructure code # Run the infrastructure code
${lib.getExe pkgs.opentofu} \ ${lib.getExe pkgs.opentofu} \
${if debug then "plan" else "apply -auto-approve"} \ ${
if debug
then "plan"
else "apply -auto-approve"
} \
-var-file='${config.sops.templates."${service}/config.tfvars".path}' -var-file='${config.sops.templates."${service}/config.tfvars".path}'
''; '';
@ -158,31 +183,29 @@ in
}; };
}; };
})) }))
|> lib.mergeAttrsList |> lib.mergeAttrsList;
;
users.users = users.users =
cfg cfg
|> lib.mapAttrsToList (service: { enable, ... }: (mkIf enable { |> lib.mapAttrsToList (service: {enable, ...}: (mkIf enable {
"${service}".extraGroups = [ "media" ]; "${service}".extraGroups = ["media"];
})) }))
|> lib.mergeAttrsList |> lib.mergeAttrsList;
;
sops = sops =
cfg cfg
|> lib.mapAttrsToList (service: { enable, ... }: (mkIf enable { |> lib.mapAttrsToList (service: {enable, ...}: (mkIf enable {
secrets."${service}/apikey" = { secrets."${service}/apikey" = {
owner = service; owner = service;
group = service; group = service;
restartUnits = [ "${service}.service" ]; restartUnits = ["${service}.service"];
}; };
templates = { templates = {
"${service}/config.env" = { "${service}/config.env" = {
owner = service; owner = service;
group = service; group = service;
restartUnits = [ "${service}.service" ]; restartUnits = ["${service}.service"];
content = '' content = ''
${lib.toUpper service}__AUTH__APIKEY="${config.sops.placeholder."${service}/apikey"}" ${lib.toUpper service}__AUTH__APIKEY="${config.sops.placeholder."${service}/apikey"}"
''; '';
@ -191,18 +214,16 @@ in
"${service}/config.tfvars" = { "${service}/config.tfvars" = {
owner = service; owner = service;
group = service; group = service;
restartUnits = [ "${service}.service" ]; restartUnits = ["${service}.service"];
content = '' content = ''
api_key = "${config.sops.placeholder."${service}/apikey"}" api_key = "${config.sops.placeholder."${service}/apikey"}"
''; '';
}; };
}; };
})) }))
|> lib.mergeAttrsList |> lib.mergeAttrsList;
;
}; };
# cfg # cfg
# |> lib.mapAttrsToList (service: { enable, debug, port, rootFolders, ... }: (mkIf enable { # |> lib.mapAttrsToList (service: { enable, debug, port, rootFolders, ... }: (mkIf enable {

View file

@ -1,2 +1,5 @@
{ ... }: {...}: {
{} config = {
programs.bash.enableCompletion = true;
};
}

View file

@ -1,101 +0,0 @@
{
lib,
fetchFromGitHub,
pkgs,
stdenv,
...
}: let
erlang = pkgs.beam.packagesWith pkgs.beam.interpreters.erlang;
erlangSystem =
{
aarch64-darwin = "macos-arm64";
aarch64-linux = "linux-arm64";
armv7l-linux = "linux-armv7";
x86_64-darwin = "macos-x64";
x86_64-linux = "linux-x64";
}
.${
stdenv.hostPlatform.system
};
version = "v0.6.0";
pname = "mydia";
src = fetchFromGitHub {
owner = "getmydia";
repo = "mydia";
rev = version;
hash = "sha256-JGT52ulnqcx8o+3e0l50TLAwLIWXEI8nwFGUsA95vH0=";
};
mixFodDeps = erlang.fetchMixDeps {
inherit version src;
pname = "mix-deps-${pname}-${version}";
hash = "sha256-19q56IZe8YjuUBXirFGgmBsewJ0cmdOoO1yfiMaWGWk=";
};
npmFodDeps = pkgs.fetchNpmDeps {
src = "${src}/assets";
hash = "sha256-0cz75pxhxvzo1RogsV8gTP6GrgLIboWQXcKpq42JZ6o=";
};
in
erlang.mixRelease {
inherit pname version src mixFodDeps;
enableDebugInfo = true;
nativeBuildInputs = with pkgs; [
which
ffmpeg_6
fdk_aac
sqlite
postgresql
tailwindcss_4
esbuild
pkg-config
];
env = {
EXQLITE_USE_SYSTEM = "1";
EXQLITE_SYSTEM_CFLAGS = "-I${pkgs.sqlite.dev}/include";
EXQLITE_SYSTEM_LDFLAGS = "-L${pkgs.sqlite.out}/lib -lsqlite3";
DATABASE_TYPE = "postgres";
};
preInstall = ''
ln -s ${lib.getExe pkgs.tailwindcss_4} _build/tailwind-${erlangSystem}
ln -s ${lib.getExe pkgs.esbuild} _build/esbuild-${erlangSystem}
ln -s ${npmFodDeps} assets/node_modules
mix do \
deps.loadpaths --no-deps-check, \
tailwind default --minify + esbuild default --minify + phx.digest, \
assets.deploy
'';
meta = {
description = "Your personal media companion, built with Phoenix LiveView";
longDescription = ''
A modern, self-hosted media management platform for tracking, organizing, and monitoring your media library.
# ✨ Features
- 📺 Unified Media Management Track both movies and TV shows with rich metadata from TMDB/TVDB
- 🤖 Automated Downloads Background search and download with quality profiles and smart release ranking
- Download Clients qBittorrent, Transmission, SABnzbd, and NZBGet support
- 🔎 Indexer Integration Search via Prowlarr and Jackett for finding releases
- 📚 Built-in Indexer Library Native Cardigann support (experimental, limited testing)
- 👥 Multi-User System Built-in admin/guest roles with request approval workflow
- 🔐 SSO Support Local authentication plus OIDC/OpenID Connect integration
- 🔔 Release Calendar Track upcoming releases and monitor episodes
- 🎨 Modern Real-Time UI Phoenix LiveView with instant updates and responsive design
'';
homepage = "https://github.com/getmydia/mydia";
changelog = "https://github.com/getmydia/mydia/releases";
license = lib.licenses.agpl3Only;
maintainers = [];
platforms = lib.platforms.all;
mainProgram = pname;
};
}

View file

@ -15,6 +15,7 @@ mkShell {
alejandra alejandra
nil nil
nixd nixd
openssl
inputs.clan-core.packages.${stdenv.hostPlatform.system}.clan-cli inputs.clan-core.packages.${stdenv.hostPlatform.system}.clan-cli
]; ];
} }

View file

@ -1,5 +1,4 @@
{ ... }: {...}: {
{
imports = [ imports = [
./disks.nix ./disks.nix
./hardware.nix ./hardware.nix
@ -8,7 +7,10 @@
networking = { networking = {
interfaces.enp2s0 = { interfaces.enp2s0 = {
ipv6.addresses = [ ipv6.addresses = [
{ address = "2a0d:6e00:1dc9:0::dead:beef"; prefixLength = 64; } {
address = "2a0d:6e00:1dc9:0::dead:beef";
prefixLength = 64;
}
]; ];
useDHCP = true; useDHCP = true;
@ -39,7 +41,7 @@
sneeuwvlok = { sneeuwvlok = {
services = { services = {
backup.borg.enable = true; backup.borg.enable = true;
authentication.zitadel = { authentication.zitadel = {
enable = true; enable = true;
@ -51,8 +53,8 @@
firstName = "Chris"; firstName = "Chris";
lastName = "Kruining"; lastName = "Kruining";
roles = [ "ORG_OWNER" ]; roles = ["ORG_OWNER"];
instanceRoles = [ "IAM_OWNER" ]; instanceRoles = ["IAM_OWNER"];
}; };
kaas = { kaas = {
@ -78,27 +80,27 @@
}; };
assign = { assign = {
chris = [ "jellyfin" "jellyfin_admin" ]; chris = ["jellyfin" "jellyfin_admin"];
kaas = [ "jellyfin" ]; kaas = ["jellyfin"];
}; };
application = { application = {
jellyfin = { jellyfin = {
redirectUris = [ "https://jellyfin.kruining.eu/sso/OID/redirect/zitadel" ]; redirectUris = ["https://jellyfin.kruining.eu/sso/OID/redirect/zitadel"];
grantTypes = [ "authorizationCode" ]; grantTypes = ["authorizationCode"];
responseTypes = [ "code" ]; responseTypes = ["code"];
}; };
forgejo = { forgejo = {
redirectUris = [ "https://git.amarth.cloud/user/oauth2/zitadel/callback" ]; redirectUris = ["https://git.amarth.cloud/user/oauth2/zitadel/callback"];
grantTypes = [ "authorizationCode" ]; grantTypes = ["authorizationCode"];
responseTypes = [ "code" ]; responseTypes = ["code"];
}; };
vaultwarden = { vaultwarden = {
redirectUris = [ "https://vault.kruining.eu/identity/connect/oidc-signin" ]; redirectUris = ["https://vault.kruining.eu/identity/connect/oidc-signin"];
grantTypes = [ "authorizationCode" ]; grantTypes = ["authorizationCode"];
responseTypes = [ "code" ]; responseTypes = ["code"];
exportMap = { exportMap = {
client_id = "SSO_CLIENT_ID"; client_id = "SSO_CLIENT_ID";
client_secret = "SSO_CLIENT_SECRET"; client_secret = "SSO_CLIENT_SECRET";
@ -106,9 +108,15 @@
}; };
matrix = { matrix = {
redirectUris = [ "https://matrix.kruining.eu/_synapse/client/oidc/callback" ]; redirectUris = ["https://matrix.kruining.eu/_synapse/client/oidc/callback"];
grantTypes = [ "authorizationCode" ]; grantTypes = ["authorizationCode"];
responseTypes = [ "code" ]; responseTypes = ["code"];
};
mydia = {
redirectUris = ["http://localhost:2010/auth/oidc/callback"];
grantTypes = ["authorizationCode"];
responseTypes = ["code"];
}; };
}; };
}; };
@ -121,9 +129,9 @@
if (ctx.v1.user.grants == undefined || ctx.v1.user.grants.count == 0) { if (ctx.v1.user.grants == undefined || ctx.v1.user.grants.count == 0) {
return; return;
} }
const roles = ctx.v1.user.grants.grants.flatMap(({ roles, projectId }) => roles.map(role => projectId + ':' + role)); const roles = ctx.v1.user.grants.grants.flatMap(({ roles, projectId }) => roles.map(role => projectId + ':' + role));
api.v1.claims.setClaim('nix:zitadel:custom', JSON.stringify({ roles })); api.v1.claims.setClaim('nix:zitadel:custom', JSON.stringify({ roles }));
}; };
''; '';
@ -131,8 +139,16 @@
}; };
triggers = [ triggers = [
{ flowType = "customiseToken"; triggerType = "preUserinfoCreation"; actions = [ "flattenRoles" ]; } {
{ flowType = "customiseToken"; triggerType = "preAccessTokenCreation"; actions = [ "flattenRoles" ]; } flowType = "customiseToken";
triggerType = "preUserinfoCreation";
actions = ["flattenRoles"];
}
{
flowType = "customiseToken";
triggerType = "preAccessTokenCreation";
actions = ["flattenRoles"];
}
]; ];
}; };
}; };
@ -146,6 +162,7 @@
media.enable = true; media.enable = true;
media.homer.enable = true; media.homer.enable = true;
media.mydia.enable = true;
media.nfs.enable = true; media.nfs.enable = true;
media.servarr = { media.servarr = {
# radarr = { # radarr = {
@ -190,7 +207,7 @@
database = { database = {
# type = "sqlite"; # type = "sqlite";
# file = "/var/lib/vaultwarden/state.db"; # file = "/var/lib/vaultwarden/state.db";
type = "postgresql"; type = "postgresql";
host = "localhost"; host = "localhost";
port = 5432; port = 5432;