Compare commits
39 commits
main
...
experiment
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
64bc77a73e | ||
|
|
6b3389c4b1 | ||
|
|
59e8ca812c | ||
|
|
cf9dcf2568 | ||
|
|
5c1e6807b6 | ||
|
|
d60d4badf3 | ||
|
|
a8a639db6e | ||
| 4dfcd5cca8 | |||
| 545b2ad871 | |||
| 4f2ecc60b4 | |||
| 8c6e72786c | |||
| 772db61b9e | |||
| e941c305b8 | |||
| 11e74b4f29 | |||
|
|
2ffece26f2 | ||
|
|
cc86b0a815 | ||
| cb30a0ba8b | |||
| ad25722249 | |||
| 6b2ec0565a | |||
| 163f4a022e | |||
| e21de6d1da | |||
| 0229b4f816 | |||
| 781d1f3c8a | |||
| db5e5974ab | |||
| b349025232 | |||
| bd540029a7 | |||
| 955b1c6ba4 | |||
| a4500a2eb6 | |||
| 611f474961 | |||
| 10bbf99210 | |||
|
|
b37c5c0cbd | ||
|
|
2471562583 | ||
|
|
f59d282c12 | ||
|
|
20de142350 | ||
|
|
ba7c3392b9 | ||
|
|
97b63074f0 | ||
|
|
a7a1763fe0 | ||
| ac3dac322d | |||
| 59a1fbaf0f |
228 changed files with 5297 additions and 2462 deletions
|
|
@ -1,20 +0,0 @@
|
||||||
@_default: list
|
|
||||||
|
|
||||||
[doc('List machines')]
|
|
||||||
@list:
|
|
||||||
ls -1 ../systems/x86_64-linux/
|
|
||||||
|
|
||||||
[doc('Update target machine')]
|
|
||||||
[no-exit-message]
|
|
||||||
@update machine:
|
|
||||||
echo "Checking vars"
|
|
||||||
cd .. && just vars _check {{ machine }}
|
|
||||||
echo ""
|
|
||||||
just assert '-d "../systems/x86_64-linux/{{ machine }}"' "Machine {{ machine }} does not exist, must be one of: $(ls ../systems/x86_64-linux/ | sed ':a;N;$!ba;s/\n/, /g')"
|
|
||||||
nixos-rebuild switch -L --sudo --target-host {{ machine }} --flake ..#{{ machine }} --log-format internal-json -v |& nom --json
|
|
||||||
|
|
||||||
[doc('Check if target machine builds')]
|
|
||||||
[no-exit-message]
|
|
||||||
@check machine:
|
|
||||||
just assert '-d "../systems/x86_64-linux/{{ machine }}"' "Machine {{ machine }} does not exist, must be one of: $(ls ../systems/x86_64-linux/ | sed ':a;N;$!ba;s/\n/, /g')"
|
|
||||||
nix build ..#nixosConfigurations.{{ machine }}.config.system.build.toplevel
|
|
||||||
101
.just/users.just
101
.just/users.just
|
|
@ -1,101 +0,0 @@
|
||||||
set unstable := true
|
|
||||||
set quiet := true
|
|
||||||
|
|
||||||
_default:
|
|
||||||
just --list users
|
|
||||||
|
|
||||||
[doc('List available users')]
|
|
||||||
[script]
|
|
||||||
list:
|
|
||||||
cd .. && just vars get ulmo zitadel/users | jq -r -C '
|
|
||||||
import ".jq/table" as table;
|
|
||||||
import ".jq/format" as f;
|
|
||||||
|
|
||||||
fromjson
|
|
||||||
| to_entries
|
|
||||||
| sort_by(.key)
|
|
||||||
| map(
|
|
||||||
(.key|f::to_title) + ":\n"
|
|
||||||
+ table::create(
|
|
||||||
.value
|
|
||||||
| to_entries
|
|
||||||
| sort_by(.key)
|
|
||||||
| map({username:.key} + .value)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
| join("\n\n┄┄┄\n\n")
|
|
||||||
';
|
|
||||||
|
|
||||||
[doc('Add a new user')]
|
|
||||||
[script]
|
|
||||||
add:
|
|
||||||
exec 5>&1
|
|
||||||
|
|
||||||
pad () { [ "$#" -gt 1 ] && [ -n "$2" ] && printf "%$2.${2#-}s" "$1"; }
|
|
||||||
|
|
||||||
input() {
|
|
||||||
local label=$1
|
|
||||||
local value=$2
|
|
||||||
|
|
||||||
local res=$(gum input --header "$label" --value "$value")
|
|
||||||
echo -e "\e[2m$(pad "$label" -11)\e[0m$res" >&5
|
|
||||||
echo $res
|
|
||||||
}
|
|
||||||
|
|
||||||
data=`cd .. && just vars get ulmo zitadel/users | jq 'fromjson'`
|
|
||||||
|
|
||||||
# Gather inputs
|
|
||||||
org=`
|
|
||||||
jq -r 'to_entries | map(.key)[]' <<< "$data" \
|
|
||||||
| gum choose --header 'Which organisation to save to?' --select-if-one
|
|
||||||
`
|
|
||||||
username=`input 'user name' ''`
|
|
||||||
email=`input 'email' ''`
|
|
||||||
first_name=`input 'first name' ''`
|
|
||||||
last_name=`input 'last name' ''`
|
|
||||||
|
|
||||||
user_exists=`jq --arg 'org' "$org" --arg 'username' "$username" '.[$org][$username]? | . != null' <<< "$data"`
|
|
||||||
|
|
||||||
if [ "$user_exists" == "true" ]; then
|
|
||||||
gum confirm 'User already exists, overwrite it?' --padding="1 1" || exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
next=`
|
|
||||||
jq \
|
|
||||||
--arg 'org' "$org" \
|
|
||||||
--arg 'username' "$username" \
|
|
||||||
--arg 'email' "$email" \
|
|
||||||
--arg 'first_name' "$first_name" \
|
|
||||||
--arg 'last_name' "$last_name" \
|
|
||||||
--compact-output \
|
|
||||||
'.[$org] += { $username: { email: $email, firstName: $first_name, lastName: $last_name } }' \
|
|
||||||
<<< $data
|
|
||||||
`
|
|
||||||
|
|
||||||
gum spin --title "saving..." -- echo "$(cd .. && just vars set ulmo 'zitadel/users' "$next")"
|
|
||||||
|
|
||||||
[doc('Remove a new user')]
|
|
||||||
[script]
|
|
||||||
remove:
|
|
||||||
data=`cd .. && just vars get ulmo zitadel/users | jq fromjson`
|
|
||||||
|
|
||||||
# Gather inputs
|
|
||||||
org=`
|
|
||||||
jq -r 'to_entries | map(.key)[]' <<< "$data" \
|
|
||||||
| gum choose --header 'Which organisation?' --select-if-one
|
|
||||||
`
|
|
||||||
user=`
|
|
||||||
jq -r --arg org "$org" '.[$org] | to_entries | map(.key)[]' <<< "$data" \
|
|
||||||
| gum choose --header 'Which user?' --select-if-one
|
|
||||||
`
|
|
||||||
|
|
||||||
next=`
|
|
||||||
jq \
|
|
||||||
--arg 'org' "$org" \
|
|
||||||
--arg 'user' "$user" \
|
|
||||||
--compact-output \
|
|
||||||
'del(.[$org][$user])' \
|
|
||||||
<<< $data
|
|
||||||
`
|
|
||||||
|
|
||||||
gum spin --title "saving..." -- echo "$(cd .. && just vars set ulmo 'zitadel/users' "$next")"
|
|
||||||
|
|
@ -1,38 +1,39 @@
|
||||||
set unstable := true
|
set unstable := true
|
||||||
set quiet := true
|
set quiet := true
|
||||||
|
|
||||||
base_path := justfile_directory() + "/systems/x86_64-linux"
|
machine_base_path := justfile_directory() + "/machines"
|
||||||
|
secret_base_path := justfile_directory() + "/systems/x86_64-linux"
|
||||||
|
|
||||||
_default:
|
_default:
|
||||||
just --list vars
|
just --list vars
|
||||||
|
|
||||||
[doc('List all vars of {machine}')]
|
[doc('List all vars of {machine}')]
|
||||||
list machine:
|
list machine:
|
||||||
sops decrypt {{ base_path }}/{{ machine }}/secrets.yml
|
sops decrypt {{ secret_base_path }}/{{ machine }}/secrets.yml
|
||||||
|
|
||||||
[doc('Edit all vars of {machine} in your editor')]
|
[doc('Edit all vars of {machine} in your editor')]
|
||||||
edit machine:
|
edit machine:
|
||||||
sops edit {{ base_path }}/{{ machine }}/secrets.yml
|
sops edit {{ secret_base_path }}/{{ machine }}/secrets.yml
|
||||||
|
|
||||||
[doc('Set var {value} by {key} for {machine}')]
|
[doc('Set var {value} by {key} for {machine}')]
|
||||||
@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 {{ secret_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 {{ secret_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 }}"' -- {{ secret_base_path }}/{{ machine }}/secrets.yml > /dev/null
|
||||||
|
|
||||||
echo "Done"
|
echo "Done"
|
||||||
|
|
||||||
[doc('Get var by {key} from {machine}')]
|
[doc('Get var by {key} from {machine}')]
|
||||||
get machine key:
|
get machine key:
|
||||||
sops decrypt {{ base_path }}/{{ machine }}/secrets.yml | yq ".$(echo "{{ key }}" | sed -E 's/\//./g') // \"\""
|
sops decrypt {{ secret_base_path }}/{{ machine }}/secrets.yml | yq ".$(echo "{{ key }}" | sed -E 's/\//./g') // \"\""
|
||||||
|
|
||||||
[doc('Remove var by {key} for {machine}')]
|
[doc('Remove var by {key} for {machine}')]
|
||||||
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 {{ secret_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 {{ secret_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 }}"' -- {{ secret_base_path }}/{{ machine }}/secrets.yml > /dev/null
|
||||||
|
|
||||||
echo "Done"
|
echo "Done"
|
||||||
|
|
||||||
|
|
@ -59,7 +60,7 @@ _rotate machine key:
|
||||||
check:
|
check:
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
for machine in $(ls {{ base_path }}); do
|
for machine in $(ls {{ machine_base_path }}); do
|
||||||
just vars _check "$machine"
|
just vars _check "$machine"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
@ -70,14 +71,14 @@ _check machine:
|
||||||
# we can skip this folder as we are
|
# we can skip this folder as we are
|
||||||
# missing the files used to compare
|
# missing the files used to compare
|
||||||
# the defined vs the configured secrets
|
# the defined vs the configured secrets
|
||||||
if [ ! -f "{{ base_path }}/{{ machine }}/default.nix" ]; then
|
if [ ! -f "{{ machine_base_path }}/{{ machine }}/default.nix" ]; then
|
||||||
printf "\r• %-8sskipped\n" "{{ machine }}"
|
printf "\r• %-8sskipped\n" "{{ machine }}"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exec 3< <(jq -nr \
|
exec 3< <(jq -nr \
|
||||||
--rawfile defined <(nix eval --json ..#nixosConfigurations.{{ machine }}.config.sops.secrets 2>/dev/null) \
|
--rawfile defined <(nix eval --json ..#nixosConfigurations.{{ machine }}.config.sops.secrets 2>/dev/null) \
|
||||||
--rawfile configured <([ -f "{{ base_path }}/{{ machine }}/secrets.yml" ] && sops decrypt {{ base_path }}/{{ machine }}/secrets.yml | yq '.' || echo "{}") \
|
--rawfile configured <([ -f "{{ secret_base_path }}/{{ machine }}/secrets.yml" ] && sops decrypt {{ secret_base_path }}/{{ machine }}/secrets.yml | yq '.' || echo "{}") \
|
||||||
'
|
'
|
||||||
[ $configured | fromjson | paths(scalars) | join("/") ] as $conf
|
[ $configured | fromjson | paths(scalars) | join("/") ] as $conf
|
||||||
| $defined
|
| $defined
|
||||||
|
|
|
||||||
31
.justfile
31
.justfile
|
|
@ -3,34 +3,3 @@
|
||||||
|
|
||||||
[doc('Manage vars')]
|
[doc('Manage vars')]
|
||||||
mod vars '.just/vars.just'
|
mod vars '.just/vars.just'
|
||||||
|
|
||||||
[doc('Manage users')]
|
|
||||||
mod users '.just/users.just'
|
|
||||||
|
|
||||||
[doc('Manage machines')]
|
|
||||||
mod machine '.just/machine.just'
|
|
||||||
|
|
||||||
[doc('Show information about project')]
|
|
||||||
@show:
|
|
||||||
echo "show"
|
|
||||||
|
|
||||||
[doc('update the flake dependencies')]
|
|
||||||
@update:
|
|
||||||
nix flake update
|
|
||||||
git commit -m 'chore: update dependencies' -- ./flake.lock > /dev/null
|
|
||||||
echo "Done"
|
|
||||||
|
|
||||||
[doc('Introspection on flake output')]
|
|
||||||
@select key:
|
|
||||||
nix eval --show-trace --json .#{{ key }} | jq .
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#===============================================================================================
|
|
||||||
# Utils
|
|
||||||
#===============================================================================================
|
|
||||||
[no-exit-message]
|
|
||||||
[no-cd]
|
|
||||||
[private]
|
|
||||||
@assert condition message:
|
|
||||||
[ {{ condition }} ] || { echo -e 1>&2 "\n\x1b[1;41m Error \x1b[0m {{ message }}\n"; exit 1; }
|
|
||||||
|
|
|
||||||
43
clan/flake-module.nix
Normal file
43
clan/flake-module.nix
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
inputs,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
imports = [
|
||||||
|
./machines.nix
|
||||||
|
./tags.nix
|
||||||
|
./instances.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
clan = {
|
||||||
|
meta = {
|
||||||
|
name = "arda";
|
||||||
|
domain = "arda";
|
||||||
|
description = "My personal machines at home";
|
||||||
|
};
|
||||||
|
|
||||||
|
directory = ../.;
|
||||||
|
|
||||||
|
specialArgs = {
|
||||||
|
ardaLib = {
|
||||||
|
types =
|
||||||
|
./types
|
||||||
|
|> (inputs.import-tree.withLib lib).leafs
|
||||||
|
|> lib.map (mod: {
|
||||||
|
name = mod |> lib.baseNameOf |> lib.splitString "." |> lib.head;
|
||||||
|
value = lib.types.submoduleWith {modules = [mod];};
|
||||||
|
})
|
||||||
|
|> lib.listToAttrs;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
exportInterfaces =
|
||||||
|
./interfaces
|
||||||
|
|> (inputs.import-tree.withLib lib).leafs
|
||||||
|
|> lib.map (mod: {
|
||||||
|
name = mod |> lib.baseNameOf |> lib.splitString "." |> lib.head;
|
||||||
|
value = import mod;
|
||||||
|
})
|
||||||
|
|> lib.listToAttrs;
|
||||||
|
};
|
||||||
|
}
|
||||||
253
clan/instances.nix
Normal file
253
clan/instances.nix
Normal file
|
|
@ -0,0 +1,253 @@
|
||||||
|
{
|
||||||
|
self,
|
||||||
|
inputs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
db =
|
||||||
|
self.clan.exports
|
||||||
|
|> inputs.clan-core.lib.getExport {
|
||||||
|
serviceName = "arda/persistence";
|
||||||
|
roleName = "default";
|
||||||
|
machineName = "ulmo";
|
||||||
|
instanceName = "persistence";
|
||||||
|
}
|
||||||
|
|> (v: v.persistence.driver.${v.persistence.main});
|
||||||
|
in {
|
||||||
|
clan.inventory.instances = {
|
||||||
|
users-chris = {
|
||||||
|
module = {
|
||||||
|
name = "users";
|
||||||
|
input = "clan-core";
|
||||||
|
};
|
||||||
|
|
||||||
|
roles.default.machines.mandos.settings = {};
|
||||||
|
roles.default.machines.manwe.settings = {};
|
||||||
|
roles.default.machines.orome.settings = {};
|
||||||
|
roles.default.machines.tulkas.settings = {};
|
||||||
|
|
||||||
|
roles.default.settings = {
|
||||||
|
user = "chris";
|
||||||
|
groups = ["wheel"];
|
||||||
|
prompt = true;
|
||||||
|
share = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
clanDns = {
|
||||||
|
module = {
|
||||||
|
name = "dm-dns";
|
||||||
|
input = "clan-core";
|
||||||
|
};
|
||||||
|
|
||||||
|
roles.default.tags = ["all"];
|
||||||
|
};
|
||||||
|
|
||||||
|
gateway = {
|
||||||
|
module = {
|
||||||
|
name = "gateway";
|
||||||
|
input = "self";
|
||||||
|
};
|
||||||
|
|
||||||
|
roles.default = {
|
||||||
|
tags = ["operational:role:gateway"];
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
driver = "caddy";
|
||||||
|
|
||||||
|
hosts = {
|
||||||
|
"auth.kruining.eu" = ''
|
||||||
|
reverse_proxy h2c://[::1]:9092
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
persistence = {
|
||||||
|
module = {
|
||||||
|
name = "persistence";
|
||||||
|
input = "self";
|
||||||
|
};
|
||||||
|
|
||||||
|
roles.default.tags = ["operational:availability:always-on" "operational:storage:large"];
|
||||||
|
};
|
||||||
|
|
||||||
|
identity = {
|
||||||
|
module = {
|
||||||
|
name = "identity";
|
||||||
|
input = "self";
|
||||||
|
};
|
||||||
|
|
||||||
|
roles.default = {
|
||||||
|
tags = ["operational:availability:always-on"];
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
database = db;
|
||||||
|
|
||||||
|
organization = {
|
||||||
|
nix = {
|
||||||
|
user = {
|
||||||
|
chris = {
|
||||||
|
email = "chris@kruining.eu";
|
||||||
|
firstName = "Chris";
|
||||||
|
lastName = "Kruining";
|
||||||
|
|
||||||
|
roles = ["ORG_OWNER"];
|
||||||
|
instanceRoles = ["IAM_OWNER"];
|
||||||
|
};
|
||||||
|
|
||||||
|
kaas = {
|
||||||
|
email = "chris+kaas@kruining.eu";
|
||||||
|
firstName = "Kaas";
|
||||||
|
lastName = "Kruining";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
project = {
|
||||||
|
ulmo = {
|
||||||
|
projectRoleCheck = true;
|
||||||
|
projectRoleAssertion = true;
|
||||||
|
hasProjectCheck = true;
|
||||||
|
|
||||||
|
role = {
|
||||||
|
jellyfin = {
|
||||||
|
group = "jellyfin";
|
||||||
|
};
|
||||||
|
jellyfin_admin = {
|
||||||
|
group = "jellyfin";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
assign = {
|
||||||
|
chris = ["jellyfin" "jellyfin_admin"];
|
||||||
|
kaas = ["jellyfin"];
|
||||||
|
};
|
||||||
|
|
||||||
|
application = {
|
||||||
|
jellyfin = {
|
||||||
|
redirectUris = ["https://jellyfin.kruining.eu/sso/OID/redirect/zitadel"];
|
||||||
|
grantTypes = ["authorizationCode"];
|
||||||
|
responseTypes = ["code"];
|
||||||
|
};
|
||||||
|
|
||||||
|
forgejo = {
|
||||||
|
redirectUris = ["https://git.amarth.cloud/user/oauth2/zitadel/callback"];
|
||||||
|
grantTypes = ["authorizationCode"];
|
||||||
|
responseTypes = ["code"];
|
||||||
|
};
|
||||||
|
|
||||||
|
vaultwarden = {
|
||||||
|
redirectUris = ["https://vault.kruining.eu/identity/connect/oidc-signin"];
|
||||||
|
grantTypes = ["authorizationCode"];
|
||||||
|
responseTypes = ["code"];
|
||||||
|
exportMap = {
|
||||||
|
client_id = "SSO_CLIENT_ID";
|
||||||
|
client_secret = "SSO_CLIENT_SECRET";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
matrix = {
|
||||||
|
redirectUris = ["https://matrix.kruining.eu/_synapse/client/oidc/callback"];
|
||||||
|
grantTypes = ["authorizationCode"];
|
||||||
|
responseTypes = ["code"];
|
||||||
|
};
|
||||||
|
|
||||||
|
mydia = {
|
||||||
|
redirectUris = ["http://localhost:2010/auth/oidc/callback"];
|
||||||
|
grantTypes = ["authorizationCode"];
|
||||||
|
responseTypes = ["code"];
|
||||||
|
};
|
||||||
|
|
||||||
|
grafana = {
|
||||||
|
redirectUris = ["http://localhost:9001/login/generic_oauth"];
|
||||||
|
grantTypes = ["authorizationCode"];
|
||||||
|
responseTypes = ["code"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
convex = {
|
||||||
|
projectRoleCheck = true;
|
||||||
|
projectRoleAssertion = true;
|
||||||
|
hasProjectCheck = true;
|
||||||
|
|
||||||
|
application = {
|
||||||
|
scry = {
|
||||||
|
redirectUris = ["https://nautical-salamander-320.eu-west-1.convex.cloud/api/auth/callback/zitadel"];
|
||||||
|
grantTypes = ["authorizationCode"];
|
||||||
|
responseTypes = ["code"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
action = {
|
||||||
|
flattenRoles = {
|
||||||
|
script = ''
|
||||||
|
(ctx, api) => {
|
||||||
|
if (ctx.v1.user.grants == undefined || ctx.v1.user.grants.count == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 }));
|
||||||
|
};
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
triggers = [
|
||||||
|
{
|
||||||
|
flowType = "customiseToken";
|
||||||
|
triggerType = "preUserinfoCreation";
|
||||||
|
actions = ["flattenRoles"];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
flowType = "customiseToken";
|
||||||
|
triggerType = "preAccessTokenCreation";
|
||||||
|
actions = ["flattenRoles"];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
servarr = {
|
||||||
|
module = {
|
||||||
|
name = "servarr";
|
||||||
|
input = "self";
|
||||||
|
};
|
||||||
|
|
||||||
|
roles.default = {
|
||||||
|
tags = ["operational:availability:always-on"];
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
enable = true;
|
||||||
|
database = db;
|
||||||
|
|
||||||
|
services = {
|
||||||
|
sonarr = {
|
||||||
|
rootFolders = [
|
||||||
|
"/var/media/series"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
radarr = {
|
||||||
|
rootFolders = [
|
||||||
|
"/var/media/movies"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
lidarr = {
|
||||||
|
rootFolders = [
|
||||||
|
"/var/media/music"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
prowlarr = {};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
94
clan/interfaces/gateway.nix
Normal file
94
clan/interfaces/gateway.nix
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
{lib, ...}: let
|
||||||
|
inherit (lib) mkOption types;
|
||||||
|
in {
|
||||||
|
options = {
|
||||||
|
services = mkOption {
|
||||||
|
type = types.attrsOf (types.submodule ({name, ...}: {
|
||||||
|
options = {
|
||||||
|
name = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = name;
|
||||||
|
};
|
||||||
|
|
||||||
|
endpoint = mkOption {
|
||||||
|
type = types.submoduleWith {
|
||||||
|
modules = [../types/endpoint.nix];
|
||||||
|
};
|
||||||
|
default = {};
|
||||||
|
apply = attrs:
|
||||||
|
attrs
|
||||||
|
// {
|
||||||
|
__toString = self: let
|
||||||
|
protocol =
|
||||||
|
if self.protocol != null
|
||||||
|
then "${self.protocol}://"
|
||||||
|
else "";
|
||||||
|
|
||||||
|
port =
|
||||||
|
if self.port != null
|
||||||
|
then ":${toString self.port}"
|
||||||
|
else "";
|
||||||
|
|
||||||
|
path =
|
||||||
|
if self.path != null
|
||||||
|
then "/${self.path}"
|
||||||
|
else "";
|
||||||
|
|
||||||
|
query =
|
||||||
|
if self.query != null
|
||||||
|
then "?${toString self.query
|
||||||
|
|> lib.attrsToList
|
||||||
|
|> lib.map ({
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
}: "${name}=${value}")}"
|
||||||
|
else "";
|
||||||
|
|
||||||
|
hash =
|
||||||
|
if self.hash != null
|
||||||
|
then "#${toString self.hash
|
||||||
|
|> lib.attrsToList
|
||||||
|
|> lib.map ({
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
}: "${name}=${value}")}"
|
||||||
|
else "";
|
||||||
|
in "${protocol}${self.host}${port}${path}${query}${hash}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# protocol = mkOption {
|
||||||
|
# type = types.str;
|
||||||
|
# default = "http";
|
||||||
|
# };
|
||||||
|
|
||||||
|
# host = mkOption {
|
||||||
|
# type = types.str;
|
||||||
|
# default = "[::1]";
|
||||||
|
# };
|
||||||
|
|
||||||
|
# port = mkOption {
|
||||||
|
# type = types.port;
|
||||||
|
# };
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
default = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
functions = mkOption {
|
||||||
|
type = types.attrsOf (types.submodule ({name, ...}: {
|
||||||
|
options = {
|
||||||
|
name = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = name;
|
||||||
|
};
|
||||||
|
|
||||||
|
body = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
default = {};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
24
clan/interfaces/persistence.nix
Normal file
24
clan/interfaces/persistence.nix
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
{lib, ...}: let
|
||||||
|
inherit (lib) mkOption types;
|
||||||
|
in {
|
||||||
|
options = {
|
||||||
|
main = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
driver = mkOption {
|
||||||
|
type = types.attrsOf (types.submoduleWith {
|
||||||
|
modules = [
|
||||||
|
../types/endpoint.nix
|
||||||
|
];
|
||||||
|
});
|
||||||
|
default = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
databases = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
75
clan/machines.nix
Normal file
75
clan/machines.nix
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
{...}: {
|
||||||
|
clan.inventory.machines = {
|
||||||
|
aule = {
|
||||||
|
name = "aule";
|
||||||
|
description = "Planned build server.";
|
||||||
|
machineClass = "nixos";
|
||||||
|
tags = [];
|
||||||
|
};
|
||||||
|
mandos = {
|
||||||
|
name = "mandos";
|
||||||
|
description = "Living room Steam box.";
|
||||||
|
machineClass = "nixos";
|
||||||
|
tags = [
|
||||||
|
"capability:mobility:stationary"
|
||||||
|
"operational:availability:wake-on-demand"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
manwe = {
|
||||||
|
name = "manwe";
|
||||||
|
description = "Main desktop.";
|
||||||
|
machineClass = "nixos";
|
||||||
|
tags = [
|
||||||
|
"capability:mobility:stationary"
|
||||||
|
"operational:availability:manual"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
melkor = {
|
||||||
|
name = "melkor";
|
||||||
|
description = "Planned machine with no defined role yet.";
|
||||||
|
machineClass = "nixos";
|
||||||
|
tags = [];
|
||||||
|
};
|
||||||
|
orome = {
|
||||||
|
name = "orome";
|
||||||
|
description = "Work laptop.";
|
||||||
|
machineClass = "nixos";
|
||||||
|
tags = [
|
||||||
|
"capability:mobility:portable"
|
||||||
|
"operational:availability:manual"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
tulkas = {
|
||||||
|
name = "tulkas";
|
||||||
|
description = "Steam Deck.";
|
||||||
|
machineClass = "nixos";
|
||||||
|
tags = [
|
||||||
|
"capability:mobility:portable"
|
||||||
|
"operational:availability:manual"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
ulmo = {
|
||||||
|
name = "ulmo";
|
||||||
|
description = "Primary self-hosted services machine.";
|
||||||
|
machineClass = "nixos";
|
||||||
|
tags = [
|
||||||
|
"capability:mobility:stationary"
|
||||||
|
"operational:availability:always-on"
|
||||||
|
"operational:storage:large"
|
||||||
|
"operational:role:gateway"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
varda = {
|
||||||
|
name = "varda";
|
||||||
|
description = "Planned machine with no defined role yet.";
|
||||||
|
machineClass = "nixos";
|
||||||
|
tags = [];
|
||||||
|
};
|
||||||
|
yavanna = {
|
||||||
|
name = "yavanna";
|
||||||
|
description = "Planned machine with no defined role yet.";
|
||||||
|
machineClass = "nixos";
|
||||||
|
tags = [];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
12
clan/tags.nix
Normal file
12
clan/tags.nix
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
{...}: {
|
||||||
|
clan.inventory.tags = {
|
||||||
|
config,
|
||||||
|
machines,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
# tag_name = [ "list" "of" "machines" ]
|
||||||
|
"capability:hardware:gpu" = [""];
|
||||||
|
"capability:hardware:audio" = [""];
|
||||||
|
"capability:hardware:bluetooth" = [""];
|
||||||
|
};
|
||||||
|
}
|
||||||
45
clan/types/endpoint.nix
Normal file
45
clan/types/endpoint.nix
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
{lib, ...}: let
|
||||||
|
inherit (lib) mkOption types;
|
||||||
|
in {
|
||||||
|
options = {
|
||||||
|
protocol = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "http";
|
||||||
|
};
|
||||||
|
|
||||||
|
host = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "localhost";
|
||||||
|
};
|
||||||
|
|
||||||
|
port = mkOption {
|
||||||
|
type = types.nullOr types.port;
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
user = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
password = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
path = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
query = mkOption {
|
||||||
|
type = types.nullOr (types.attrsOf types.str);
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
hash = mkOption {
|
||||||
|
type = types.nullOr (types.attrsOf types.str);
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
19
clanServices/flake-module.nix
Normal file
19
clanServices/flake-module.nix
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
{lib, ...}: {
|
||||||
|
imports =
|
||||||
|
./.
|
||||||
|
|> builtins.readDir
|
||||||
|
|> lib.attrsToList
|
||||||
|
|> builtins.map ({
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
}: {
|
||||||
|
type = value;
|
||||||
|
path = ./. + "/${name}/flake-module.nix";
|
||||||
|
})
|
||||||
|
|> builtins.filter ({
|
||||||
|
type,
|
||||||
|
path,
|
||||||
|
}:
|
||||||
|
type == "directory" && (builtins.pathExists path))
|
||||||
|
|> builtins.map ({path, ...}: path);
|
||||||
|
}
|
||||||
0
clanServices/gateway/README.md
Normal file
0
clanServices/gateway/README.md
Normal file
92
clanServices/gateway/default.nix
Normal file
92
clanServices/gateway/default.nix
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
clanLib,
|
||||||
|
exports,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (builtins) toString;
|
||||||
|
in {
|
||||||
|
_class = "clan.service";
|
||||||
|
manifest = {
|
||||||
|
name = "arda/gateway";
|
||||||
|
description = ''
|
||||||
|
'';
|
||||||
|
readme = builtins.readFile ./README.md;
|
||||||
|
exports = {
|
||||||
|
inputs = [];
|
||||||
|
out = [];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
roles.default = {
|
||||||
|
description = '''';
|
||||||
|
|
||||||
|
interface = {lib, ...}: let
|
||||||
|
inherit (lib) mkOption types;
|
||||||
|
in {
|
||||||
|
options = {
|
||||||
|
driver = mkOption {
|
||||||
|
type = types.enum ["caddy" "nginx"];
|
||||||
|
};
|
||||||
|
|
||||||
|
hosts = mkOption {
|
||||||
|
type = types.attrsOf types.str;
|
||||||
|
default = {};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
perInstance = {
|
||||||
|
mkExports,
|
||||||
|
machine,
|
||||||
|
settings,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
reverse_proxies =
|
||||||
|
exports
|
||||||
|
|> clanLib.selectExports (_scope: true)
|
||||||
|
|> lib.mapAttrsToList (_: value: (value.gateway.services or {}) |> lib.attrValues)
|
||||||
|
|> lib.concatLists
|
||||||
|
|> lib.map ({
|
||||||
|
name,
|
||||||
|
endpoint,
|
||||||
|
}: {
|
||||||
|
name = "${name}.${machine.name}.arda";
|
||||||
|
value = {
|
||||||
|
extraConfig = ''
|
||||||
|
reverse_proxy ${toString endpoint}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|> lib.listToAttrs;
|
||||||
|
in {
|
||||||
|
# exports =
|
||||||
|
# mkExports {
|
||||||
|
# };
|
||||||
|
|
||||||
|
nixosModule = {
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (lib) mkMerge mkIf;
|
||||||
|
|
||||||
|
caddyPackage = pkgs.caddy.withPlugins {
|
||||||
|
plugins = ["github.com/corazawaf/coraza-caddy/v2@v2.1.0"];
|
||||||
|
hash = "sha256-pSXjLaZoRtKV3eFl2ySRSjl3yxi514G1Cb7pfrpxxtE=";
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
config = mkMerge [
|
||||||
|
(lib.mkIf (settings.driver == "caddy") {
|
||||||
|
services.caddy = {
|
||||||
|
enable = true;
|
||||||
|
package = caddyPackage;
|
||||||
|
|
||||||
|
virtualHosts = reverse_proxies // {};
|
||||||
|
};
|
||||||
|
})
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
13
clanServices/gateway/flake-module.nix
Normal file
13
clanServices/gateway/flake-module.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
{...}: let
|
||||||
|
module = ./default.nix;
|
||||||
|
in {
|
||||||
|
clan.modules.gateway = module;
|
||||||
|
|
||||||
|
# perSystem = {...}: {
|
||||||
|
# clan.nixosTests.gateway = {
|
||||||
|
# imports = [];
|
||||||
|
|
||||||
|
# clan.modules."@arda/gateway" = module;
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
}
|
||||||
0
clanServices/identity/README.md
Normal file
0
clanServices/identity/README.md
Normal file
518
clanServices/identity/default.nix
Normal file
518
clanServices/identity/default.nix
Normal file
|
|
@ -0,0 +1,518 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
clanLib,
|
||||||
|
exports,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (builtins) toString readFile;
|
||||||
|
inherit (lib) mkMerge mkIf;
|
||||||
|
in {
|
||||||
|
_class = "clan.service";
|
||||||
|
manifest = {
|
||||||
|
name = "arda/identity";
|
||||||
|
description = ''
|
||||||
|
'';
|
||||||
|
readme = readFile ./README.md;
|
||||||
|
exports = {
|
||||||
|
inputs = ["persistence"];
|
||||||
|
out = ["gateway" "persistence"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
roles.default = {
|
||||||
|
description = '''';
|
||||||
|
|
||||||
|
interface = {lib, ...}: let
|
||||||
|
inherit (lib) mkOption types toSentenceCase literalExpression;
|
||||||
|
in {
|
||||||
|
options = {
|
||||||
|
driver = mkOption {
|
||||||
|
type = types.enum ["zitadel"];
|
||||||
|
default = "zitadel";
|
||||||
|
};
|
||||||
|
|
||||||
|
database = mkOption {
|
||||||
|
type = types.anything;
|
||||||
|
};
|
||||||
|
|
||||||
|
port = mkOption {
|
||||||
|
type = types.port;
|
||||||
|
default = 9092;
|
||||||
|
};
|
||||||
|
|
||||||
|
organization = mkOption {
|
||||||
|
type = types.attrsOf (types.submodule ({ name, ... }: {
|
||||||
|
options =
|
||||||
|
let
|
||||||
|
org = name;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
isDefault = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
example = "true";
|
||||||
|
description = ''
|
||||||
|
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.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
project = mkOption {
|
||||||
|
default = {};
|
||||||
|
type = types.attrsOf (types.submodule {
|
||||||
|
options = {
|
||||||
|
hasProjectCheck = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
example = "true";
|
||||||
|
description = ''
|
||||||
|
ZITADEL checks if the org of the user has permission to this project.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
privateLabelingSetting = mkOption {
|
||||||
|
type = types.nullOr (types.enum [ "unspecified" "enforceProjectResourceOwnerPolicy" "allowLoginUserResourceOwnerPolicy" ]);
|
||||||
|
default = null;
|
||||||
|
example = "enforceProjectResourceOwnerPolicy";
|
||||||
|
description = ''
|
||||||
|
Defines from where the private labeling should be triggered,
|
||||||
|
|
||||||
|
supported values:
|
||||||
|
- unspecified
|
||||||
|
- enforceProjectResourceOwnerPolicy
|
||||||
|
- allowLoginUserResourceOwnerPolicy
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
projectRoleAssertion = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
example = "true";
|
||||||
|
description = ''
|
||||||
|
Describes if roles of user should be added in token.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
projectRoleCheck = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
example = "true";
|
||||||
|
description = ''
|
||||||
|
ZITADEL checks if the user has at least one on this project.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
role = mkOption {
|
||||||
|
default = {};
|
||||||
|
type = types.attrsOf (types.submodule ({ name, ... }: {
|
||||||
|
options =
|
||||||
|
let
|
||||||
|
roleName = name;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
displayName = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = toSentenceCase name;
|
||||||
|
example = "RoleName";
|
||||||
|
description = ''
|
||||||
|
Name used for project role.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
group = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
example = "some_group";
|
||||||
|
description = ''
|
||||||
|
Group used for project role.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
assign = mkOption {
|
||||||
|
default = {};
|
||||||
|
type = types.attrsOf (types.listOf types.str);
|
||||||
|
};
|
||||||
|
|
||||||
|
application = mkOption {
|
||||||
|
default = {};
|
||||||
|
type = types.attrsOf (types.submodule {
|
||||||
|
options = {
|
||||||
|
redirectUris = mkOption {
|
||||||
|
type = types.nonEmptyListOf types.str;
|
||||||
|
example = ''
|
||||||
|
[ "https://example.com/redirect/url" ]
|
||||||
|
'';
|
||||||
|
description = ''
|
||||||
|
.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
grantTypes = mkOption {
|
||||||
|
type = types.nonEmptyListOf (types.enum [ "authorizationCode" "implicit" "refreshToken" "deviceCode" "tokenExchange" ]);
|
||||||
|
example = ''
|
||||||
|
[ "authorizationCode" ]
|
||||||
|
'';
|
||||||
|
description = ''
|
||||||
|
.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
responseTypes = mkOption {
|
||||||
|
type = types.nonEmptyListOf (types.enum [ "code" "idToken" "idTokenToken" ]);
|
||||||
|
example = ''
|
||||||
|
[ "code" ]
|
||||||
|
'';
|
||||||
|
description = ''
|
||||||
|
.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
exportMap =
|
||||||
|
let
|
||||||
|
strOpt = mkOption { type = types.nullOr types.str; default = null; };
|
||||||
|
in
|
||||||
|
mkOption {
|
||||||
|
type = types.submodule { options = { client_id = strOpt; client_secret = strOpt; }; };
|
||||||
|
default = {};
|
||||||
|
example = literalExpression ''
|
||||||
|
{
|
||||||
|
client_id = "SSO_CLIENT_ID";
|
||||||
|
client_secret = "SSO_CLIENT_SECRET";
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
description = ''
|
||||||
|
Remap the outputted variables to another key.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
user = mkOption {
|
||||||
|
default = {};
|
||||||
|
type = types.attrsOf (types.submodule ({ name, ... }: {
|
||||||
|
options =
|
||||||
|
let
|
||||||
|
username = name;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
email = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
example = "someone@some.domain";
|
||||||
|
description = ''
|
||||||
|
Username.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
userName = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = username;
|
||||||
|
example = "some_user_name";
|
||||||
|
description = ''
|
||||||
|
Username. Default value is the key of the config object you created, you can overwrite that by setting this option
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
firstName = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
example = "John";
|
||||||
|
description = ''
|
||||||
|
First name of the user.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
lastName = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
example = "Doe";
|
||||||
|
description = ''
|
||||||
|
Last name of the user.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
roles = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
example = "[ \"ORG_OWNER\" ]";
|
||||||
|
description = ''
|
||||||
|
List of roles granted to organisation.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
instanceRoles = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
example = "[ \"IAM_OWNER\" ]";
|
||||||
|
description = ''
|
||||||
|
List of roles granted to instance.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
action = mkOption {
|
||||||
|
default = {};
|
||||||
|
type = types.attrsOf (types.submodule ({ name, ... }: {
|
||||||
|
options = {
|
||||||
|
script = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
example = ''
|
||||||
|
(ctx, api) => {
|
||||||
|
api.v1.claims.setClaim('some_claim', 'some_value');
|
||||||
|
};
|
||||||
|
'';
|
||||||
|
description = ''
|
||||||
|
The script to run. This must be a function that receives 2 parameters, and returns void. During the creation of the action's script this module simly does `const {{name}} = {{script}}`.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
timeout = mkOption {
|
||||||
|
type = (types.ints.between 0 20);
|
||||||
|
default = 10;
|
||||||
|
example = "10";
|
||||||
|
description = ''
|
||||||
|
After which time the action will be terminated if not finished.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
allowedToFail = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
example = "true";
|
||||||
|
description = ''
|
||||||
|
Allowed to fail.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
triggers = mkOption {
|
||||||
|
default = [];
|
||||||
|
type = types.listOf (types.submodule {
|
||||||
|
options = {
|
||||||
|
flowType = mkOption {
|
||||||
|
type = types.enum [ "authentication" "customiseToken" "internalAuthentication" "samlResponse" ];
|
||||||
|
example = "customiseToken";
|
||||||
|
description = ''
|
||||||
|
Type of the flow to which the action triggers belong.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
triggerType = mkOption {
|
||||||
|
type = types.enum [ "postAuthentication" "preCreation" "postCreation" "preUserinfoCreation" "preAccessTokenCreation" "preSamlResponse" ];
|
||||||
|
example = "postAuthentication";
|
||||||
|
description = ''
|
||||||
|
Trigger type on when the actions get triggered.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
actions = mkOption {
|
||||||
|
type = types.nonEmptyListOf types.str;
|
||||||
|
example = ''[ "action_name" ]'';
|
||||||
|
description = ''
|
||||||
|
Names of actions to trigger
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
perInstance = {
|
||||||
|
mkExports,
|
||||||
|
settings,
|
||||||
|
machine,
|
||||||
|
instanceName,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
exports = mkExports (mkMerge [
|
||||||
|
{
|
||||||
|
gateway.services.identity = {endpoint.port = settings.port;};
|
||||||
|
}
|
||||||
|
(mkIf (settings.driver == "zitadel") {
|
||||||
|
gateway.functions.auth = {
|
||||||
|
body = ''
|
||||||
|
forward_auth h2c://[::1]:${toString settings.port} {
|
||||||
|
uri /api/authz/forward-auth
|
||||||
|
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
persistence.databases = ["zitadel"];
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
|
||||||
|
nixosModule = args@{
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
config,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
vars = config.clan.core.vars.generators.zitadel.files;
|
||||||
|
users = config.clan.core.vars.generators.zitadel_users.files.users.path;
|
||||||
|
email_password = config.clan.core.vars.generators.zitadel_email_password.files.password.path;
|
||||||
|
|
||||||
|
ardaLib = import ../../lib/strings.nix args;
|
||||||
|
zLib = import ./lib.nix (args // {inherit settings ardaLib;});
|
||||||
|
in {
|
||||||
|
config = mkMerge [
|
||||||
|
(mkIf (settings.driver == "zitadel") ({
|
||||||
|
clan.core.vars.generators.zitadel = {
|
||||||
|
dependencies = ["persistence"];
|
||||||
|
|
||||||
|
files = {
|
||||||
|
masterKey = {
|
||||||
|
deploy = true;
|
||||||
|
owner = "zitadel";
|
||||||
|
group = "zitadel";
|
||||||
|
restartUnits = ["zitadel.service"];
|
||||||
|
};
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
deploy = true;
|
||||||
|
owner = "zitadel";
|
||||||
|
group = "zitadel";
|
||||||
|
restartUnits = ["zitadel.service"];
|
||||||
|
};
|
||||||
|
|
||||||
|
infraPrivateKey = {
|
||||||
|
deploy = true;
|
||||||
|
owner = "zitadel";
|
||||||
|
group = "zitadel";
|
||||||
|
restartUnits = ["zitadel.service"];
|
||||||
|
};
|
||||||
|
|
||||||
|
infraPublicKey = {
|
||||||
|
deploy = true;
|
||||||
|
owner = "zitadel";
|
||||||
|
group = "zitadel";
|
||||||
|
restartUnits = ["zitadel.service"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
runtimeInputs = with pkgs; [pwgen openssl_3_5];
|
||||||
|
script = ''
|
||||||
|
pwgen -s 32 1 > $out/masterKey
|
||||||
|
|
||||||
|
openssl genrsa -traditional -out $out/infraPrivateKey 2048
|
||||||
|
openssl rsa -pubout -in $out/infraPrivateKey -out $out/infraPublicKey
|
||||||
|
|
||||||
|
cat << EOL > $out/settings
|
||||||
|
Database:
|
||||||
|
postgres:
|
||||||
|
User:
|
||||||
|
Password: $(cat $in/persistence/zitadel_password)
|
||||||
|
Admin:
|
||||||
|
Password: $(cat $in/persistence/zitadel_password)
|
||||||
|
EOL
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
clan.core.vars.generators.zitadel_users = {
|
||||||
|
files = {
|
||||||
|
users = {
|
||||||
|
deploy = true;
|
||||||
|
owner = "zitadel";
|
||||||
|
group = "zitadel";
|
||||||
|
restartUnits = ["infra-zitadel.service"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
script = ''
|
||||||
|
echo "{}" > $out/users
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
clan.core.vars.generators.zitadel_email_password = {
|
||||||
|
prompts = {
|
||||||
|
password = {
|
||||||
|
description = "password to email for zitadel's smpt connection";
|
||||||
|
type = "hidden";
|
||||||
|
persist = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
files = {
|
||||||
|
password = {
|
||||||
|
deploy = true;
|
||||||
|
owner = "zitadel";
|
||||||
|
group = "zitadel";
|
||||||
|
restartUnits = ["infra-zitadel.service"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
script = ''
|
||||||
|
cat $prompts/password > $out/password
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
zitadel
|
||||||
|
];
|
||||||
|
|
||||||
|
services.zitadel = {
|
||||||
|
enable = true;
|
||||||
|
masterKeyFile = vars.masterKey.path;
|
||||||
|
|
||||||
|
tlsMode = "external";
|
||||||
|
|
||||||
|
extraSettingsPaths = [
|
||||||
|
vars.settings.path
|
||||||
|
];
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
Port = settings.port;
|
||||||
|
|
||||||
|
ExternalDomain = "auth.kruining.eu";
|
||||||
|
ExternalPort = 443;
|
||||||
|
ExternalSecure = true;
|
||||||
|
|
||||||
|
Metrics.Type = "otel";
|
||||||
|
Tracing.Type = "otel";
|
||||||
|
Telemetry.Enabled = true;
|
||||||
|
|
||||||
|
SystemDefaults = {
|
||||||
|
PasswordHasher.Hasher.Algorithm = "argon2id";
|
||||||
|
SecretHasher.Hasher.Algorithm = "argon2id";
|
||||||
|
};
|
||||||
|
|
||||||
|
Database.postgres = {
|
||||||
|
Host = settings.database.host;
|
||||||
|
Port = settings.database.port;
|
||||||
|
Database = "zitadel";
|
||||||
|
User = {
|
||||||
|
Username = "zitadel";
|
||||||
|
};
|
||||||
|
Admin = {
|
||||||
|
Username = "zitadel";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
SystemAPIUsers = {
|
||||||
|
infra = {
|
||||||
|
Path = vars.infraPublicKey.path;
|
||||||
|
Memberships = [
|
||||||
|
{ MemberType = "System"; Roles = [ "SYSTEM_OWNER" "IAM_OWNER" "ORG_OWNER" ]; }
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} // (zLib.createInfra { inherit users email_password; key_file = vars.infraPrivateKey.path; })))
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
13
clanServices/identity/flake-module.nix
Normal file
13
clanServices/identity/flake-module.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
{...}: let
|
||||||
|
module = ./default.nix;
|
||||||
|
in {
|
||||||
|
clan.modules.identity = module;
|
||||||
|
|
||||||
|
# perSystem = {...}: {
|
||||||
|
# clan.nixosTests.identity = {
|
||||||
|
# imports = [];
|
||||||
|
|
||||||
|
# clan.modules."@arda/identity" = module;
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
}
|
||||||
372
clanServices/identity/lib.nix
Normal file
372
clanServices/identity/lib.nix
Normal file
|
|
@ -0,0 +1,372 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
ardaLib,
|
||||||
|
self,
|
||||||
|
pkgs,
|
||||||
|
settings,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
createTerranixModule = {
|
||||||
|
users,
|
||||||
|
email_password,
|
||||||
|
key_file,
|
||||||
|
...
|
||||||
|
}: terra: let
|
||||||
|
inherit (lib) toUpper toSentenceCase nameValuePair mapAttrs mapAttrs' concatMapAttrs concatMapStringsSep filterAttrsRecursive listToAttrs imap0 head drop length literalExpression attrNames;
|
||||||
|
inherit (ardaLib) toSnakeCase;
|
||||||
|
inherit (terra.lib) tfRef;
|
||||||
|
|
||||||
|
_refTypeMap = {
|
||||||
|
org = {type = "org";};
|
||||||
|
project = {type = "project";};
|
||||||
|
user = {
|
||||||
|
type = "user";
|
||||||
|
tfType = "human_user";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
mapRef' = {
|
||||||
|
type,
|
||||||
|
tfType ? type,
|
||||||
|
}: name: {"${type}Id" = "\${ resource.zitadel_${tfType}.${toSnakeCase name}.id }";};
|
||||||
|
mapRef = type: name: mapRef' (_refTypeMap.${type}) name;
|
||||||
|
mapEnum = prefix: value: "${prefix}_${value |> toSnakeCase |> toUpper}";
|
||||||
|
|
||||||
|
mapValue = type: value: ({
|
||||||
|
appType = mapEnum "OIDC_APP_TYPE" value;
|
||||||
|
grantTypes = map (t: mapEnum "OIDC_GRANT_TYPE" t) value;
|
||||||
|
responseTypes = map (t: mapEnum "OIDC_RESPONSE_TYPE" t) value;
|
||||||
|
authMethodType = mapEnum "OIDC_AUTH_METHOD_TYPE" value;
|
||||||
|
|
||||||
|
flowType = mapEnum "FLOW_TYPE" value;
|
||||||
|
triggerType = mapEnum "TRIGGER_TYPE" value;
|
||||||
|
accessTokenType = mapEnum "OIDC_TOKEN_TYPE" value;
|
||||||
|
}."${type}" or value);
|
||||||
|
|
||||||
|
toResource = name: value:
|
||||||
|
nameValuePair
|
||||||
|
(toSnakeCase name)
|
||||||
|
(lib.mapAttrs' (k: v: nameValuePair (toSnakeCase k) (mapValue k v)) value);
|
||||||
|
|
||||||
|
withRef = type: name: attrs: attrs // (mapRef type name);
|
||||||
|
|
||||||
|
select = keys: callback: set:
|
||||||
|
if (length keys) == 0
|
||||||
|
then mapAttrs' callback set
|
||||||
|
else let
|
||||||
|
key = head keys;
|
||||||
|
in
|
||||||
|
concatMapAttrs (k: v: select (drop 1 keys) (callback k) (v.${key} or {})) set;
|
||||||
|
|
||||||
|
append = attrList: set: set // (listToAttrs attrList);
|
||||||
|
|
||||||
|
forEach = src: key: set: let
|
||||||
|
_key = concatMapStringsSep "_" (k: "\${item.${k}}") key;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
forEach = tfRef '' {
|
||||||
|
for item in ${src} :
|
||||||
|
"''${item.org}_''${item.name}" => item
|
||||||
|
}'';
|
||||||
|
}
|
||||||
|
// set;
|
||||||
|
in {
|
||||||
|
terraform.required_providers.zitadel = {
|
||||||
|
source = "zitadel/zitadel";
|
||||||
|
version = "2.2.0";
|
||||||
|
};
|
||||||
|
|
||||||
|
provider.zitadel = {
|
||||||
|
domain = "auth.kruining.eu";
|
||||||
|
insecure = false;
|
||||||
|
|
||||||
|
system_api = {
|
||||||
|
user = "infra";
|
||||||
|
inherit key_file;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
locals = {
|
||||||
|
extra_users = tfRef "
|
||||||
|
flatten([ for org, users in jsondecode(file(\"${users}\")): [
|
||||||
|
for name, details in users: {
|
||||||
|
org = org
|
||||||
|
name = name
|
||||||
|
email = details.email
|
||||||
|
firstName = details.firstName
|
||||||
|
lastName = details.lastName
|
||||||
|
}
|
||||||
|
] ])
|
||||||
|
";
|
||||||
|
orgs = settings.organization |> mapAttrs (org: _: tfRef "resource.zitadel_org.${org}.id");
|
||||||
|
};
|
||||||
|
|
||||||
|
resource = {
|
||||||
|
# Organizations
|
||||||
|
zitadel_org =
|
||||||
|
settings.organization
|
||||||
|
|> select [] (
|
||||||
|
name: {isDefault, ...}:
|
||||||
|
{inherit name isDefault;}
|
||||||
|
|> toResource name
|
||||||
|
);
|
||||||
|
|
||||||
|
# Projects per organization
|
||||||
|
zitadel_project =
|
||||||
|
settings.organization
|
||||||
|
|> select ["project"] (
|
||||||
|
org: name: {
|
||||||
|
hasProjectCheck,
|
||||||
|
privateLabelingSetting,
|
||||||
|
projectRoleAssertion,
|
||||||
|
projectRoleCheck,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
inherit name hasProjectCheck privateLabelingSetting projectRoleAssertion projectRoleCheck;
|
||||||
|
}
|
||||||
|
|> withRef "org" org
|
||||||
|
|> toResource "${org}_${name}"
|
||||||
|
);
|
||||||
|
|
||||||
|
# Each OIDC app per project
|
||||||
|
zitadel_application_oidc =
|
||||||
|
settings.organization
|
||||||
|
|> select ["project" "application"] (
|
||||||
|
org: project: name: {
|
||||||
|
redirectUris,
|
||||||
|
grantTypes,
|
||||||
|
responseTypes,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
inherit name redirectUris grantTypes responseTypes;
|
||||||
|
|
||||||
|
accessTokenRoleAssertion = true;
|
||||||
|
idTokenRoleAssertion = true;
|
||||||
|
accessTokenType = "JWT";
|
||||||
|
}
|
||||||
|
|> withRef "org" org
|
||||||
|
|> withRef "project" "${org}_${project}"
|
||||||
|
|> toResource "${org}_${project}_${name}"
|
||||||
|
);
|
||||||
|
|
||||||
|
# Each project role
|
||||||
|
zitadel_project_role =
|
||||||
|
settings.organization
|
||||||
|
|> select ["project" "role"] (
|
||||||
|
org: project: name: value:
|
||||||
|
{
|
||||||
|
inherit (value) displayName group;
|
||||||
|
roleKey = name;
|
||||||
|
}
|
||||||
|
|> withRef "org" org
|
||||||
|
|> withRef "project" "${org}_${project}"
|
||||||
|
|> toResource "${org}_${project}_${name}"
|
||||||
|
);
|
||||||
|
|
||||||
|
# Each project role assignment
|
||||||
|
zitadel_user_grant =
|
||||||
|
settings.organization
|
||||||
|
|> select ["project" "assign"] (
|
||||||
|
org: project: user: roles:
|
||||||
|
{roleKeys = roles;}
|
||||||
|
|> withRef "org" org
|
||||||
|
|> withRef "project" "${org}_${project}"
|
||||||
|
|> withRef "user" "${org}_${user}"
|
||||||
|
|> toResource "${org}_${project}_${user}"
|
||||||
|
);
|
||||||
|
|
||||||
|
# Users
|
||||||
|
zitadel_human_user =
|
||||||
|
settings.organization
|
||||||
|
|> select ["user"] (
|
||||||
|
org: name: {
|
||||||
|
email,
|
||||||
|
userName,
|
||||||
|
firstName,
|
||||||
|
lastName,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
inherit email userName firstName lastName;
|
||||||
|
|
||||||
|
isEmailVerified = true;
|
||||||
|
lifecycle = {
|
||||||
|
ignore_changes = ["first_name" "last_name" "user_name"];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|> withRef "org" org
|
||||||
|
|> toResource "${org}_${name}"
|
||||||
|
)
|
||||||
|
|> append [
|
||||||
|
(forEach "local.extra_users" ["org" "name"] {
|
||||||
|
orgId = tfRef "local.orgs[each.value.org]";
|
||||||
|
userName = tfRef "each.value.name";
|
||||||
|
email = tfRef "each.value.email";
|
||||||
|
firstName = tfRef "each.value.firstName";
|
||||||
|
lastName = tfRef "each.value.lastName";
|
||||||
|
|
||||||
|
isEmailVerified = true;
|
||||||
|
}
|
||||||
|
|> toResource "extraUsers")
|
||||||
|
];
|
||||||
|
|
||||||
|
# Global user roles
|
||||||
|
zitadel_instance_member =
|
||||||
|
settings.organization
|
||||||
|
|> filterAttrsRecursive (n: v: !(v ? "instanceRoles" && (length v.instanceRoles) == 0))
|
||||||
|
|> select ["user"] (
|
||||||
|
org: name: {instanceRoles, ...}:
|
||||||
|
{roles = instanceRoles;}
|
||||||
|
|> withRef "user" "${org}_${name}"
|
||||||
|
|> toResource "${org}_${name}"
|
||||||
|
);
|
||||||
|
|
||||||
|
# Organazation specific roles
|
||||||
|
zitadel_org_member =
|
||||||
|
settings.organization
|
||||||
|
|> filterAttrsRecursive (n: v: !(v ? "roles" && (length v.roles) == 0))
|
||||||
|
|> select ["user"] (
|
||||||
|
org: name: {roles, ...}:
|
||||||
|
{inherit roles;}
|
||||||
|
|> withRef "org" org
|
||||||
|
|> withRef "user" "${org}_${name}"
|
||||||
|
|> toResource "${org}_${name}"
|
||||||
|
);
|
||||||
|
|
||||||
|
# Organazation's actions
|
||||||
|
zitadel_action =
|
||||||
|
settings.organization
|
||||||
|
|> select ["action"] (
|
||||||
|
org: name: {
|
||||||
|
timeout,
|
||||||
|
allowedToFail,
|
||||||
|
script,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
inherit allowedToFail name;
|
||||||
|
timeout = "${toString timeout}s";
|
||||||
|
script = "const ${name} = ${script}";
|
||||||
|
}
|
||||||
|
|> withRef "org" org
|
||||||
|
|> toResource "${org}_${name}"
|
||||||
|
);
|
||||||
|
|
||||||
|
# Organazation's action assignments
|
||||||
|
zitadel_trigger_actions =
|
||||||
|
settings.organization
|
||||||
|
|> concatMapAttrs (
|
||||||
|
org: {triggers, ...}:
|
||||||
|
triggers
|
||||||
|
|> imap0 (i: {
|
||||||
|
flowType,
|
||||||
|
triggerType,
|
||||||
|
actions,
|
||||||
|
...
|
||||||
|
}: (
|
||||||
|
let
|
||||||
|
name = "trigger_${toString i}";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
inherit flowType triggerType;
|
||||||
|
|
||||||
|
actionIds =
|
||||||
|
actions
|
||||||
|
|> map (action: (tfRef "zitadel_action.${org}_${toSnakeCase action}.id"));
|
||||||
|
}
|
||||||
|
|> withRef "org" org
|
||||||
|
|> toResource "${org}_${name}"
|
||||||
|
))
|
||||||
|
|> listToAttrs
|
||||||
|
);
|
||||||
|
|
||||||
|
# SMTP config
|
||||||
|
zitadel_smtp_config.default = {
|
||||||
|
sender_address = "chris@kruining.eu";
|
||||||
|
sender_name = "no-reply (Zitadel)";
|
||||||
|
tls = true;
|
||||||
|
host = "black-mail.nl:587";
|
||||||
|
user = "chris@kruining.eu";
|
||||||
|
password = tfRef "file(\"${email_password}\")";
|
||||||
|
set_active = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Client credentials per app
|
||||||
|
local_sensitive_file =
|
||||||
|
settings.organization
|
||||||
|
|> select ["project" "application"] (
|
||||||
|
org: project: name: {exportMap, ...}:
|
||||||
|
nameValuePair "${org}_${project}_${name}" {
|
||||||
|
content = ''
|
||||||
|
${
|
||||||
|
if exportMap.client_id != null
|
||||||
|
then exportMap.client_id
|
||||||
|
else "CLIENT_ID"
|
||||||
|
}=${tfRef "resource.zitadel_application_oidc.${org}_${project}_${name}.client_id"}
|
||||||
|
${
|
||||||
|
if exportMap.client_secret != null
|
||||||
|
then exportMap.client_secret
|
||||||
|
else "CLIENT_SECRET"
|
||||||
|
}=${tfRef "resource.zitadel_application_oidc.${org}_${project}_${name}.client_secret"}
|
||||||
|
'';
|
||||||
|
filename = "/var/lib/zitadel/clients/${org}_${project}_${name}";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
createInfra = args @ {...}: let
|
||||||
|
tofu = "${lib.getExe pkgs.opentofu} -input=false";
|
||||||
|
terraformConfiguration = self.inputs.terranix.lib.terranixConfiguration {
|
||||||
|
system = pkgs.stdenv.hostPlatform.system;
|
||||||
|
modules = [
|
||||||
|
(createTerranixModule args)
|
||||||
|
];
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
systemd.services."infra-zitadel" = {
|
||||||
|
description = "Infra for Zitadel";
|
||||||
|
|
||||||
|
wantedBy = ["multi-user.target"];
|
||||||
|
wants = ["zitadel.service"];
|
||||||
|
after = ["zitadel.service"];
|
||||||
|
|
||||||
|
preStart = ''
|
||||||
|
install -d -m 0770 -o zitadel -g media /var/lib/infra-zitadel
|
||||||
|
'';
|
||||||
|
|
||||||
|
script = ''
|
||||||
|
# Sleep for a bit to give the service a chance to start up
|
||||||
|
sleep 5s
|
||||||
|
|
||||||
|
if [ "$(systemctl is-active zitadel)" != "active" ]; then
|
||||||
|
echo "zitadel is not running"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Print the path to the source for easier debugging
|
||||||
|
echo "config location: ${terraformConfiguration}"
|
||||||
|
|
||||||
|
# Copy infra code into workspace
|
||||||
|
cp -f ${terraformConfiguration} config.tf.json
|
||||||
|
|
||||||
|
# Initialize OpenTofu
|
||||||
|
${tofu} init
|
||||||
|
|
||||||
|
# Run the infrastructure code
|
||||||
|
${tofu} plan -out=tfplan
|
||||||
|
${tofu} apply -json -auto-approve tfplan
|
||||||
|
'';
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
User = "zitadel";
|
||||||
|
Group = "zitadel";
|
||||||
|
|
||||||
|
StateDirectory = "/var/lib/infra-zitadel";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
0
clanServices/peristence/README.md
Normal file
0
clanServices/peristence/README.md
Normal file
169
clanServices/peristence/default.nix
Normal file
169
clanServices/peristence/default.nix
Normal file
|
|
@ -0,0 +1,169 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
clanLib,
|
||||||
|
exports,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (builtins) toString;
|
||||||
|
in {
|
||||||
|
_class = "clan.service";
|
||||||
|
manifest = {
|
||||||
|
name = "arda/persistence";
|
||||||
|
description = ''
|
||||||
|
Configuration of persistence resrouce(s)
|
||||||
|
(for now this means a database. and specifically it means postgres)
|
||||||
|
'';
|
||||||
|
readme = builtins.readFile ./README.md;
|
||||||
|
exports = {
|
||||||
|
inputs = ["persistence"];
|
||||||
|
out = ["persistence"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
roles.default = {
|
||||||
|
description = '''';
|
||||||
|
|
||||||
|
interface = {lib, ...}: let
|
||||||
|
inherit (lib) mkOption types;
|
||||||
|
in {
|
||||||
|
options = {
|
||||||
|
port = mkOption {
|
||||||
|
type = types.port;
|
||||||
|
default = 5432;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
perInstance = {
|
||||||
|
mkExports,
|
||||||
|
machine,
|
||||||
|
settings,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
requested_databases =
|
||||||
|
exports
|
||||||
|
|> clanLib.selectExports (_scope: true)
|
||||||
|
|> lib.mapAttrsToList (_: value: value.persistence.databases or [])
|
||||||
|
|> lib.concatLists;
|
||||||
|
in {
|
||||||
|
exports = mkExports {
|
||||||
|
persistence = {
|
||||||
|
main = "postgresql";
|
||||||
|
driver.postgresql = {
|
||||||
|
host = "localhost";
|
||||||
|
port = settings.port;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
nixosModule = {
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
config,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
clan.core.vars.generators.postgresql = let
|
||||||
|
password_files =
|
||||||
|
requested_databases
|
||||||
|
|> lib.map (db: [
|
||||||
|
{
|
||||||
|
name = "${db}_password";
|
||||||
|
value = {
|
||||||
|
secret = true;
|
||||||
|
deploy = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|> lib.concatLists
|
||||||
|
|> lib.listToAttrs;
|
||||||
|
in {
|
||||||
|
files =
|
||||||
|
{
|
||||||
|
"server.crt" = {
|
||||||
|
secret = true;
|
||||||
|
deploy = true;
|
||||||
|
};
|
||||||
|
"server.key" = {
|
||||||
|
secret = true;
|
||||||
|
deploy = true;
|
||||||
|
};
|
||||||
|
".pgpass" = {
|
||||||
|
secret = true;
|
||||||
|
deploy = true;
|
||||||
|
|
||||||
|
owner = "postgres";
|
||||||
|
group = "postgres";
|
||||||
|
mode = "0600";
|
||||||
|
restartUnits = ["postgresql.service"];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// password_files;
|
||||||
|
|
||||||
|
runtimeInputs = with pkgs; [openssl_3_5 pwgen];
|
||||||
|
script = ''
|
||||||
|
openssl req \
|
||||||
|
-new -x509 -days 365 -nodes -text \
|
||||||
|
-out $out/server.crt \
|
||||||
|
-keyout $out/server.key \
|
||||||
|
-subj "/CN=db.${config.networking.fqdn}"
|
||||||
|
|
||||||
|
${requested_databases
|
||||||
|
|> lib.map (db: "pwgen -s 128 1 > $out/${db}_password")
|
||||||
|
|> lib.join "\n"}
|
||||||
|
|
||||||
|
cat << EOL > $out/.pgpass
|
||||||
|
#host:port:database:user:password
|
||||||
|
${requested_databases
|
||||||
|
|> lib.map (db: "*:${toString settings.port}:${db}:${db}:$(cat $out/${db}_password)")
|
||||||
|
|> lib.join "\n"}
|
||||||
|
EOL
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.postgresql.environment.PGPASSFILE = config.clan.core.vars.generators.postgresql.files.".pgpass".path;
|
||||||
|
|
||||||
|
services = {
|
||||||
|
postgresql = {
|
||||||
|
enable = true;
|
||||||
|
# enableTCPIP = true;
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
port = settings.port;
|
||||||
|
ssl = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
ensureDatabases = requested_databases;
|
||||||
|
ensureUsers =
|
||||||
|
requested_databases
|
||||||
|
|> lib.map (db: {
|
||||||
|
name = db;
|
||||||
|
ensureDBOwnership = true;
|
||||||
|
ensureClauses = {
|
||||||
|
login = true;
|
||||||
|
connection_limit = 5;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
identMap = ''
|
||||||
|
#map sys user db user
|
||||||
|
superuser_map root postgres
|
||||||
|
superuser_map postgres postgres
|
||||||
|
superuser_map /^(.+)$ \1
|
||||||
|
'';
|
||||||
|
|
||||||
|
authentication = ''
|
||||||
|
# Generated file, do not edit!
|
||||||
|
# type database user auth-method optional_ident_map
|
||||||
|
local sameuser all peer map=superuser_map
|
||||||
|
|
||||||
|
# TYPE DATABASE USER ADDRESS METHOD
|
||||||
|
# local all all trust
|
||||||
|
host all all 127.0.0.1/32 scram-sha-256
|
||||||
|
host all all ::1/128 scram-sha-256
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
13
clanServices/peristence/flake-module.nix
Normal file
13
clanServices/peristence/flake-module.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
{...}: let
|
||||||
|
module = ./default.nix;
|
||||||
|
in {
|
||||||
|
clan.modules.persistence = module;
|
||||||
|
|
||||||
|
# perSystem = {...}: {
|
||||||
|
# clan.nixosTests.persistence = {
|
||||||
|
# imports = [];
|
||||||
|
|
||||||
|
# clan.modules."@arda/persistence" = module;
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
}
|
||||||
0
clanServices/servarr/README.md
Normal file
0
clanServices/servarr/README.md
Normal file
150
clanServices/servarr/default.nix
Normal file
150
clanServices/servarr/default.nix
Normal file
|
|
@ -0,0 +1,150 @@
|
||||||
|
{
|
||||||
|
exports,
|
||||||
|
clanLib,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (lib) toString;
|
||||||
|
in {
|
||||||
|
_class = "clan.service";
|
||||||
|
manifest = {
|
||||||
|
name = "arda/servarr";
|
||||||
|
description = '''';
|
||||||
|
categories = ["Service" "Media"];
|
||||||
|
readme = builtins.readFile ./README.md;
|
||||||
|
exports = {
|
||||||
|
inputs = ["persistence"];
|
||||||
|
out = ["gateway" "persistence"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
roles.default = {
|
||||||
|
description = '''';
|
||||||
|
|
||||||
|
interface = {lib, ...}: let
|
||||||
|
inherit (lib) mkOption mkEnableOption types;
|
||||||
|
in {
|
||||||
|
options = {
|
||||||
|
enable = mkEnableOption "Enable configured *arr services";
|
||||||
|
|
||||||
|
database = mkOption {
|
||||||
|
type = types.anything; #ardaLib.types.endpoint;
|
||||||
|
};
|
||||||
|
|
||||||
|
services = mkOption {
|
||||||
|
type = types.attrsOf (types.submodule ({name, ...}: {
|
||||||
|
options = {
|
||||||
|
enable = mkEnableOption "Enable ${name}" // {default = true;};
|
||||||
|
debug = mkEnableOption "Use tofu plan instead of tofu apply for ${name} ";
|
||||||
|
|
||||||
|
rootFolders = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
default = {};
|
||||||
|
description = ''
|
||||||
|
Settings foreach *arr service
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
perInstance = {
|
||||||
|
instanceName,
|
||||||
|
settings,
|
||||||
|
machine,
|
||||||
|
roles,
|
||||||
|
mkExports,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
exports = mkExports {
|
||||||
|
# endpoints.hosts =
|
||||||
|
# settings.services
|
||||||
|
# |> lib.attrNames
|
||||||
|
# |> (s: lib.concat s ["sabnzbd" "qbittorrent" "flaresolverr"])
|
||||||
|
# |> lib.map (service: "${service}.${machine.name}.arda");
|
||||||
|
|
||||||
|
persistence.databases =
|
||||||
|
settings.services
|
||||||
|
|> lib.attrNames;
|
||||||
|
|
||||||
|
gateway.services =
|
||||||
|
settings.services
|
||||||
|
|> lib.attrNames
|
||||||
|
# |> (s: lib.concat s ["sabnzbd" "qbittorrent" "flaresolverr"])
|
||||||
|
|> lib.imap1 (i: name: {
|
||||||
|
inherit name;
|
||||||
|
value = {
|
||||||
|
endpoint.port = 2000 + i;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|> lib.listToAttrs;
|
||||||
|
};
|
||||||
|
|
||||||
|
nixosModule = args @ {
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
services = settings.services |> lib.attrNames;
|
||||||
|
service_count = services |> lib.length;
|
||||||
|
|
||||||
|
servarr = import ./lib.nix (args // {inherit settings;});
|
||||||
|
in {
|
||||||
|
imports = [
|
||||||
|
(import ./sabnzbd.nix (args
|
||||||
|
// {
|
||||||
|
inherit settings;
|
||||||
|
port = 2000 + service_count + 1;
|
||||||
|
}))
|
||||||
|
(import ./qbittorrent.nix (args
|
||||||
|
// {
|
||||||
|
inherit settings;
|
||||||
|
port = 2000 + service_count + 2;
|
||||||
|
}))
|
||||||
|
(servarr.createModule settings.services)
|
||||||
|
];
|
||||||
|
|
||||||
|
config = {
|
||||||
|
clan.core.vars.generators.servarr = rec {
|
||||||
|
dependencies =
|
||||||
|
services ++ ["sabnzbd" "qbittorrent"];
|
||||||
|
|
||||||
|
files."config.tfvars" = {
|
||||||
|
owner = "media";
|
||||||
|
group = "media";
|
||||||
|
mode = "0440";
|
||||||
|
restartUnits = services |> lib.map (s: "${s}.service");
|
||||||
|
};
|
||||||
|
|
||||||
|
script = ''
|
||||||
|
cat << EOL > $out/config.tfvars
|
||||||
|
${
|
||||||
|
services
|
||||||
|
|> lib.map (s: "${s}_api_key = \"$(cat $in/${s}/api_key)\"")
|
||||||
|
|> lib.join "\n"
|
||||||
|
}
|
||||||
|
qbittorrent_api_key = "$(cat $in/qbittorrent/password)"
|
||||||
|
sabnzbd_api_key = "$(cat $in/sabnzbd/api_key)"
|
||||||
|
EOL
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
services = {
|
||||||
|
flaresolverr = {
|
||||||
|
enable = true;
|
||||||
|
openFirewall = true;
|
||||||
|
port = 2000 + service_count + 3;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
perMachine = {...}: {
|
||||||
|
};
|
||||||
|
}
|
||||||
13
clanServices/servarr/flake-module.nix
Normal file
13
clanServices/servarr/flake-module.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
{...}: let
|
||||||
|
module = ./default.nix;
|
||||||
|
in {
|
||||||
|
clan.modules.servarr = module;
|
||||||
|
|
||||||
|
# perSystem = {...}: {
|
||||||
|
# clan.nixosTests.servarr = {
|
||||||
|
# imports = [];
|
||||||
|
|
||||||
|
# clan.modules."@arda/servarr" = module;
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
}
|
||||||
329
clanServices/servarr/lib.nix
Normal file
329
clanServices/servarr/lib.nix
Normal file
|
|
@ -0,0 +1,329 @@
|
||||||
|
{
|
||||||
|
self,
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
settings,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (lib) mkIf;
|
||||||
|
|
||||||
|
createGenerator = {
|
||||||
|
service,
|
||||||
|
options,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
dependencies = ["postgresql"];
|
||||||
|
|
||||||
|
files = {
|
||||||
|
api_key = {
|
||||||
|
secret = true;
|
||||||
|
deploy = true;
|
||||||
|
owner = service;
|
||||||
|
group = "media";
|
||||||
|
restartUnits = ["${service}.service"];
|
||||||
|
};
|
||||||
|
"config.env" = {
|
||||||
|
secret = true;
|
||||||
|
deploy = true;
|
||||||
|
owner = service;
|
||||||
|
group = "media";
|
||||||
|
restartUnits = ["${service}.service"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
runtimeInputs = with pkgs; [pwgen];
|
||||||
|
script = ''
|
||||||
|
pwgen -s 128 1 > $out/api_key
|
||||||
|
cat << EOL > $out/config.env
|
||||||
|
${lib.toUpper service}__AUTH__APIKEY="$(cat $out/api_key)"
|
||||||
|
${lib.toUpper service}__POSTGRES_PASSWORD="$(cat $in/postgresql/${service}_password)"
|
||||||
|
EOL
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
createService = {
|
||||||
|
service,
|
||||||
|
options,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (builtins) toString;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
enable = true;
|
||||||
|
# openFirewall = true;
|
||||||
|
|
||||||
|
environmentFiles = [
|
||||||
|
config.clan.core.vars.generators.${service}.files."config.env".path
|
||||||
|
];
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
auth.authenticationMethod = "External";
|
||||||
|
|
||||||
|
server = {
|
||||||
|
bindaddress = "[::1]";
|
||||||
|
port = options.port;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Password provided via environment file
|
||||||
|
postgres = {
|
||||||
|
host = settings.database.host;
|
||||||
|
port = toString settings.database.port;
|
||||||
|
user = service;
|
||||||
|
maindb = service;
|
||||||
|
logdb = service;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// (lib.optionalAttrs (lib.elem service ["radarr" "sonarr" "lidarr" "whisparr"]) {
|
||||||
|
user = service;
|
||||||
|
group = "media";
|
||||||
|
});
|
||||||
|
|
||||||
|
createSystemdService = args @ {
|
||||||
|
service,
|
||||||
|
options,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
tofu = lib.getExe pkgs.opentofu;
|
||||||
|
terraformConfiguration = self.inputs.terranix.lib.terranixConfiguration {
|
||||||
|
system = pkgs.stdenv.hostPlatform.system;
|
||||||
|
modules = [
|
||||||
|
(createInfra args)
|
||||||
|
];
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
description = "${service} apply infra";
|
||||||
|
|
||||||
|
wantedBy = ["multi-user.target"];
|
||||||
|
wants = ["${service}.service"];
|
||||||
|
|
||||||
|
preStart = ''
|
||||||
|
install -d -m 0770 -o ${service} -g media /var/lib/infra-${service}
|
||||||
|
${
|
||||||
|
options.rootFolders
|
||||||
|
|> lib.map (folder: "install -d -m 0770 -o media -g media ${folder}")
|
||||||
|
|> lib.join "\n"
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
|
||||||
|
script = ''
|
||||||
|
# Sleep for a bit to give the service a chance to start up
|
||||||
|
sleep 5s
|
||||||
|
|
||||||
|
if [ "$(systemctl is-active ${lib.escapeShellArg service})" != "active" ]; then
|
||||||
|
echo "${service} is not running"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Print the path to the source for easier debugging
|
||||||
|
echo "config location: ${terraformConfiguration}"
|
||||||
|
|
||||||
|
# Copy infra code into workspace
|
||||||
|
cp -f ${terraformConfiguration} config.tf.json
|
||||||
|
|
||||||
|
# Initialize OpenTofu
|
||||||
|
${tofu} init
|
||||||
|
|
||||||
|
# Run the infrastructure code
|
||||||
|
${tofu} \
|
||||||
|
${
|
||||||
|
if options.debug
|
||||||
|
then "plan"
|
||||||
|
else "apply -auto-approve"
|
||||||
|
} \
|
||||||
|
-var-file='${config.clan.core.vars.generators.servarr.files."config.tfvars".path}'
|
||||||
|
'';
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
User = service;
|
||||||
|
Group = "media";
|
||||||
|
|
||||||
|
WorkingDirectory = "/var/lib/${service}-apply-infra";
|
||||||
|
|
||||||
|
EnvironmentFile = [
|
||||||
|
config.clan.core.vars.generators.${service}.files."config.env".path
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Returns a module to be used in a modules list of terranix
|
||||||
|
createInfra = {
|
||||||
|
service,
|
||||||
|
options,
|
||||||
|
...
|
||||||
|
}: terra: let
|
||||||
|
inherit (terra.lib) tfRef;
|
||||||
|
in {
|
||||||
|
variable = {
|
||||||
|
"${service}_api_key" = {
|
||||||
|
type = "string";
|
||||||
|
description = "${service} API key";
|
||||||
|
};
|
||||||
|
|
||||||
|
qbittorrent_api_key = {
|
||||||
|
type = "string";
|
||||||
|
description = "qbittorrent api key";
|
||||||
|
};
|
||||||
|
|
||||||
|
sabnzbd_api_key = {
|
||||||
|
type = "string";
|
||||||
|
description = "sabnzbd api key";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
terraform.required_providers.${service} = {
|
||||||
|
source = "devopsarr/${service}";
|
||||||
|
version =
|
||||||
|
{
|
||||||
|
radarr = "2.3.5";
|
||||||
|
sonarr = "3.4.2";
|
||||||
|
prowlarr = "3.2.1";
|
||||||
|
lidarr = "1.13.0";
|
||||||
|
readarr = "2.1.0";
|
||||||
|
whisparr = "1.2.0";
|
||||||
|
}.${
|
||||||
|
service
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
provider.${service} = {
|
||||||
|
url = "http://[::1]:${toString options.port}";
|
||||||
|
api_key = tfRef "var.${service}_api_key";
|
||||||
|
};
|
||||||
|
|
||||||
|
resource =
|
||||||
|
{
|
||||||
|
"${service}_root_folder" = mkIf (lib.elem service ["radarr" "sonarr" "whisparr" "readarr"]) (
|
||||||
|
options.rootFolders
|
||||||
|
|> lib.imap (i: f: lib.nameValuePair "local${toString i}" {path = f;})
|
||||||
|
|> lib.listToAttrs
|
||||||
|
);
|
||||||
|
|
||||||
|
"${service}_download_client_qbittorrent" = mkIf (lib.elem service ["radarr" "sonarr" "lidarr" "whisparr"]) {
|
||||||
|
"main" = {
|
||||||
|
name = "qBittorrent";
|
||||||
|
enable = true;
|
||||||
|
priority = 1;
|
||||||
|
host = "localhost";
|
||||||
|
username = "admin";
|
||||||
|
password = tfRef "var.qbittorrent_api_key";
|
||||||
|
url_base = "/";
|
||||||
|
port = config.services.qbittorrent.webuiPort;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
"${service}_download_client_sabnzbd" = mkIf (lib.elem service ["radarr" "sonarr" "lidarr" "whisparr"]) {
|
||||||
|
"main" = {
|
||||||
|
name = "SABnzbd";
|
||||||
|
enable = true;
|
||||||
|
priority = 1;
|
||||||
|
host = "localhost";
|
||||||
|
api_key = tfRef "var.sabnzbd_api_key";
|
||||||
|
url_base = "/";
|
||||||
|
port = config.services.sabnzbd.settings.misc.port;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// (lib.optionalAttrs (service == "prowlarr") (
|
||||||
|
settings.services
|
||||||
|
|> lib.filterAttrs (s: _: lib.elem s ["radarr" "sonarr" "lidarr" "whisparr"])
|
||||||
|
|> lib.mapAttrsToList (s: {port, ...}: {
|
||||||
|
"prowlarr_application_${s}"."main" = let
|
||||||
|
p = config.services.prowlarr.settings.server.port or 9696;
|
||||||
|
in {
|
||||||
|
name = s;
|
||||||
|
sync_level = "addOnly";
|
||||||
|
base_url = "http://localhost:${toString port}";
|
||||||
|
prowlarr_url = "http://localhost:${toString p}";
|
||||||
|
api_key = tfRef "var.${s}_api_key";
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|> lib.concat [
|
||||||
|
{
|
||||||
|
"prowlarr_indexer" = {
|
||||||
|
"nyaa" = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
app_profile_id = 1;
|
||||||
|
priority = 1;
|
||||||
|
|
||||||
|
name = "Nyaa";
|
||||||
|
implementation = "Cardigann";
|
||||||
|
config_contract = "CardigannSettings";
|
||||||
|
protocol = "torrent";
|
||||||
|
|
||||||
|
fields = [
|
||||||
|
{
|
||||||
|
name = "definitionFile";
|
||||||
|
text_value = "nyaasi";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "baseSettings.limitsUnit";
|
||||||
|
number_value = 0;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "torrentBaseSettings.preferMagnetUrl";
|
||||||
|
bool_value = false;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "prefer_magnet_links";
|
||||||
|
bool_value = true;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "sonarr_compatibility";
|
||||||
|
bool_value = false;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "strip_s01";
|
||||||
|
bool_value = false;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "radarr_compatibility";
|
||||||
|
bool_value = false;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "filter-id";
|
||||||
|
number_value = 0;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "cat-id";
|
||||||
|
number_value = 0;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "sort";
|
||||||
|
number_value = 0;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "type";
|
||||||
|
number_value = 1;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|> lib.mkMerge
|
||||||
|
));
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
createModule = services: args: {
|
||||||
|
config =
|
||||||
|
services
|
||||||
|
|> lib.attrsToList
|
||||||
|
|> lib.imap1 (i: {
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
}: let
|
||||||
|
service = name;
|
||||||
|
options = value // {port = 2000 + i;};
|
||||||
|
in {
|
||||||
|
clan.core.vars.generators.${service} = createGenerator (args // {inherit service options;});
|
||||||
|
services.${service} = createService (args // {inherit service options;});
|
||||||
|
|
||||||
|
systemd.services."infra-${service}" = lib.mkIf settings.enable (createSystemdService (args // {inherit service options;}));
|
||||||
|
})
|
||||||
|
|> lib.mkMerge;
|
||||||
|
};
|
||||||
|
}
|
||||||
96
clanServices/servarr/qbittorrent.nix
Normal file
96
clanServices/servarr/qbittorrent.nix
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
settings,
|
||||||
|
port,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
clan.core.vars.generators.qbittorrent = let
|
||||||
|
hash_password = pkgs.writers.writePython3 "hashPassword" {} ''
|
||||||
|
import base64
|
||||||
|
import hashlib
|
||||||
|
import sys
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
password = sys.argv[1]
|
||||||
|
salt = uuid.uuid4()
|
||||||
|
salt_bytes = salt.bytes
|
||||||
|
|
||||||
|
password = str.encode(password)
|
||||||
|
hashed_password = hashlib.pbkdf2_hmac(
|
||||||
|
"sha512",
|
||||||
|
password,
|
||||||
|
salt_bytes,
|
||||||
|
100000,
|
||||||
|
dklen=64
|
||||||
|
)
|
||||||
|
b64_salt = base64.b64encode(salt_bytes).decode("utf-8")
|
||||||
|
b64_password = base64.b64encode(hashed_password).decode("utf-8")
|
||||||
|
password_string = "@ByteArray({salt}:{password})".format(
|
||||||
|
salt=b64_salt, password=b64_password
|
||||||
|
)
|
||||||
|
print(password_string)
|
||||||
|
'';
|
||||||
|
in {
|
||||||
|
files = {
|
||||||
|
"password" = {
|
||||||
|
secret = true;
|
||||||
|
deploy = true;
|
||||||
|
};
|
||||||
|
"password_hash" = {
|
||||||
|
secret = true;
|
||||||
|
deploy = true;
|
||||||
|
};
|
||||||
|
"qBittorrent.conf" = {
|
||||||
|
secret = true;
|
||||||
|
deploy = true;
|
||||||
|
owner = "qbittorrent";
|
||||||
|
group = "media";
|
||||||
|
mode = "0660";
|
||||||
|
restartUnits = ["qbittorrent.service"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
runtimeInputs = with pkgs; [pwgen hash_password];
|
||||||
|
|
||||||
|
script = ''
|
||||||
|
pwgen -s 128 1 > $out/password
|
||||||
|
|
||||||
|
${hash_password} $(cat $out/password) > $out/password_hash
|
||||||
|
|
||||||
|
cat << EOF > $out/qBittorrent.conf
|
||||||
|
[LegalNotice]
|
||||||
|
Accepted=true
|
||||||
|
|
||||||
|
[Preferences]
|
||||||
|
WebUI\AlternativeUIEnabled=true
|
||||||
|
WebUI\RootFolder=${pkgs.vuetorrent}/share/vuetorrent
|
||||||
|
WebUI\Username=admin
|
||||||
|
WebUI\Password_PBKDF2=$(cat $out/password_hash)
|
||||||
|
EOF
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
system.activationScripts.qbittorrent-config = {
|
||||||
|
deps = lib.optional (!config.sops.useSystemdActivation) "setupSecrets";
|
||||||
|
# TODO: If sops-nix is switched to systemd activation, add a systemd unit
|
||||||
|
# for this install step that runs after sops-install-secrets.service,
|
||||||
|
# because this activation-script dependency only orders against setupSecrets.
|
||||||
|
text = ''
|
||||||
|
install -Dm0600 -o ${config.services.qbittorrent.user} -g ${config.services.qbittorrent.group} \
|
||||||
|
${config.clan.core.vars.generators.qbittorrent.files."qBittorrent.conf".path} \
|
||||||
|
${config.services.qbittorrent.profileDir}/qBittorrent/config/qBittorrent.conf
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
services.qbittorrent = {
|
||||||
|
enable = true;
|
||||||
|
openFirewall = true;
|
||||||
|
webuiPort = port;
|
||||||
|
serverConfig = lib.mkForce {};
|
||||||
|
|
||||||
|
user = "qbittorrent";
|
||||||
|
group = "media";
|
||||||
|
};
|
||||||
|
}
|
||||||
95
clanServices/servarr/sabnzbd.nix
Normal file
95
clanServices/servarr/sabnzbd.nix
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
settings,
|
||||||
|
port,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
clan.core.vars.generators.sabnzbd = {
|
||||||
|
files = {
|
||||||
|
"api_key" = {
|
||||||
|
secret = true;
|
||||||
|
deploy = true;
|
||||||
|
};
|
||||||
|
"nzb_key" = {
|
||||||
|
secret = true;
|
||||||
|
deploy = true;
|
||||||
|
};
|
||||||
|
"config.ini" = {
|
||||||
|
secret = true;
|
||||||
|
deploy = true;
|
||||||
|
owner = "sabnzbd";
|
||||||
|
group = "media";
|
||||||
|
mode = "0660";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
prompts = {
|
||||||
|
username = {
|
||||||
|
description = "usenet username";
|
||||||
|
type = "hidden";
|
||||||
|
persist = true;
|
||||||
|
};
|
||||||
|
password = {
|
||||||
|
description = "usenet password";
|
||||||
|
type = "hidden";
|
||||||
|
persist = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
runtimeInputs = with pkgs; [pwgen];
|
||||||
|
|
||||||
|
script = ''
|
||||||
|
pwgen -s 128 1 > $out/api_key
|
||||||
|
pwgen -s 128 1 > $out/nzb_key
|
||||||
|
|
||||||
|
cat << EOF > $out/config.ini
|
||||||
|
[misc]
|
||||||
|
api_key = $(cat $out/api_key)
|
||||||
|
nzb_key = $(cat $out/nzb_key)
|
||||||
|
|
||||||
|
[servers]
|
||||||
|
[[news.sunnyusenet.com]]
|
||||||
|
username = $(cat $prompts/username)
|
||||||
|
password = $(cat $prompts/password)
|
||||||
|
EOF
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
services.sabnzbd = {
|
||||||
|
enable = true;
|
||||||
|
openFirewall = true;
|
||||||
|
|
||||||
|
allowConfigWrite = false;
|
||||||
|
configFile = lib.mkForce null;
|
||||||
|
|
||||||
|
secretFiles = [
|
||||||
|
config.clan.core.vars.generators.sabnzbd.files."config.ini".path
|
||||||
|
];
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
misc = {
|
||||||
|
host = "0.0.0.0";
|
||||||
|
port = port;
|
||||||
|
host_whitelist = "${config.networking.hostName}";
|
||||||
|
|
||||||
|
download_dir = "/var/media/downloads/incomplete";
|
||||||
|
complete_dir = "/var/media/downloads/done";
|
||||||
|
};
|
||||||
|
|
||||||
|
servers = {
|
||||||
|
"news.sunnyusenet.com" = {
|
||||||
|
name = "news.sunnyusenet.com";
|
||||||
|
displayname = "news.sunnyusenet.com";
|
||||||
|
host = "news.sunnyusenet.com";
|
||||||
|
port = 563;
|
||||||
|
timeout = 60;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
user = "sabnzbd";
|
||||||
|
group = "media";
|
||||||
|
};
|
||||||
|
}
|
||||||
22
devShell.nix
Normal file
22
devShell.nix
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
inputs,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
perSystem = {pkgs, system, ...}: {
|
||||||
|
devShells.default = pkgs.mkShell {
|
||||||
|
packages = with pkgs; [
|
||||||
|
bash
|
||||||
|
sops
|
||||||
|
just
|
||||||
|
yq
|
||||||
|
pwgen
|
||||||
|
alejandra
|
||||||
|
nil
|
||||||
|
nixd
|
||||||
|
openssl
|
||||||
|
inputs.clan-core.packages.${system}.clan-cli
|
||||||
|
nix-output-monitor
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
125
docs/plans/mandos-wake-on-demand-build-host.md
Normal file
125
docs/plans/mandos-wake-on-demand-build-host.md
Normal file
|
|
@ -0,0 +1,125 @@
|
||||||
|
# Mandos as a wake-on-demand build host
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
Mandos is primarily an interactive living-room machine, but it is also a strong candidate for handling remote Nix builds when it is idle. The goal is to make that dual use practical without keeping the machine powered all the time.
|
||||||
|
|
||||||
|
## Current context
|
||||||
|
|
||||||
|
On `main`, Mandos is configured as an interactive gaming machine:
|
||||||
|
|
||||||
|
- `systems/x86_64-linux/mandos/default.nix`
|
||||||
|
- `sneeuwvlok.hardware.has.gpu.nvidia = true`
|
||||||
|
- `sneeuwvlok.hardware.has.audio = true`
|
||||||
|
- `sneeuwvlok.desktop.use = "gamescope"`
|
||||||
|
- `sneeuwvlok.application.steam.enable = true`
|
||||||
|
- `homes/x86_64-linux/chris@mandos/default.nix`
|
||||||
|
- user-facing application set for an interactive machine
|
||||||
|
|
||||||
|
This makes Mandos a poor fit for "always running random infrastructure", but a reasonable fit for "available for work when needed".
|
||||||
|
|
||||||
|
## Desired behavior
|
||||||
|
|
||||||
|
- Mandos remains an interactive machine first.
|
||||||
|
- Mandos can be used as a remote build worker when no one is actively using it.
|
||||||
|
- Mandos should not need to stay fully on all day just to be eligible for builds.
|
||||||
|
- Waking and idling down should be automatic enough that the machine can participate in builds without turning into a maintenance burden.
|
||||||
|
|
||||||
|
## Recommended model
|
||||||
|
|
||||||
|
### 1. Use wake-on-LAN as the activation mechanism
|
||||||
|
|
||||||
|
Mandos should support being awakened by another machine on the same LAN.
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
|
||||||
|
- BIOS or UEFI wake-on-LAN support enabled
|
||||||
|
- NixOS interface configuration enabling wake-on-LAN
|
||||||
|
- one low-power machine that is effectively always available to send wake requests
|
||||||
|
|
||||||
|
In this repo, `ulmo` is the obvious candidate to act as the coordinator, but the pattern should stay generic: one machine is always reachable, and one or more stronger machines can be woken on demand.
|
||||||
|
|
||||||
|
### 2. Prefer suspend-first over shutdown-first
|
||||||
|
|
||||||
|
There are two main power states worth considering:
|
||||||
|
|
||||||
|
- **Suspend on idle**
|
||||||
|
- faster resume
|
||||||
|
- generally better user experience
|
||||||
|
- often easier to make reliable for wake-on-LAN
|
||||||
|
- **Shutdown on idle**
|
||||||
|
- lowest power draw
|
||||||
|
- more fragile in practice because firmware support for wake from soft-off varies
|
||||||
|
- longer time to become available again
|
||||||
|
|
||||||
|
Recommended rollout order:
|
||||||
|
|
||||||
|
1. Prove the concept with suspend on idle.
|
||||||
|
2. Only consider full power-off later if the hardware and firmware behave reliably.
|
||||||
|
|
||||||
|
## 3. Add an explicit availability policy
|
||||||
|
|
||||||
|
The interesting lesson for tagging is not "Mandos should have a build tag". The interesting lesson is that some machines have a deliberate availability policy that affects how safely they can participate in automation.
|
||||||
|
|
||||||
|
A future host-level setting could encode this policy directly, for example:
|
||||||
|
|
||||||
|
- `always-on`
|
||||||
|
- `wake-on-demand`
|
||||||
|
- `manual`
|
||||||
|
|
||||||
|
That setting would be a better source for any computed operational tag than current workload or ad hoc tags.
|
||||||
|
|
||||||
|
## 4. Idle detection should be policy-driven
|
||||||
|
|
||||||
|
If Mandos becomes a build worker, idle shutdown or suspend should depend on signals such as:
|
||||||
|
|
||||||
|
- no local interactive session activity
|
||||||
|
- no active build job
|
||||||
|
- no long-running system task that should keep the machine awake
|
||||||
|
|
||||||
|
This should not be a blind timer that powers the machine down every X minutes regardless of context.
|
||||||
|
|
||||||
|
## 5. Build orchestration needs a coordinator
|
||||||
|
|
||||||
|
Wake-on-demand only works well if something else can wake the machine and wait for it to become reachable. In practice, this means:
|
||||||
|
|
||||||
|
- a coordinator sends the wake signal
|
||||||
|
- the build client retries until the machine is reachable
|
||||||
|
- the remote builder participates only after it is actually ready
|
||||||
|
|
||||||
|
The exact implementation can vary, but the architectural point is the same: a wakeable build worker is not self-sufficient.
|
||||||
|
|
||||||
|
## Risks and caveats
|
||||||
|
|
||||||
|
- Firmware wake support may be unreliable, especially from full shutdown.
|
||||||
|
- Build latency increases because wake and readiness checks take time.
|
||||||
|
- A machine that users expect to be immediately available should not surprise them with power-state transitions at awkward moments.
|
||||||
|
- Interactive workload detection matters; otherwise the machine will feel hostile as a living-room device.
|
||||||
|
|
||||||
|
## Recommendation
|
||||||
|
|
||||||
|
Treat the Mandos idea as a good pattern, but generalize it:
|
||||||
|
|
||||||
|
- some machines are **interactive**
|
||||||
|
- some machines are **wakeable on demand**
|
||||||
|
- some machines are suitable for **interruptible background work**
|
||||||
|
|
||||||
|
Those are more reusable concepts than "Mandos is the build server".
|
||||||
|
|
||||||
|
## Implications for the tag strategy
|
||||||
|
|
||||||
|
This investigation strengthens a small part of the `operational:*` space:
|
||||||
|
|
||||||
|
- `operational:availability:always-on`
|
||||||
|
- `operational:availability:wake-on-demand`
|
||||||
|
- `operational:workload:interruptible`
|
||||||
|
|
||||||
|
These should not be assigned by hand if they can instead be computed from explicit machine settings that describe availability policy.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- Clan inventory tags and dynamic tags docs: `https://clan.lol/docs/25.11/reference/options/clan_inventory`
|
||||||
|
- NixOS Wake-on-LAN wiki: `https://wiki.nixos.org/wiki/Wake_on_LAN`
|
||||||
|
- Home-lab wake-on-demand discussion and patterns:
|
||||||
|
- `https://dgross.ca/blog/linux-home-server-auto-sleep`
|
||||||
|
- `https://danielpgross.github.io/friendly_neighbor/howto-sleep-wake-on-demand.html`
|
||||||
235
docs/plans/tagging-strategy.md
Normal file
235
docs/plans/tagging-strategy.md
Normal file
|
|
@ -0,0 +1,235 @@
|
||||||
|
# Clan machine tagging strategy
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
Replace machine-name targeting with stable tags that survive machine renames, hardware reshuffles, and service moves.
|
||||||
|
|
||||||
|
The strategy should fit how this repo is evolving:
|
||||||
|
|
||||||
|
- machine tags should describe the machine
|
||||||
|
- service roles should describe service topology
|
||||||
|
- computed tags should be derived from machine settings or other explicit metadata, not from other tags
|
||||||
|
|
||||||
|
## Source material
|
||||||
|
|
||||||
|
This plan is based on:
|
||||||
|
|
||||||
|
- current Clan inventory in `clan.nix`
|
||||||
|
- current machine configs under `machines/*/configuration.nix`
|
||||||
|
- workload and module usage on `main` under:
|
||||||
|
- `systems/x86_64-linux/*/default.nix`
|
||||||
|
- `homes/x86_64-linux/chris@*/default.nix`
|
||||||
|
- Clan inventory tag and dynamic-tag documentation
|
||||||
|
|
||||||
|
## Guiding principles
|
||||||
|
|
||||||
|
### 1. Prefer capabilities over roles
|
||||||
|
|
||||||
|
A machine rarely has one permanent role. In this repo especially, a machine may be interactive, portable, build-capable, and temporarily host some service at the same time.
|
||||||
|
|
||||||
|
Because of that, tags should describe durable traits and capabilities rather than trying to answer "what is this machine?"
|
||||||
|
|
||||||
|
### 2. Do not encode current workload as a machine tag
|
||||||
|
|
||||||
|
A machine currently running Grafana, Jellyfin, or PostgreSQL does not mean that those should become machine tags. Those are current placements, not stable identity.
|
||||||
|
|
||||||
|
If a service can move, its current presence is weak evidence for tagging.
|
||||||
|
|
||||||
|
### 3. Use service roles for topology
|
||||||
|
|
||||||
|
Some relationships belong in service definitions rather than host tags.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
- NFS producer and consumer
|
||||||
|
- persistence provider and client
|
||||||
|
- reverse proxy frontend and backend
|
||||||
|
|
||||||
|
These are not machine identity tags; they are service-topology relationships.
|
||||||
|
|
||||||
|
### 4. Derive tags from settings when possible
|
||||||
|
|
||||||
|
If a machine setting already captures a fact, derive the tag from that setting instead of duplicating it by hand.
|
||||||
|
|
||||||
|
Good examples in this repo:
|
||||||
|
|
||||||
|
- `desktop.use` can imply whether a machine is interactive
|
||||||
|
- `hardware.has.gpu.*` can imply GPU availability
|
||||||
|
- `hardware.has.audio` can imply audio capability
|
||||||
|
- `hardware.has.bluetooth` can imply Bluetooth capability
|
||||||
|
|
||||||
|
### 5. Avoid deriving tags from other tags
|
||||||
|
|
||||||
|
Clan supports dynamic tags, but tag-from-tag derivation can become fragile and can even recurse. If tags need computation, compute them from machine settings or an explicit metadata source instead.
|
||||||
|
|
||||||
|
## Proposed namespaces
|
||||||
|
|
||||||
|
Use full words:
|
||||||
|
|
||||||
|
- `capability:*`
|
||||||
|
- `operational:*`
|
||||||
|
|
||||||
|
The intention is:
|
||||||
|
|
||||||
|
- `capability:*` describes stable machine traits
|
||||||
|
- `operational:*` describes automation-relevant policy or availability behavior
|
||||||
|
|
||||||
|
## Tag catalog
|
||||||
|
|
||||||
|
This is the current list of tags discussed so far, grouped by status.
|
||||||
|
|
||||||
|
### Agreed capability tags
|
||||||
|
|
||||||
|
- `capability:runtime:interactive`
|
||||||
|
- `capability:runtime:headless`
|
||||||
|
- `capability:hardware:gpu`
|
||||||
|
- `capability:hardware:audio`
|
||||||
|
- `capability:hardware:bluetooth`
|
||||||
|
- `capability:mobility:portable`
|
||||||
|
- `capability:mobility:stationary`
|
||||||
|
|
||||||
|
### Agreed operational tags
|
||||||
|
|
||||||
|
- `operational:availability:always-on`
|
||||||
|
- `operational:availability:wake-on-demand`
|
||||||
|
- `operational:availability:manual`
|
||||||
|
- `operational:workload:interruptible`
|
||||||
|
|
||||||
|
### Explicitly rejected or deferred
|
||||||
|
|
||||||
|
- GPU vendor-specific tags such as AMD- or NVIDIA-specific variants
|
||||||
|
- service-presence tags such as Jellyfin, Grafana, Forgejo, or PostgreSQL
|
||||||
|
- service-topology tags such as NFS producer or consumer
|
||||||
|
- application-presence tags such as Discord or TeamSpeak
|
||||||
|
- desktop-environment tags such as Plasma or Gamescope
|
||||||
|
- location tags such as "living room" unless location later becomes a deliberate scheduling dimension
|
||||||
|
|
||||||
|
## Current static tags in `clan.nix`
|
||||||
|
|
||||||
|
These are the manually assigned tags currently present in the inventory. Settings-derived tags are intentionally not listed here because they are meant to be computed rather than maintained by hand.
|
||||||
|
|
||||||
|
- `mandos`
|
||||||
|
- `capability:mobility:stationary`
|
||||||
|
- `operational:availability:wake-on-demand`
|
||||||
|
- `manwe`
|
||||||
|
- `capability:mobility:stationary`
|
||||||
|
- `operational:availability:manual`
|
||||||
|
- `orome`
|
||||||
|
- `capability:mobility:portable`
|
||||||
|
- `operational:availability:manual`
|
||||||
|
- `tulkas`
|
||||||
|
- `capability:mobility:portable`
|
||||||
|
- `operational:availability:manual`
|
||||||
|
- `ulmo`
|
||||||
|
- `capability:mobility:stationary`
|
||||||
|
- `operational:availability:always-on`
|
||||||
|
|
||||||
|
## Capability tags
|
||||||
|
|
||||||
|
These are the strongest candidates for machine tags.
|
||||||
|
|
||||||
|
### Runtime
|
||||||
|
|
||||||
|
- `capability:runtime:interactive`
|
||||||
|
- `capability:runtime:headless`
|
||||||
|
|
||||||
|
These are directly useful for deciding where a service with a user-facing local experience does or does not belong.
|
||||||
|
|
||||||
|
### Hardware
|
||||||
|
|
||||||
|
- `capability:hardware:gpu`
|
||||||
|
- `capability:hardware:audio`
|
||||||
|
- `capability:hardware:bluetooth`
|
||||||
|
|
||||||
|
At the moment, the repo provides enough configuration structure to derive these from machine settings.
|
||||||
|
|
||||||
|
GPU vendor-specific tags are intentionally excluded for now. The current conclusion is that the presence of GPU hardware may matter, but the vendor usually does not unless there is a specific workload that depends on CUDA, ROCm, or a similar stack.
|
||||||
|
|
||||||
|
### Mobility
|
||||||
|
|
||||||
|
- `capability:mobility:portable`
|
||||||
|
- `capability:mobility:stationary`
|
||||||
|
|
||||||
|
These are useful concepts, but they are not currently obvious from one uniform machine setting in the repo. If they become desirable, they likely need either:
|
||||||
|
|
||||||
|
- an explicit machine setting, or
|
||||||
|
- a stronger convention around machine form factor
|
||||||
|
|
||||||
|
For now they are candidates, not automatic defaults.
|
||||||
|
|
||||||
|
## Operational tags
|
||||||
|
|
||||||
|
Operational tags are weaker than capability tags and should stay small in number.
|
||||||
|
|
||||||
|
They should only exist when they capture real automation constraints that are not already represented elsewhere.
|
||||||
|
|
||||||
|
### Availability
|
||||||
|
|
||||||
|
- `operational:availability:always-on`
|
||||||
|
- `operational:availability:wake-on-demand`
|
||||||
|
- `operational:availability:manual`
|
||||||
|
|
||||||
|
This dimension became clearer while thinking through the Mandos build-host idea. A machine may be technically capable of a workload, while its availability policy determines whether it is a sensible target.
|
||||||
|
|
||||||
|
These tags should not be guessed from existing workloads. They should come from an explicit machine setting that states the intended availability policy.
|
||||||
|
|
||||||
|
### Interruptibility
|
||||||
|
|
||||||
|
- `operational:workload:interruptible`
|
||||||
|
|
||||||
|
This is not about the machine by itself. It is a useful policy boundary for selecting machines that may host work that can be delayed, retried, paused, or moved.
|
||||||
|
|
||||||
|
If introduced, it should again come from explicit machine policy rather than being inferred from current services.
|
||||||
|
|
||||||
|
## What should not become machine tags
|
||||||
|
|
||||||
|
- current service assignments, such as Jellyfin, Grafana, Forgejo, or PostgreSQL
|
||||||
|
- service topology, such as NFS producer or consumer
|
||||||
|
- user application presence, such as Discord or TeamSpeak
|
||||||
|
- detailed desktop-environment choice, such as Plasma or Gamescope
|
||||||
|
- one-off descriptions like "living room" unless location becomes a deliberate scheduling dimension
|
||||||
|
|
||||||
|
## What is derivable today
|
||||||
|
|
||||||
|
The repo already contains enough structure to derive several useful capability tags.
|
||||||
|
|
||||||
|
Examples from the current configuration style:
|
||||||
|
|
||||||
|
- if a machine enables a desktop session, derive `capability:runtime:interactive`
|
||||||
|
- if a machine does not, derive `capability:runtime:headless`
|
||||||
|
- if a machine enables `hardware.has.audio`, derive `capability:hardware:audio`
|
||||||
|
- if a machine enables `hardware.has.bluetooth`, derive `capability:hardware:bluetooth`
|
||||||
|
- if a machine enables any `hardware.has.gpu.*`, derive `capability:hardware:gpu`
|
||||||
|
|
||||||
|
## What probably needs explicit policy
|
||||||
|
|
||||||
|
These should not be inferred from current services or tag combinations:
|
||||||
|
|
||||||
|
- `operational:availability:*`
|
||||||
|
- `operational:workload:interruptible`
|
||||||
|
- mobility-related tags if there is no explicit machine setting to derive them from
|
||||||
|
|
||||||
|
The clean way to support these is to introduce one or more explicit machine settings whose purpose is to describe machine policy rather than workload.
|
||||||
|
|
||||||
|
## Mandos update
|
||||||
|
|
||||||
|
The Mandos wake-on-demand build-host idea adds an important refinement:
|
||||||
|
|
||||||
|
- some machines should be eligible for background work only when they are available through a specific policy, such as wake-on-demand
|
||||||
|
|
||||||
|
This does **not** mean Mandos should get a hand-maintained "build server" tag.
|
||||||
|
|
||||||
|
It instead suggests a more generic pattern:
|
||||||
|
|
||||||
|
- a machine may be interactive
|
||||||
|
- a machine may be available on demand rather than always on
|
||||||
|
- that availability policy may influence whether certain classes of automation should target it
|
||||||
|
|
||||||
|
That strengthens the case for a very small `operational:*` namespace derived from explicit machine policy.
|
||||||
|
|
||||||
|
## Recommended next steps
|
||||||
|
|
||||||
|
1. Start with `capability:*` tags that are clearly derivable from machine settings.
|
||||||
|
2. Keep service topology in service roles instead of machine tags.
|
||||||
|
3. If availability policy becomes important, add an explicit machine setting for it and derive `operational:*` tags from that setting.
|
||||||
|
4. Avoid expanding the tag vocabulary until there is a clear service-selection use case for each added tag.
|
||||||
512
flake.lock
generated
512
flake.lock
generated
|
|
@ -71,15 +71,23 @@
|
||||||
"clan-core": {
|
"clan-core": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"data-mesher": "data-mesher",
|
"data-mesher": "data-mesher",
|
||||||
"disko": "disko",
|
"disko": [
|
||||||
"flake-parts": "flake-parts",
|
"disko"
|
||||||
|
],
|
||||||
|
"flake-parts": [
|
||||||
|
"flake-parts"
|
||||||
|
],
|
||||||
"nix-darwin": "nix-darwin",
|
"nix-darwin": "nix-darwin",
|
||||||
"nix-select": "nix-select",
|
"nix-select": "nix-select",
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
],
|
],
|
||||||
"sops-nix": "sops-nix",
|
"sops-nix": [
|
||||||
"systems": "systems",
|
"sops-nix"
|
||||||
|
],
|
||||||
|
"systems": [
|
||||||
|
"systems"
|
||||||
|
],
|
||||||
"treefmt-nix": "treefmt-nix"
|
"treefmt-nix": "treefmt-nix"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
|
|
@ -139,7 +147,6 @@
|
||||||
"disko": {
|
"disko": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"clan-core",
|
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -184,11 +191,11 @@
|
||||||
"rust-analyzer-src": "rust-analyzer-src"
|
"rust-analyzer-src": "rust-analyzer-src"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1774250935,
|
"lastModified": 1774423251,
|
||||||
"narHash": "sha256-mWID0WFgTnd9hbEeaPNX+YYWF70JN3r7zBouEqERJOE=",
|
"narHash": "sha256-g/PP8G9WcP4vtZVOBNYwfGxLnwLQoTERHnef8irAMeQ=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "fenix",
|
"repo": "fenix",
|
||||||
"rev": "64d7705e8c37d650cfb1aa99c24a8ce46597f29e",
|
"rev": "b70d7535088cd8a9e4322c372a475f66ffa18adf",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -197,26 +204,6 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"firefox": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-compat": "flake-compat_2",
|
|
||||||
"lib-aggregate": "lib-aggregate",
|
|
||||||
"nixpkgs": "nixpkgs_2"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1774141843,
|
|
||||||
"narHash": "sha256-gpjHyyfLvBLZQiWumOxsfsOxt6KTjNhUOXk+m9ISBHc=",
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "flake-firefox-nightly",
|
|
||||||
"rev": "3a1fcd6a4dbd617ad2014dd03aa68cdd885d5322",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "flake-firefox-nightly",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"firefox-gnome-theme": {
|
"firefox-gnome-theme": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
|
|
@ -250,21 +237,6 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-compat_2": {
|
"flake-compat_2": {
|
||||||
"locked": {
|
|
||||||
"lastModified": 1761640442,
|
|
||||||
"narHash": "sha256-AtrEP6Jmdvrqiv4x2xa5mrtaIp3OEe8uBYCDZDS+hu8=",
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"rev": "4a56054d8ffc173222d09dad23adf4ba946c8884",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-compat_3": {
|
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1747046372,
|
"lastModified": 1747046372,
|
||||||
|
|
@ -280,7 +252,7 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-compat_4": {
|
"flake-compat_3": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1751685974,
|
"lastModified": 1751685974,
|
||||||
|
|
@ -296,26 +268,9 @@
|
||||||
"url": "https://git.lix.systems/lix-project/flake-compat.git"
|
"url": "https://git.lix.systems/lix-project/flake-compat.git"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-compat_5": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1650374568,
|
|
||||||
"narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=",
|
|
||||||
"owner": "edolstra",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"rev": "b4a34015c698c7793d592d66adbab377907a2be8",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "edolstra",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-parts": {
|
"flake-parts": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs-lib": [
|
"nixpkgs-lib": [
|
||||||
"clan-core",
|
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -396,86 +351,10 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-parts_5": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs-lib": [
|
|
||||||
"terranix",
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1736143030,
|
|
||||||
"narHash": "sha256-+hu54pAoLDEZT9pjHlqL9DNzWz0NbUn8NEAHP7PQPzU=",
|
|
||||||
"owner": "hercules-ci",
|
|
||||||
"repo": "flake-parts",
|
|
||||||
"rev": "b905f6fc23a9051a6e1b741e1438dbfc0634c6de",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "hercules-ci",
|
|
||||||
"repo": "flake-parts",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-utils": {
|
|
||||||
"inputs": {
|
|
||||||
"systems": "systems_2"
|
|
||||||
},
|
|
||||||
"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-plus": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-utils": "flake-utils_2"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1715533576,
|
|
||||||
"narHash": "sha256-fT4ppWeCJ0uR300EH3i7kmgRZnAVxrH+XtK09jQWihk=",
|
|
||||||
"owner": "gytis-ivaskevicius",
|
|
||||||
"repo": "flake-utils-plus",
|
|
||||||
"rev": "3542fe9126dc492e53ddd252bb0260fe035f2c0f",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "gytis-ivaskevicius",
|
|
||||||
"repo": "flake-utils-plus",
|
|
||||||
"rev": "3542fe9126dc492e53ddd252bb0260fe035f2c0f",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-utils_2": {
|
|
||||||
"inputs": {
|
|
||||||
"systems": "systems_5"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1694529238,
|
|
||||||
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flux": {
|
"flux": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"mcman": "mcman",
|
"mcman": "mcman",
|
||||||
"nixpkgs": "nixpkgs_4"
|
"nixpkgs": "nixpkgs_3"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1767316901,
|
"lastModified": 1767316901,
|
||||||
|
|
@ -528,7 +407,7 @@
|
||||||
},
|
},
|
||||||
"grub2-themes": {
|
"grub2-themes": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": "nixpkgs_5"
|
"nixpkgs": "nixpkgs_4"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1757136219,
|
"lastModified": 1757136219,
|
||||||
|
|
@ -551,11 +430,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1773992301,
|
"lastModified": 1774387289,
|
||||||
"narHash": "sha256-lm1qy9P463cblBAFC2g8VaALR1Gje1oyYXCPtiEumus=",
|
"narHash": "sha256-Z/0IfVHrb0lEdv1WcHEe/ni4utBMR2GXZIktzYcTDSU=",
|
||||||
"owner": "himmelblau-idm",
|
"owner": "himmelblau-idm",
|
||||||
"repo": "himmelblau",
|
"repo": "himmelblau",
|
||||||
"rev": "fcb8966990c24f97fe224fa0c8977fe730d4cf50",
|
"rev": "b2eccc7cb188253e49bffdddd743d01f52ab9625",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -571,11 +450,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1774210133,
|
"lastModified": 1774379316,
|
||||||
"narHash": "sha256-yeiWCY9aAUUJ3ebMVjs0UZXRnT5x90MCtpbpOWiXrvM=",
|
"narHash": "sha256-0nGNxWDUH2Hzlj/R3Zf4FEK6fsFNB/dvewuboSRZqiI=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "home-manager",
|
"repo": "home-manager",
|
||||||
"rev": "c6fe2944ad9f2444b2d767c4a5edee7c166e8a95",
|
"rev": "1eb0549a1ab3fe3f5acf86668249be15fa0e64f7",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -605,6 +484,21 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"import-tree": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1773693634,
|
||||||
|
"narHash": "sha256-BtZ2dtkBdSUnFPPFc+n0kcMbgaTxzFNPv2iaO326Ffg=",
|
||||||
|
"owner": "vic",
|
||||||
|
"repo": "import-tree",
|
||||||
|
"rev": "c41e7d58045f9057880b0d85e1152d6a4430dbf1",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "vic",
|
||||||
|
"repo": "import-tree",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"jovian": {
|
"jovian": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nix-github-actions": "nix-github-actions",
|
"nix-github-actions": "nix-github-actions",
|
||||||
|
|
@ -613,11 +507,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1774168156,
|
"lastModified": 1774333446,
|
||||||
"narHash": "sha256-+pwZSARdlM2RQQ6V0q76+WMKW9aNIcxkSOIThcz/f0A=",
|
"narHash": "sha256-jeAUd4mfLle7Zw8F3lDdXvw2cmeP3FgVphHq2XuEKbs=",
|
||||||
"owner": "Jovian-Experiments",
|
"owner": "Jovian-Experiments",
|
||||||
"repo": "Jovian-NixOS",
|
"repo": "Jovian-NixOS",
|
||||||
"rev": "939caad56508542d0f19cab963e2bc693f5f2831",
|
"rev": "79b45622eff2ae0437d7a712610044bbc7b87fa2",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -626,29 +520,10 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lib-aggregate": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-utils": "flake-utils",
|
|
||||||
"nixpkgs-lib": "nixpkgs-lib"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1773579712,
|
|
||||||
"narHash": "sha256-cvxFTYuOvvmpLJz5nB8iREmMGsDksY6gmZFf74UKD1Q=",
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "lib-aggregate",
|
|
||||||
"rev": "c23c52797845b8e4f273ddb5ccdf8622b5d98284",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "lib-aggregate",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"mcman": {
|
"mcman": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"crane": "crane",
|
"crane": "crane",
|
||||||
"nixpkgs": "nixpkgs_3"
|
"nixpkgs": "nixpkgs_2"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1766962671,
|
"lastModified": 1766962671,
|
||||||
|
|
@ -682,7 +557,7 @@
|
||||||
"mydia": {
|
"mydia": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-parts": "flake-parts_2",
|
"flake-parts": "flake-parts_2",
|
||||||
"nixpkgs": "nixpkgs_6"
|
"nixpkgs": "nixpkgs_5"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1764866402,
|
"lastModified": 1764866402,
|
||||||
|
|
@ -765,16 +640,16 @@
|
||||||
},
|
},
|
||||||
"nix-minecraft": {
|
"nix-minecraft": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-compat": "flake-compat_3",
|
"flake-compat": "flake-compat_2",
|
||||||
"nixpkgs": "nixpkgs_7",
|
"nixpkgs": "nixpkgs_6",
|
||||||
"systems": "systems_3"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1774060651,
|
"lastModified": 1774407052,
|
||||||
"narHash": "sha256-sZiam+rmNcOZGnlbnqDD9oTwfMdQUM+uQmFqqSoe194=",
|
"narHash": "sha256-rUkn7Bo3PAlpcZl8+0FDsTwFyDwvS4xwMT9+RJ+XJoE=",
|
||||||
"owner": "Infinidoge",
|
"owner": "Infinidoge",
|
||||||
"repo": "nix-minecraft",
|
"repo": "nix-minecraft",
|
||||||
"rev": "46727bd27d32d63069ed26a690554373ae2b4702",
|
"rev": "70daf1f48885f0b4a70797076cd2ff5d9139b46e",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -796,78 +671,6 @@
|
||||||
"url": "https://git.clan.lol/clan/nix-select/archive/main.tar.gz"
|
"url": "https://git.clan.lol/clan/nix-select/archive/main.tar.gz"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixlib": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1736643958,
|
|
||||||
"narHash": "sha256-tmpqTSWVRJVhpvfSN9KXBvKEXplrwKnSZNAoNPf/S/s=",
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "nixpkgs.lib",
|
|
||||||
"rev": "1418bc28a52126761c02dd3d89b2d8ca0f521181",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "nixpkgs.lib",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixos-boot": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1722927293,
|
|
||||||
"narHash": "sha256-8oCsiFyAuidAdhSz60Lu8+TwCPHxaeWixyv0xT0mLt4=",
|
|
||||||
"owner": "Melkor333",
|
|
||||||
"repo": "nixos-boot",
|
|
||||||
"rev": "afaed735149d0a06f234e54dd2d9db2e18dc64ae",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "Melkor333",
|
|
||||||
"repo": "nixos-boot",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixos-generators": {
|
|
||||||
"inputs": {
|
|
||||||
"nixlib": "nixlib",
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1769813415,
|
|
||||||
"narHash": "sha256-nnVmNNKBi1YiBNPhKclNYDORoHkuKipoz7EtVnXO50A=",
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "nixos-generators",
|
|
||||||
"rev": "8946737ff703382fda7623b9fab071d037e897d5",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "nixos-generators",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixos-wsl": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-compat": [],
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1773882647,
|
|
||||||
"narHash": "sha256-VzcOcE0LLpEnyoxLuMuptZ9ZWCkSBn99bTgEQoz5Viw=",
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "nixos-wsl",
|
|
||||||
"rev": "fd0eae98d1ecee31024271f8d64676250a386ee7",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "nixos-wsl",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1772380631,
|
"lastModified": 1772380631,
|
||||||
|
|
@ -884,38 +687,7 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs-lib": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1773538553,
|
|
||||||
"narHash": "sha256-hohiyWALn8cXqk3FPnE3UADy03lRMaTV5iRzKCU86zM=",
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "nixpkgs.lib",
|
|
||||||
"rev": "a5ed666a3c206de0019b4c9dafc3a51f352bc7e3",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "nixpkgs.lib",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs_10": {
|
"nixpkgs_10": {
|
||||||
"locked": {
|
|
||||||
"lastModified": 1773840656,
|
|
||||||
"narHash": "sha256-9tpvMGFteZnd3gRQZFlRCohVpqooygFuy9yjuyRL2C0=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "9cf7092bdd603554bd8b63c216e8943cf9b12512",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixpkgs-unstable",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs_11": {
|
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1767767207,
|
"lastModified": 1767767207,
|
||||||
"narHash": "sha256-Mj3d3PfwltLmukFal5i3fFt27L6NiKXdBezC1EBuZs4=",
|
"narHash": "sha256-Mj3d3PfwltLmukFal5i3fFt27L6NiKXdBezC1EBuZs4=",
|
||||||
|
|
@ -932,22 +704,6 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
|
||||||
"lastModified": 1774106199,
|
|
||||||
"narHash": "sha256-US5Tda2sKmjrg2lNHQL3jRQ6p96cgfWh3J1QBliQ8Ws=",
|
|
||||||
"owner": "nixos",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "6c9a78c09ff4d6c21d0319114873508a6ec01655",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nixos",
|
|
||||||
"ref": "nixos-unstable-small",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs_3": {
|
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1757347588,
|
"lastModified": 1757347588,
|
||||||
"narHash": "sha256-tLdkkC6XnsY9EOZW9TlpesTclELy8W7lL2ClL+nma8o=",
|
"narHash": "sha256-tLdkkC6XnsY9EOZW9TlpesTclELy8W7lL2ClL+nma8o=",
|
||||||
|
|
@ -962,7 +718,7 @@
|
||||||
"type": "indirect"
|
"type": "indirect"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_4": {
|
"nixpkgs_3": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1766902085,
|
"lastModified": 1766902085,
|
||||||
"narHash": "sha256-coBu0ONtFzlwwVBzmjacUQwj3G+lybcZ1oeNSQkgC0M=",
|
"narHash": "sha256-coBu0ONtFzlwwVBzmjacUQwj3G+lybcZ1oeNSQkgC0M=",
|
||||||
|
|
@ -978,13 +734,13 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_5": {
|
"nixpkgs_4": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1774259547,
|
"lastModified": 1774449288,
|
||||||
"narHash": "sha256-5EQ1TL+R/tcsoGas1oALp5Tj2ACfSul+pfrrxP72xC0=",
|
"narHash": "sha256-ukB6NS45Oi62fQM4RpZfx3dpqxIu66ADCCFl6h72Fjo=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "b3f8d82c4c685fb6f3080745dab8f07606ae50d3",
|
"rev": "cd0256cd8c537170cf24827fa821efb57aed9f40",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -994,7 +750,7 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_6": {
|
"nixpkgs_5": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1764242076,
|
"lastModified": 1764242076,
|
||||||
"narHash": "sha256-sKoIWfnijJ0+9e4wRvIgm/HgE27bzwQxcEmo2J/gNpI=",
|
"narHash": "sha256-sKoIWfnijJ0+9e4wRvIgm/HgE27bzwQxcEmo2J/gNpI=",
|
||||||
|
|
@ -1010,7 +766,7 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_7": {
|
"nixpkgs_6": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1769461804,
|
"lastModified": 1769461804,
|
||||||
"narHash": "sha256-msG8SU5WsBUfVVa/9RPLaymvi5bI8edTavbIq3vRlhI=",
|
"narHash": "sha256-msG8SU5WsBUfVVa/9RPLaymvi5bI8edTavbIq3vRlhI=",
|
||||||
|
|
@ -1026,13 +782,13 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_8": {
|
"nixpkgs_7": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1774106199,
|
"lastModified": 1774386573,
|
||||||
"narHash": "sha256-US5Tda2sKmjrg2lNHQL3jRQ6p96cgfWh3J1QBliQ8Ws=",
|
"narHash": "sha256-4hAV26quOxdC6iyG7kYaZcM3VOskcPUrdCQd/nx8obc=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "6c9a78c09ff4d6c21d0319114873508a6ec01655",
|
"rev": "46db2e09e1d3f113a13c0d7b81e2f221c63b8ce9",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -1042,7 +798,7 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_9": {
|
"nixpkgs_8": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1771008912,
|
"lastModified": 1771008912,
|
||||||
"narHash": "sha256-gf2AmWVTs8lEq7z/3ZAsgnZDhWIckkb+ZnAo5RzSxJg=",
|
"narHash": "sha256-gf2AmWVTs8lEq7z/3ZAsgnZDhWIckkb+ZnAo5RzSxJg=",
|
||||||
|
|
@ -1058,6 +814,22 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"nixpkgs_9": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1773840656,
|
||||||
|
"narHash": "sha256-9tpvMGFteZnd3gRQZFlRCohVpqooygFuy9yjuyRL2C0=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "9cf7092bdd603554bd8b63c216e8943cf9b12512",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixpkgs-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nur": {
|
"nur": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-parts": [
|
"flake-parts": [
|
||||||
|
|
@ -1085,19 +857,19 @@
|
||||||
},
|
},
|
||||||
"nvf": {
|
"nvf": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-compat": "flake-compat_4",
|
"flake-compat": "flake-compat_3",
|
||||||
"flake-parts": "flake-parts_3",
|
"flake-parts": "flake-parts_3",
|
||||||
"mnw": "mnw",
|
"mnw": "mnw",
|
||||||
"ndg": "ndg",
|
"ndg": "ndg",
|
||||||
"nixpkgs": "nixpkgs_9",
|
"nixpkgs": "nixpkgs_8",
|
||||||
"systems": "systems_4"
|
"systems": "systems_2"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1774224548,
|
"lastModified": 1774375131,
|
||||||
"narHash": "sha256-g45WZAZHNc7wJBkK4IdB5dq0Bh0JE7G0gcY2H5DFi44=",
|
"narHash": "sha256-d22VIgsDXagQQWnAnebYeQWGHlmF81YRwuGCzAgNZAQ=",
|
||||||
"owner": "notashelf",
|
"owner": "notashelf",
|
||||||
"repo": "nvf",
|
"repo": "nvf",
|
||||||
"rev": "edfb73fa4ced576f587d259a70a513b4152f8cea",
|
"rev": "d847d401bea4dcb1478d02a61a3209fa8512f71d",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -1132,25 +904,24 @@
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"clan-core": "clan-core",
|
"clan-core": "clan-core",
|
||||||
|
"disko": "disko",
|
||||||
"erosanix": "erosanix",
|
"erosanix": "erosanix",
|
||||||
"fenix": "fenix",
|
"fenix": "fenix",
|
||||||
"firefox": "firefox",
|
"flake-parts": "flake-parts",
|
||||||
"flux": "flux",
|
"flux": "flux",
|
||||||
"grub2-themes": "grub2-themes",
|
"grub2-themes": "grub2-themes",
|
||||||
"himmelblau": "himmelblau",
|
"himmelblau": "himmelblau",
|
||||||
"home-manager": "home-manager",
|
"home-manager": "home-manager",
|
||||||
|
"import-tree": "import-tree",
|
||||||
"jovian": "jovian",
|
"jovian": "jovian",
|
||||||
"mydia": "mydia",
|
"mydia": "mydia",
|
||||||
"nix-minecraft": "nix-minecraft",
|
"nix-minecraft": "nix-minecraft",
|
||||||
"nixos-boot": "nixos-boot",
|
"nixpkgs": "nixpkgs_7",
|
||||||
"nixos-generators": "nixos-generators",
|
|
||||||
"nixos-wsl": "nixos-wsl",
|
|
||||||
"nixpkgs": "nixpkgs_8",
|
|
||||||
"nvf": "nvf",
|
"nvf": "nvf",
|
||||||
"plasma-manager": "plasma-manager",
|
"plasma-manager": "plasma-manager",
|
||||||
"snowfall-lib": "snowfall-lib",
|
"sops-nix": "sops-nix",
|
||||||
"sops-nix": "sops-nix_2",
|
|
||||||
"stylix": "stylix",
|
"stylix": "stylix",
|
||||||
|
"systems": "systems_4",
|
||||||
"terranix": "terranix",
|
"terranix": "terranix",
|
||||||
"zen-browser": "zen-browser"
|
"zen-browser": "zen-browser"
|
||||||
}
|
}
|
||||||
|
|
@ -1158,11 +929,11 @@
|
||||||
"rust-analyzer-src": {
|
"rust-analyzer-src": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1774221325,
|
"lastModified": 1774376228,
|
||||||
"narHash": "sha256-aEIdkqB8gtQZtEbogdUb5iyfcZpKIlD3FkG8ANu73/I=",
|
"narHash": "sha256-7oA0u4aghFjjIcIDKZ26NUpXH7hVXGPC0sI1OfK7NUk=",
|
||||||
"owner": "rust-lang",
|
"owner": "rust-lang",
|
||||||
"repo": "rust-analyzer",
|
"repo": "rust-analyzer",
|
||||||
"rev": "b42b63f390a4dab14e6efa34a70e67f5b087cc62",
|
"rev": "eabb84b771420b8396ab4bb4747694302d9be277",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -1172,59 +943,16 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"snowfall-lib": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-compat": "flake-compat_5",
|
|
||||||
"flake-utils-plus": "flake-utils-plus",
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1765361626,
|
|
||||||
"narHash": "sha256-kX0Dp/kYSRbQ+yd9e3lmmUWdNbipufvKfL2IzbrSpnY=",
|
|
||||||
"owner": "snowfallorg",
|
|
||||||
"repo": "lib",
|
|
||||||
"rev": "c566ad8b7352c30ec3763435de7c8f1c46ebb357",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "snowfallorg",
|
|
||||||
"repo": "lib",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sops-nix": {
|
"sops-nix": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": "nixpkgs_9"
|
||||||
"clan-core",
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1774154798,
|
"lastModified": 1774303811,
|
||||||
"narHash": "sha256-zsTuloDSdKf+PrI1MsWx5z/cyGEJ8P3eERtAfdP8Bmg=",
|
"narHash": "sha256-fhG4JAcLgjKwt+XHbjs8brpWnyKUfU4LikLm3s0Q/ic=",
|
||||||
"owner": "Mic92",
|
"owner": "Mic92",
|
||||||
"repo": "sops-nix",
|
"repo": "sops-nix",
|
||||||
"rev": "3e0d543e6ba6c0c48117a81614e90c6d8c425170",
|
"rev": "614e256310e0a4f8a9ccae3fa80c11844fba7042",
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "Mic92",
|
|
||||||
"repo": "sops-nix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sops-nix_2": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": "nixpkgs_10"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1774154798,
|
|
||||||
"narHash": "sha256-zsTuloDSdKf+PrI1MsWx5z/cyGEJ8P3eERtAfdP8Bmg=",
|
|
||||||
"owner": "Mic92",
|
|
||||||
"repo": "sops-nix",
|
|
||||||
"rev": "3e0d543e6ba6c0c48117a81614e90c6d8c425170",
|
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -1242,9 +970,9 @@
|
||||||
"firefox-gnome-theme": "firefox-gnome-theme",
|
"firefox-gnome-theme": "firefox-gnome-theme",
|
||||||
"flake-parts": "flake-parts_4",
|
"flake-parts": "flake-parts_4",
|
||||||
"gnome-shell": "gnome-shell",
|
"gnome-shell": "gnome-shell",
|
||||||
"nixpkgs": "nixpkgs_11",
|
"nixpkgs": "nixpkgs_10",
|
||||||
"nur": "nur",
|
"nur": "nur",
|
||||||
"systems": "systems_6",
|
"systems": "systems_3",
|
||||||
"tinted-foot": "tinted-foot",
|
"tinted-foot": "tinted-foot",
|
||||||
"tinted-kitty": "tinted-kitty",
|
"tinted-kitty": "tinted-kitty",
|
||||||
"tinted-schemes": "tinted-schemes",
|
"tinted-schemes": "tinted-schemes",
|
||||||
|
|
@ -1340,43 +1068,15 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"systems_6": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681028828,
|
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"systems_7": {
|
|
||||||
"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_5",
|
"flake-parts": [
|
||||||
|
"flake-parts"
|
||||||
|
],
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
],
|
],
|
||||||
"systems": "systems_7"
|
"systems": "systems_5"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1773700838,
|
"lastModified": 1773700838,
|
||||||
|
|
@ -1502,11 +1202,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1774242250,
|
"lastModified": 1774352774,
|
||||||
"narHash": "sha256-pchbnY7KVnH26g4O3LZO8vpshInqNj937gAqlPob1Mk=",
|
"narHash": "sha256-gibUM0pSnLxEeuFrYA8T1oEaixk+fjQpqXbYaxcEX/4=",
|
||||||
"owner": "0xc000022070",
|
"owner": "0xc000022070",
|
||||||
"repo": "zen-browser-flake",
|
"repo": "zen-browser-flake",
|
||||||
"rev": "f19c3e6683c2d2f3fcfcb88fb691931a104bc47c",
|
"rev": "a0f3d47dbd8f8618a1920d5a5ca09b7993415895",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
||||||
128
flake.nix
128
flake.nix
|
|
@ -1,11 +1,24 @@
|
||||||
{
|
{
|
||||||
description = "Nixos config flake";
|
description = "Nixos config flake";
|
||||||
|
|
||||||
|
nixConfig = {
|
||||||
|
warn-dirty = false;
|
||||||
|
extra-experimental-features = ["nix-command" "flakes" "pipe-operators"];
|
||||||
|
};
|
||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||||
|
|
||||||
snowfall-lib = {
|
flake-parts = {
|
||||||
url = "github:snowfallorg/lib";
|
url = "github:hercules-ci/flake-parts";
|
||||||
|
inputs.nixpkgs-lib.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
import-tree.url = "github:vic/import-tree";
|
||||||
|
systems.url = "github:nix-systems/default";
|
||||||
|
sops-nix.url = "github:Mic92/sops-nix";
|
||||||
|
|
||||||
|
disko = {
|
||||||
|
url = "github:nix-community/disko";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -14,25 +27,32 @@
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
terranix = {
|
||||||
|
url = "github:terranix/terranix";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
inputs.flake-parts.follows = "flake-parts";
|
||||||
|
};
|
||||||
|
|
||||||
|
clan-core = {
|
||||||
|
url = "https://git.clan.lol/clan/clan-core/archive/main.tar.gz";
|
||||||
|
inputs = {
|
||||||
|
flake-parts.follows = "flake-parts";
|
||||||
|
nixpkgs.follows = "nixpkgs";
|
||||||
|
sops-nix.follows = "sops-nix";
|
||||||
|
disko.follows = "disko";
|
||||||
|
systems.follows = "systems";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
plasma-manager = {
|
plasma-manager = {
|
||||||
url = "github:nix-community/plasma-manager";
|
url = "github:nix-community/plasma-manager";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
inputs.home-manager.follows = "home-manager";
|
inputs.home-manager.follows = "home-manager";
|
||||||
};
|
};
|
||||||
|
|
||||||
nixos-generators = {
|
|
||||||
url = "github:nix-community/nixos-generators";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
};
|
|
||||||
|
|
||||||
# neovim
|
# neovim
|
||||||
nvf.url = "github:notashelf/nvf";
|
nvf.url = "github:notashelf/nvf";
|
||||||
|
|
||||||
# plymouth theme
|
|
||||||
nixos-boot.url = "github:Melkor333/nixos-boot";
|
|
||||||
|
|
||||||
firefox.url = "github:nix-community/flake-firefox-nightly";
|
|
||||||
|
|
||||||
stylix.url = "github:nix-community/stylix";
|
stylix.url = "github:nix-community/stylix";
|
||||||
|
|
||||||
# Rust toolchain
|
# Rust toolchain
|
||||||
|
|
@ -50,8 +70,6 @@
|
||||||
|
|
||||||
flux.url = "github:IogaMaster/flux";
|
flux.url = "github:IogaMaster/flux";
|
||||||
|
|
||||||
sops-nix.url = "github:Mic92/sops-nix";
|
|
||||||
|
|
||||||
# Azure AD for linux
|
# Azure AD for linux
|
||||||
himmelblau = {
|
himmelblau = {
|
||||||
url = "github:himmelblau-idm/himmelblau";
|
url = "github:himmelblau-idm/himmelblau";
|
||||||
|
|
@ -71,58 +89,34 @@
|
||||||
url = "github:vinceliuice/grub2-themes";
|
url = "github:vinceliuice/grub2-themes";
|
||||||
};
|
};
|
||||||
|
|
||||||
nixos-wsl = {
|
|
||||||
url = "github:nix-community/nixos-wsl";
|
|
||||||
inputs = {
|
|
||||||
nixpkgs.follows = "nixpkgs";
|
|
||||||
flake-compat.follows = "";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
terranix = {
|
|
||||||
url = "github:terranix/terranix";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
};
|
|
||||||
|
|
||||||
clan-core = {
|
|
||||||
url = "https://git.clan.lol/clan/clan-core/archive/main.tar.gz";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
};
|
|
||||||
|
|
||||||
mydia = {
|
mydia = {
|
||||||
url = "github:chris-kruining/mydia";
|
url = "github:chris-kruining/mydia";
|
||||||
# url = "github:getmydia/mydia";
|
# url = "github:getmydia/mydia";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = inputs:
|
outputs = inputs @ {
|
||||||
inputs.snowfall-lib.mkFlake {
|
flake-parts,
|
||||||
inherit inputs;
|
nixpkgs,
|
||||||
src = ./.;
|
systems,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
flake-parts.lib.mkFlake {inherit inputs;} {
|
||||||
|
systems = import systems;
|
||||||
|
|
||||||
snowfall = {
|
imports = with inputs; [
|
||||||
namespace = "sneeuwvlok";
|
flake-parts.flakeModules.modules
|
||||||
|
clan-core.flakeModules.default
|
||||||
meta = {
|
home-manager.flakeModules.default
|
||||||
name = "sneeuwvlok";
|
./clan/flake-module.nix
|
||||||
title = "Sneeuwvlok";
|
./packages/flake-module.nix
|
||||||
};
|
./clanServices/flake-module.nix
|
||||||
};
|
|
||||||
|
|
||||||
channels-config = {
|
|
||||||
allowUnfree = true;
|
|
||||||
permittedInsecurePackages = [
|
|
||||||
# Due to *arr stack
|
|
||||||
"dotnet-sdk-6.0.428"
|
|
||||||
"aspnetcore-runtime-6.0.36"
|
|
||||||
|
|
||||||
# I think this is because of zen
|
|
||||||
"qtwebengine-5.15.19"
|
|
||||||
|
|
||||||
# For Nheko, the matrix client
|
|
||||||
"olm-3.2.16"
|
|
||||||
];
|
];
|
||||||
};
|
|
||||||
|
perSystem = {system, ...}: {
|
||||||
|
_module.args = {
|
||||||
|
pkgs = import nixpkgs {
|
||||||
|
inherit system;
|
||||||
|
|
||||||
overlays = with inputs; [
|
overlays = with inputs; [
|
||||||
fenix.overlays.default
|
fenix.overlays.default
|
||||||
|
|
@ -130,13 +124,19 @@
|
||||||
flux.overlays.default
|
flux.overlays.default
|
||||||
];
|
];
|
||||||
|
|
||||||
systems.modules = with inputs; [
|
config = {
|
||||||
clan-core.nixosModules.default
|
allowUnfree = true;
|
||||||
];
|
|
||||||
|
|
||||||
homes.modules = with inputs; [
|
permittedInsecurePackages = [
|
||||||
stylix.homeModules.stylix
|
# I think this is because of zen
|
||||||
plasma-manager.homeModules.plasma-manager
|
"qtwebengine-5.15.19"
|
||||||
|
|
||||||
|
# For mautrix-signal, the matrix to signal bridge
|
||||||
|
"olm-3.2.16"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
{osConfig, ...}: {
|
|
||||||
home.stateVersion = osConfig.system.stateVersion;
|
|
||||||
|
|
||||||
programs.git = {
|
|
||||||
settings.user = {
|
|
||||||
name = "Chris Kruining";
|
|
||||||
email = "chris@kruining.eu";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
sneeuwvlok = {
|
|
||||||
defaults = {
|
|
||||||
shell = "zsh";
|
|
||||||
terminal = "ghostty";
|
|
||||||
browser = "zen";
|
|
||||||
editor = "zed";
|
|
||||||
};
|
|
||||||
|
|
||||||
shell = {
|
|
||||||
corePkgs.enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
themes = {
|
|
||||||
enable = true;
|
|
||||||
theme = "everforest";
|
|
||||||
polarity = "dark";
|
|
||||||
};
|
|
||||||
|
|
||||||
application = {
|
|
||||||
bitwarden.enable = true;
|
|
||||||
teamspeak.enable = true;
|
|
||||||
steam.enable = true;
|
|
||||||
zen.enable = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
{osConfig, ...}: {
|
|
||||||
home.stateVersion = osConfig.system.stateVersion;
|
|
||||||
|
|
||||||
programs.git = {
|
|
||||||
settings.user = {
|
|
||||||
name = "Chris Kruining";
|
|
||||||
email = "chris@kruining.eu";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
sneeuwvlok = {
|
|
||||||
defaults = {
|
|
||||||
shell = "zsh";
|
|
||||||
terminal = "ghostty";
|
|
||||||
browser = "zen";
|
|
||||||
editor = "zed";
|
|
||||||
};
|
|
||||||
|
|
||||||
shell = {
|
|
||||||
corePkgs.enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
themes = {
|
|
||||||
enable = true;
|
|
||||||
theme = "everforest";
|
|
||||||
polarity = "dark";
|
|
||||||
};
|
|
||||||
|
|
||||||
development = {
|
|
||||||
rust.enable = true;
|
|
||||||
javascript.enable = true;
|
|
||||||
dotnet.enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
application = {
|
|
||||||
bitwarden.enable = true;
|
|
||||||
discord.enable = true;
|
|
||||||
ladybird.enable = true;
|
|
||||||
matrix.enable = true;
|
|
||||||
obs.enable = true;
|
|
||||||
onlyoffice.enable = true;
|
|
||||||
signal.enable = true;
|
|
||||||
steam.enable = true;
|
|
||||||
studio.enable = true;
|
|
||||||
teamspeak.enable = true;
|
|
||||||
thunderbird.enable = true;
|
|
||||||
zen.enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
shell.zsh.enable = true;
|
|
||||||
terminal.ghostty.enable = true;
|
|
||||||
|
|
||||||
editor = {
|
|
||||||
zed.enable = true;
|
|
||||||
nvim.enable = true;
|
|
||||||
nano.enable = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
{osConfig, ...}: {
|
|
||||||
home.stateVersion = osConfig.system.stateVersion;
|
|
||||||
|
|
||||||
programs.git = {
|
|
||||||
settings.user = {
|
|
||||||
name = "Chris Kruining";
|
|
||||||
email = "chris@kruining.eu";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
sneeuwvlok = {
|
|
||||||
defaults = {
|
|
||||||
shell = "zsh";
|
|
||||||
terminal = "ghostty";
|
|
||||||
browser = "zen";
|
|
||||||
editor = "zed";
|
|
||||||
};
|
|
||||||
|
|
||||||
shell = {
|
|
||||||
corePkgs.enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
themes = {
|
|
||||||
enable = true;
|
|
||||||
theme = "everforest";
|
|
||||||
polarity = "dark";
|
|
||||||
};
|
|
||||||
|
|
||||||
development = {
|
|
||||||
javascript.enable = true;
|
|
||||||
dotnet.enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
application = {
|
|
||||||
bitwarden.enable = true;
|
|
||||||
onlyoffice.enable = true;
|
|
||||||
signal.enable = true;
|
|
||||||
zen.enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
shell.zsh.enable = true;
|
|
||||||
terminal.ghostty.enable = true;
|
|
||||||
|
|
||||||
editor = {
|
|
||||||
zed.enable = true;
|
|
||||||
nano.enable = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
{osConfig, ...}: {
|
|
||||||
home.stateVersion = osConfig.system.stateVersion;
|
|
||||||
|
|
||||||
programs.git = {
|
|
||||||
settings.user = {
|
|
||||||
name = "Chris Kruining";
|
|
||||||
email = "chris@kruining.eu";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
sneeuwvlok = {
|
|
||||||
defaults = {
|
|
||||||
shell = "zsh";
|
|
||||||
terminal = "ghostty";
|
|
||||||
browser = "zen";
|
|
||||||
editor = "zed";
|
|
||||||
};
|
|
||||||
|
|
||||||
shell = {
|
|
||||||
corePkgs.enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
themes = {
|
|
||||||
enable = true;
|
|
||||||
theme = "everforest";
|
|
||||||
polarity = "dark";
|
|
||||||
};
|
|
||||||
|
|
||||||
application = {
|
|
||||||
bitwarden.enable = true;
|
|
||||||
teamspeak.enable = true;
|
|
||||||
steam.enable = true;
|
|
||||||
zen.enable = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
37
lib/options.nix
Normal file
37
lib/options.nix
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
{lib, ...}: let
|
||||||
|
inherit (lib) mkOption types;
|
||||||
|
in {
|
||||||
|
mkUrlOptions = defaults: {
|
||||||
|
host =
|
||||||
|
mkOption {
|
||||||
|
type = types.str;
|
||||||
|
example = "host.tld";
|
||||||
|
description = ''
|
||||||
|
Hostname
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
// (defaults.host or {});
|
||||||
|
|
||||||
|
port =
|
||||||
|
mkOption {
|
||||||
|
type = types.port;
|
||||||
|
default = 1234;
|
||||||
|
example = "1234";
|
||||||
|
description = ''
|
||||||
|
Port
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
// (defaults.port or {});
|
||||||
|
|
||||||
|
protocol =
|
||||||
|
mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "https";
|
||||||
|
example = "https";
|
||||||
|
description = ''
|
||||||
|
Which protocol to use when creating a url string
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
// (defaults.protocol or {});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
{ lib, ...}:
|
|
||||||
let
|
|
||||||
inherit (builtins) isString typeOf;
|
|
||||||
inherit (lib) mkOption types throwIfNot concatStringsSep splitStringBy toLower map;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options = {
|
|
||||||
mkUrlOptions =
|
|
||||||
defaults:
|
|
||||||
{
|
|
||||||
host = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
example = "host.tld";
|
|
||||||
description = ''
|
|
||||||
Hostname
|
|
||||||
'';
|
|
||||||
} // (defaults.host or {});
|
|
||||||
|
|
||||||
port = mkOption {
|
|
||||||
type = types.port;
|
|
||||||
default = 1234;
|
|
||||||
example = "1234";
|
|
||||||
description = ''
|
|
||||||
Port
|
|
||||||
'';
|
|
||||||
} // (defaults.port or {});
|
|
||||||
|
|
||||||
protocol = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "https";
|
|
||||||
example = "https";
|
|
||||||
description = ''
|
|
||||||
Which protocol to use when creating a url string
|
|
||||||
'';
|
|
||||||
} // (defaults.protocol or {});
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
53
lib/strings.nix
Normal file
53
lib/strings.nix
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
{lib, ...}: let
|
||||||
|
inherit (builtins) isString typeOf match toString head;
|
||||||
|
inherit (lib) throwIfNot concatStringsSep splitStringBy toLower map concatMapAttrsStringSep;
|
||||||
|
in {
|
||||||
|
#========================================================================================
|
||||||
|
# Converts a string to snake case
|
||||||
|
#
|
||||||
|
# simply replaces any uppercase letter to its lowercase variant preceeded by an underscore
|
||||||
|
#========================================================================================
|
||||||
|
toSnakeCase = str:
|
||||||
|
throwIfNot (isString str) "toSnakeCase only accepts string values, but got ${typeOf str}" (
|
||||||
|
str
|
||||||
|
|> splitStringBy (prev: curr: builtins.match "[a-z]" prev != null && builtins.match "[A-Z]" curr != null) true
|
||||||
|
|> map (p: toLower p)
|
||||||
|
|> concatStringsSep "_"
|
||||||
|
);
|
||||||
|
|
||||||
|
#========================================================================================
|
||||||
|
# Converts a set of url parts to a string
|
||||||
|
#========================================================================================
|
||||||
|
toUrl = {
|
||||||
|
protocol ? null,
|
||||||
|
host,
|
||||||
|
port ? null,
|
||||||
|
path ? null,
|
||||||
|
query ? null,
|
||||||
|
hash ? null,
|
||||||
|
}: let
|
||||||
|
trim_slashes = str: str |> match "^\/*(.+?)\/*$" |> head;
|
||||||
|
encode_to_str = set: concatMapAttrsStringSep "&" (n: v: "${n}=${v}") set;
|
||||||
|
|
||||||
|
_protocol =
|
||||||
|
if protocol != null
|
||||||
|
then "${protocol}://"
|
||||||
|
else "";
|
||||||
|
_port =
|
||||||
|
if port != null
|
||||||
|
then ":${toString port}"
|
||||||
|
else "";
|
||||||
|
_path =
|
||||||
|
if path != null
|
||||||
|
then "/${path |> trim_slashes}"
|
||||||
|
else "";
|
||||||
|
_query =
|
||||||
|
if query != null
|
||||||
|
then "?${query |> encode_to_str}"
|
||||||
|
else "";
|
||||||
|
_hash =
|
||||||
|
if hash != null
|
||||||
|
then "#${hash |> encode_to_str}"
|
||||||
|
else "";
|
||||||
|
in "${_protocol}${host}${_port}${_path}${_query}${_hash}";
|
||||||
|
}
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
{ lib, ...}:
|
|
||||||
let
|
|
||||||
inherit (builtins) isString typeOf match toString head;
|
|
||||||
inherit (lib) throwIfNot concatStringsSep splitStringBy toLower map concatMapAttrsStringSep;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
strings = {
|
|
||||||
#========================================================================================
|
|
||||||
# Converts a string to snake case
|
|
||||||
#
|
|
||||||
# simply replaces any uppercase letter to its lowercase variant preceeded by an underscore
|
|
||||||
#========================================================================================
|
|
||||||
toSnakeCase =
|
|
||||||
str:
|
|
||||||
throwIfNot (isString str) "toSnakeCase only accepts string values, but got ${typeOf str}" (
|
|
||||||
str
|
|
||||||
|> splitStringBy (prev: curr: builtins.match "[a-z]" prev != null && builtins.match "[A-Z]" curr != null) true
|
|
||||||
|> map (p: toLower p)
|
|
||||||
|> concatStringsSep "_"
|
|
||||||
);
|
|
||||||
|
|
||||||
#========================================================================================
|
|
||||||
# Converts a set of url parts to a string
|
|
||||||
#========================================================================================
|
|
||||||
toUrl =
|
|
||||||
{ protocol ? null, host, port ? null, path ? null, query ? null, hash ? null }:
|
|
||||||
let
|
|
||||||
trim_slashes = str: str |> match "^\/*(.+?)\/*$" |> head;
|
|
||||||
encode_to_str = set: concatMapAttrsStringSep "&" (n: v: "${n}=${v}") set;
|
|
||||||
|
|
||||||
_protocol = if protocol != null then "${protocol}://" else "";
|
|
||||||
_port = if port != null then ":${toString port}" else "";
|
|
||||||
_path = if path != null then "/${path |> trim_slashes}" else "";
|
|
||||||
_query = if query != null then "?${query |> encode_to_str}" else "";
|
|
||||||
_hash = if hash != null then "#${hash |> encode_to_str}" else "";
|
|
||||||
in
|
|
||||||
"${_protocol}${host}${_port}${_path}${_query}${_hash}";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
3
machines/aule/configuration.nix
Normal file
3
machines/aule/configuration.nix
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{ ... }: {
|
||||||
|
nixpkgs.hostPlatform = "x86_64-linux";
|
||||||
|
}
|
||||||
40
machines/mandos/configuration.nix
Normal file
40
machines/mandos/configuration.nix
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
{self, ...}: {
|
||||||
|
imports = [
|
||||||
|
./disks.nix
|
||||||
|
./hardware.nix
|
||||||
|
self.inputs.home-manager.nixosModules.home-manager
|
||||||
|
self.inputs.himmelblau.nixosModules.himmelblau
|
||||||
|
self.inputs.jovian.nixosModules.default
|
||||||
|
self.inputs.mydia.nixosModules.default
|
||||||
|
self.inputs.nix-minecraft.nixosModules.minecraft-servers
|
||||||
|
self.inputs.nvf.nixosModules.default
|
||||||
|
self.inputs.sops-nix.nixosModules.sops
|
||||||
|
(self.inputs.import-tree ../../modules/nixos)
|
||||||
|
];
|
||||||
|
|
||||||
|
nixpkgs.hostPlatform = "x86_64-linux";
|
||||||
|
|
||||||
|
sneeuwvlok = {
|
||||||
|
hardware.has = {
|
||||||
|
gpu.nvidia = true;
|
||||||
|
audio = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
boot = {
|
||||||
|
quiet = true;
|
||||||
|
animated = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
desktop.use = "gamescope";
|
||||||
|
|
||||||
|
application = {
|
||||||
|
steam.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
editor = {
|
||||||
|
nano.enable = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
system.stateVersion = "23.11";
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
{ config, lib, pkgs, modulesPath, system, ... }:
|
{ config, lib, pkgs, modulesPath, ... }:
|
||||||
let
|
let
|
||||||
inherit (lib.modules) mkDefault;
|
inherit (lib.modules) mkDefault;
|
||||||
in
|
in
|
||||||
|
|
@ -13,6 +13,6 @@ in
|
||||||
extraModulePackages = [ ];
|
extraModulePackages = [ ];
|
||||||
};
|
};
|
||||||
|
|
||||||
nixpkgs.hostPlatform = mkDefault system;
|
nixpkgs.hostPlatform = mkDefault pkgs.stdenv.hostPlatform.system;
|
||||||
hardware.cpu.intel.updateMicrocode = mkDefault config.hardware.enableRedistributableFirmware;
|
hardware.cpu.intel.updateMicrocode = mkDefault config.hardware.enableRedistributableFirmware;
|
||||||
}
|
}
|
||||||
79
machines/manwe/configuration.nix
Normal file
79
machines/manwe/configuration.nix
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
{
|
||||||
|
self,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
_module.args = {
|
||||||
|
pkgs = lib.mkForce (import self.inputs.nixpkgs {
|
||||||
|
system = "x86_64-linux";
|
||||||
|
|
||||||
|
overlays = with self.inputs; [
|
||||||
|
fenix.overlays.default
|
||||||
|
nix-minecraft.overlay
|
||||||
|
flux.overlays.default
|
||||||
|
];
|
||||||
|
|
||||||
|
config = {
|
||||||
|
allowUnfree = true;
|
||||||
|
|
||||||
|
permittedInsecurePackages = [
|
||||||
|
# I think this is because of zen
|
||||||
|
"qtwebengine-5.15.19"
|
||||||
|
|
||||||
|
# For mautrix-signal, the matrix to signal bridge
|
||||||
|
"olm-3.2.16"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
imports = [
|
||||||
|
./disks.nix
|
||||||
|
./hardware.nix
|
||||||
|
self.inputs.home-manager.nixosModules.home-manager
|
||||||
|
self.inputs.himmelblau.nixosModules.himmelblau
|
||||||
|
self.inputs.jovian.nixosModules.default
|
||||||
|
self.inputs.mydia.nixosModules.default
|
||||||
|
self.inputs.nix-minecraft.nixosModules.minecraft-servers
|
||||||
|
self.inputs.nvf.nixosModules.default
|
||||||
|
self.inputs.sops-nix.nixosModules.sops
|
||||||
|
(self.inputs.import-tree ../../modules/nixos)
|
||||||
|
];
|
||||||
|
|
||||||
|
system.activationScripts.remove-gtkrc.text = "rm -f /home/chris/.gtkrc-2.0";
|
||||||
|
|
||||||
|
services.logrotate.checkConfig = false;
|
||||||
|
|
||||||
|
environment.systemPackages = with pkgs; [beyond-all-reason openrct2];
|
||||||
|
|
||||||
|
sneeuwvlok = {
|
||||||
|
hardware.has = {
|
||||||
|
gpu.amd = true;
|
||||||
|
bluetooth = true;
|
||||||
|
audio = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
boot = {
|
||||||
|
quiet = true;
|
||||||
|
animated = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
desktop.use = "plasma";
|
||||||
|
|
||||||
|
application = {
|
||||||
|
steam.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
editor = {
|
||||||
|
nano.enable = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.displayManager.autoLogin = {
|
||||||
|
enable = true;
|
||||||
|
user = "chris";
|
||||||
|
};
|
||||||
|
|
||||||
|
system.stateVersion = "23.11";
|
||||||
|
}
|
||||||
18
machines/manwe/hardware.nix
Normal file
18
machines/manwe/hardware.nix
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (lib.modules) mkDefault;
|
||||||
|
in {
|
||||||
|
boot = {
|
||||||
|
initrd.availableKernelModules = ["xhci_pci" "ahci" "usb_storage" "usbhid" "sd_mod"];
|
||||||
|
initrd.kernelModules = [];
|
||||||
|
kernelModules = ["kvm-amd"];
|
||||||
|
kernelParams = [];
|
||||||
|
extraModulePackages = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
nixpkgs.hostPlatform = "x86_64-linux";
|
||||||
|
hardware.cpu.amd.updateMicrocode = mkDefault config.hardware.enableRedistributableFirmware;
|
||||||
|
}
|
||||||
3
machines/melkor/configuration.nix
Normal file
3
machines/melkor/configuration.nix
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{ ... }: {
|
||||||
|
nixpkgs.hostPlatform = "x86_64-linux";
|
||||||
|
}
|
||||||
44
machines/orome/configuration.nix
Normal file
44
machines/orome/configuration.nix
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
{
|
||||||
|
self,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
imports = [
|
||||||
|
./disks.nix
|
||||||
|
./hardware.nix
|
||||||
|
self.inputs.home-manager.nixosModules.home-manager
|
||||||
|
self.inputs.himmelblau.nixosModules.himmelblau
|
||||||
|
self.inputs.jovian.nixosModules.default
|
||||||
|
self.inputs.mydia.nixosModules.default
|
||||||
|
self.inputs.nix-minecraft.nixosModules.minecraft-servers
|
||||||
|
self.inputs.nvf.nixosModules.default
|
||||||
|
self.inputs.sops-nix.nixosModules.sops
|
||||||
|
(self.inputs.import-tree ../../modules/nixos)
|
||||||
|
];
|
||||||
|
|
||||||
|
nixpkgs.hostPlatform = "x86_64-linux";
|
||||||
|
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
azure-cli
|
||||||
|
github-copilot-cli
|
||||||
|
];
|
||||||
|
|
||||||
|
sneeuwvlok = {
|
||||||
|
hardware.has = {
|
||||||
|
bluetooth = true;
|
||||||
|
audio = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
services.authentication.himmelblau.enable = true;
|
||||||
|
|
||||||
|
application = {
|
||||||
|
steam.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
editor = {
|
||||||
|
nano.enable = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
system.stateVersion = "23.11";
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
{ config, lib, pkgs, modulesPath, system, ... }:
|
{ config, lib, pkgs, modulesPath, ... }:
|
||||||
let
|
let
|
||||||
inherit (lib.modules) mkDefault;
|
inherit (lib.modules) mkDefault;
|
||||||
in
|
in
|
||||||
|
|
@ -13,6 +13,6 @@ in
|
||||||
extraModulePackages = [ ];
|
extraModulePackages = [ ];
|
||||||
};
|
};
|
||||||
|
|
||||||
nixpkgs.hostPlatform = mkDefault system;
|
nixpkgs.hostPlatform = mkDefault pkgs.stdenv.hostPlatform.system;
|
||||||
hardware.cpu.intel.updateMicrocode = mkDefault config.hardware.enableRedistributableFirmware;
|
hardware.cpu.intel.updateMicrocode = mkDefault config.hardware.enableRedistributableFirmware;
|
||||||
}
|
}
|
||||||
41
machines/tulkas/configuration.nix
Normal file
41
machines/tulkas/configuration.nix
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
{self, ...}: {
|
||||||
|
imports = [
|
||||||
|
./disks.nix
|
||||||
|
./hardware.nix
|
||||||
|
self.inputs.home-manager.nixosModules.home-manager
|
||||||
|
self.inputs.himmelblau.nixosModules.himmelblau
|
||||||
|
self.inputs.jovian.nixosModules.default
|
||||||
|
self.inputs.mydia.nixosModules.default
|
||||||
|
self.inputs.nix-minecraft.nixosModules.minecraft-servers
|
||||||
|
self.inputs.nvf.nixosModules.default
|
||||||
|
self.inputs.sops-nix.nixosModules.sops
|
||||||
|
(self.inputs.import-tree ../../modules/nixos)
|
||||||
|
];
|
||||||
|
|
||||||
|
nixpkgs.hostPlatform = "x86_64-linux";
|
||||||
|
|
||||||
|
sneeuwvlok = {
|
||||||
|
hardware.has = {
|
||||||
|
gpu.amd = true;
|
||||||
|
bluetooth = true;
|
||||||
|
audio = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
boot = {
|
||||||
|
quiet = true;
|
||||||
|
animated = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
desktop.use = "gamescope";
|
||||||
|
|
||||||
|
application = {
|
||||||
|
steam.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
editor = {
|
||||||
|
nano.enable = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
system.stateVersion = "23.11";
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
{ config, lib, pkgs, modulesPath, system, ... }:
|
{ config, lib, pkgs, modulesPath, ... }:
|
||||||
let
|
let
|
||||||
inherit (lib.modules) mkDefault;
|
inherit (lib.modules) mkDefault;
|
||||||
in
|
in
|
||||||
|
|
@ -13,6 +13,6 @@ in
|
||||||
extraModulePackages = [ ];
|
extraModulePackages = [ ];
|
||||||
};
|
};
|
||||||
|
|
||||||
nixpkgs.hostPlatform = mkDefault system;
|
nixpkgs.hostPlatform = mkDefault pkgs.stdenv.hostPlatform.system;
|
||||||
hardware.cpu.intel.updateMicrocode = mkDefault config.hardware.enableRedistributableFirmware;
|
hardware.cpu.intel.updateMicrocode = mkDefault config.hardware.enableRedistributableFirmware;
|
||||||
}
|
}
|
||||||
286
machines/ulmo/configuration.nix
Normal file
286
machines/ulmo/configuration.nix
Normal file
|
|
@ -0,0 +1,286 @@
|
||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
self,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
_module.args = {
|
||||||
|
pkgs = lib.mkForce (import self.inputs.nixpkgs {
|
||||||
|
system = "x86_64-linux";
|
||||||
|
|
||||||
|
overlays = with self.inputs; [
|
||||||
|
fenix.overlays.default
|
||||||
|
nix-minecraft.overlay
|
||||||
|
flux.overlays.default
|
||||||
|
];
|
||||||
|
|
||||||
|
config = {
|
||||||
|
allowUnfree = true;
|
||||||
|
|
||||||
|
permittedInsecurePackages = [
|
||||||
|
# I think this is because of zen
|
||||||
|
"qtwebengine-5.15.19"
|
||||||
|
|
||||||
|
# For mautrix-signal, the matrix to signal bridge
|
||||||
|
"olm-3.2.16"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
imports = [
|
||||||
|
./disks.nix
|
||||||
|
./hardware.nix
|
||||||
|
self.inputs.home-manager.nixosModules.home-manager
|
||||||
|
self.inputs.himmelblau.nixosModules.himmelblau
|
||||||
|
self.inputs.jovian.nixosModules.default
|
||||||
|
self.inputs.mydia.nixosModules.default
|
||||||
|
self.inputs.nix-minecraft.nixosModules.minecraft-servers
|
||||||
|
self.inputs.nvf.nixosModules.default
|
||||||
|
self.inputs.sops-nix.nixosModules.sops
|
||||||
|
(self.inputs.import-tree ../../modules/nixos)
|
||||||
|
];
|
||||||
|
|
||||||
|
system.stateVersion = "23.11";
|
||||||
|
|
||||||
|
networking = {
|
||||||
|
interfaces.enp2s0 = {
|
||||||
|
ipv6.addresses = [
|
||||||
|
{
|
||||||
|
address = "2a0d:6e00:1dc9:0::dead:beef";
|
||||||
|
prefixLength = 64;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
useDHCP = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
defaultGateway = {
|
||||||
|
address = "192.168.1.1";
|
||||||
|
interface = "enp2s0";
|
||||||
|
};
|
||||||
|
|
||||||
|
defaultGateway6 = {
|
||||||
|
address = "fe80::1";
|
||||||
|
interface = "enp2s0";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# sneeuwvlok = {
|
||||||
|
# services = {
|
||||||
|
# backup.borg.enable = true;
|
||||||
|
|
||||||
|
# authentication.zitadel = {
|
||||||
|
# enable = true;
|
||||||
|
|
||||||
|
# organization = {
|
||||||
|
# nix = {
|
||||||
|
# user = {
|
||||||
|
# chris = {
|
||||||
|
# email = "chris@kruining.eu";
|
||||||
|
# firstName = "Chris";
|
||||||
|
# lastName = "Kruining";
|
||||||
|
|
||||||
|
# roles = ["ORG_OWNER"];
|
||||||
|
# instanceRoles = ["IAM_OWNER"];
|
||||||
|
# };
|
||||||
|
|
||||||
|
# kaas = {
|
||||||
|
# email = "chris+kaas@kruining.eu";
|
||||||
|
# firstName = "Kaas";
|
||||||
|
# lastName = "Kruining";
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
|
||||||
|
# project = {
|
||||||
|
# ulmo = {
|
||||||
|
# projectRoleCheck = true;
|
||||||
|
# projectRoleAssertion = true;
|
||||||
|
# hasProjectCheck = true;
|
||||||
|
|
||||||
|
# role = {
|
||||||
|
# jellyfin = {
|
||||||
|
# group = "jellyfin";
|
||||||
|
# };
|
||||||
|
# jellyfin_admin = {
|
||||||
|
# group = "jellyfin";
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
|
||||||
|
# assign = {
|
||||||
|
# chris = ["jellyfin" "jellyfin_admin"];
|
||||||
|
# kaas = ["jellyfin"];
|
||||||
|
# };
|
||||||
|
|
||||||
|
# application = {
|
||||||
|
# jellyfin = {
|
||||||
|
# redirectUris = ["https://jellyfin.kruining.eu/sso/OID/redirect/zitadel"];
|
||||||
|
# grantTypes = ["authorizationCode"];
|
||||||
|
# responseTypes = ["code"];
|
||||||
|
# };
|
||||||
|
|
||||||
|
# forgejo = {
|
||||||
|
# redirectUris = ["https://git.amarth.cloud/user/oauth2/zitadel/callback"];
|
||||||
|
# grantTypes = ["authorizationCode"];
|
||||||
|
# responseTypes = ["code"];
|
||||||
|
# };
|
||||||
|
|
||||||
|
# vaultwarden = {
|
||||||
|
# redirectUris = ["https://vault.kruining.eu/identity/connect/oidc-signin"];
|
||||||
|
# grantTypes = ["authorizationCode"];
|
||||||
|
# responseTypes = ["code"];
|
||||||
|
# exportMap = {
|
||||||
|
# client_id = "SSO_CLIENT_ID";
|
||||||
|
# client_secret = "SSO_CLIENT_SECRET";
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
|
||||||
|
# matrix = {
|
||||||
|
# redirectUris = ["https://matrix.kruining.eu/_synapse/client/oidc/callback"];
|
||||||
|
# grantTypes = ["authorizationCode"];
|
||||||
|
# responseTypes = ["code"];
|
||||||
|
# };
|
||||||
|
|
||||||
|
# mydia = {
|
||||||
|
# redirectUris = ["http://localhost:2010/auth/oidc/callback"];
|
||||||
|
# grantTypes = ["authorizationCode"];
|
||||||
|
# responseTypes = ["code"];
|
||||||
|
# };
|
||||||
|
|
||||||
|
# grafana = {
|
||||||
|
# redirectUris = ["http://localhost:9001/login/generic_oauth"];
|
||||||
|
# grantTypes = ["authorizationCode"];
|
||||||
|
# responseTypes = ["code"];
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
|
||||||
|
# convex = {
|
||||||
|
# projectRoleCheck = true;
|
||||||
|
# projectRoleAssertion = true;
|
||||||
|
# hasProjectCheck = true;
|
||||||
|
|
||||||
|
# application = {
|
||||||
|
# scry = {
|
||||||
|
# redirectUris = ["https://nautical-salamander-320.eu-west-1.convex.cloud/api/auth/callback/zitadel"];
|
||||||
|
# grantTypes = ["authorizationCode"];
|
||||||
|
# responseTypes = ["code"];
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
|
||||||
|
# action = {
|
||||||
|
# flattenRoles = {
|
||||||
|
# script = ''
|
||||||
|
# (ctx, api) => {
|
||||||
|
# if (ctx.v1.user.grants == undefined || ctx.v1.user.grants.count == 0) {
|
||||||
|
# return;
|
||||||
|
# }
|
||||||
|
|
||||||
|
# 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 }));
|
||||||
|
# };
|
||||||
|
# '';
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
|
||||||
|
# triggers = [
|
||||||
|
# {
|
||||||
|
# flowType = "customiseToken";
|
||||||
|
# triggerType = "preUserinfoCreation";
|
||||||
|
# actions = ["flattenRoles"];
|
||||||
|
# }
|
||||||
|
# {
|
||||||
|
# flowType = "customiseToken";
|
||||||
|
# triggerType = "preAccessTokenCreation";
|
||||||
|
# actions = ["flattenRoles"];
|
||||||
|
# }
|
||||||
|
# ];
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
|
||||||
|
# communication.matrix.enable = true;
|
||||||
|
|
||||||
|
# development.forgejo.enable = true;
|
||||||
|
|
||||||
|
# networking.ssh.enable = true;
|
||||||
|
# networking.caddy.hosts = {
|
||||||
|
# # Expose amarht cloud stuff like this until I have a proper solution
|
||||||
|
# "auth.amarth.cloud" = ''
|
||||||
|
# reverse_proxy http://192.168.1.223:9092
|
||||||
|
# '';
|
||||||
|
|
||||||
|
# "amarth.cloud" = ''
|
||||||
|
# reverse_proxy http://192.168.1.223:8080
|
||||||
|
# '';
|
||||||
|
# };
|
||||||
|
|
||||||
|
# media.enable = true;
|
||||||
|
# media.glance.enable = true;
|
||||||
|
# media.mydia.enable = true;
|
||||||
|
# media.nfs.enable = true;
|
||||||
|
# media.jellyfin.enable = true;
|
||||||
|
# # media.servarr = {
|
||||||
|
# # radarr = {
|
||||||
|
# # enable = true;
|
||||||
|
# # port = 2001;
|
||||||
|
# # rootFolders = [
|
||||||
|
# # "/var/media/movies"
|
||||||
|
# # ];
|
||||||
|
# # };
|
||||||
|
|
||||||
|
# # sonarr = {
|
||||||
|
# # enable = true;
|
||||||
|
# # # debug = true;
|
||||||
|
# # port = 2002;
|
||||||
|
# # rootFolders = [
|
||||||
|
# # "/var/media/series"
|
||||||
|
# # ];
|
||||||
|
# # };
|
||||||
|
|
||||||
|
# # lidarr = {
|
||||||
|
# # enable = true;
|
||||||
|
# # debug = true;
|
||||||
|
# # port = 2003;
|
||||||
|
# # rootFolders = [
|
||||||
|
# # "/var/media/music"
|
||||||
|
# # ];
|
||||||
|
# # };
|
||||||
|
|
||||||
|
# # prowlarr = {
|
||||||
|
# # enable = true;
|
||||||
|
# # # debug = true;
|
||||||
|
# # port = 2004;
|
||||||
|
# # };
|
||||||
|
# # };
|
||||||
|
|
||||||
|
# observability = {
|
||||||
|
# grafana.enable = true;
|
||||||
|
# prometheus.enable = true;
|
||||||
|
# loki.enable = true;
|
||||||
|
# promtail.enable = true;
|
||||||
|
# # uptime-kuma.enable = true;
|
||||||
|
# };
|
||||||
|
|
||||||
|
# security.vaultwarden = {
|
||||||
|
# enable = true;
|
||||||
|
# database = {
|
||||||
|
# # type = "sqlite";
|
||||||
|
# # file = "/var/lib/vaultwarden/state.db";
|
||||||
|
|
||||||
|
# type = "postgresql";
|
||||||
|
# host = "localhost";
|
||||||
|
# port = 5432;
|
||||||
|
# sslMode = "disabled";
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
|
||||||
|
# editor = {
|
||||||
|
# nano.enable = true;
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
}
|
||||||
20
machines/ulmo/hardware.nix
Normal file
20
machines/ulmo/hardware.nix
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
modulesPath,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (lib.modules) mkDefault;
|
||||||
|
in {
|
||||||
|
boot = {
|
||||||
|
initrd.availableKernelModules = ["xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod"];
|
||||||
|
initrd.kernelModules = [];
|
||||||
|
kernelModules = ["kvm-intel"];
|
||||||
|
kernelParams = [];
|
||||||
|
extraModulePackages = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
nixpkgs.hostPlatform = "x86_64-linux";
|
||||||
|
hardware.cpu.intel.updateMicrocode = mkDefault config.hardware.enableRedistributableFirmware;
|
||||||
|
}
|
||||||
3
machines/varda/configuration.nix
Normal file
3
machines/varda/configuration.nix
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{ ... }: {
|
||||||
|
nixpkgs.hostPlatform = "x86_64-linux";
|
||||||
|
}
|
||||||
3
machines/yavanna/configuration.nix
Normal file
3
machines/yavanna/configuration.nix
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{ ... }: {
|
||||||
|
nixpkgs.hostPlatform = "x86_64-linux";
|
||||||
|
}
|
||||||
19
modules/home/application/bitwarden.nix
Normal file
19
modules/home/application/bitwarden.nix
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
inputs,
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (lib) mkIf mkEnableOption;
|
||||||
|
|
||||||
|
cfg = config.sneeuwvlok.application.bitwarden;
|
||||||
|
in {
|
||||||
|
options.sneeuwvlok.application.bitwarden = {
|
||||||
|
enable = mkEnableOption "enable bitwarden";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
home.packages = with pkgs; [bitwarden-desktop];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
{ inputs, config, lib, pkgs, namespace, ... }:
|
|
||||||
let
|
|
||||||
inherit (lib) mkIf mkEnableOption;
|
|
||||||
|
|
||||||
cfg = config.${namespace}.application.bitwarden;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.${namespace}.application.bitwarden = {
|
|
||||||
enable = mkEnableOption "enable bitwarden";
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
home.packages = with pkgs; [ bitwarden-desktop ];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +1,15 @@
|
||||||
{ inputs, config, lib, pkgs, namespace, ... }:
|
{
|
||||||
let
|
inputs,
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
inherit (lib) mkIf mkEnableOption;
|
inherit (lib) mkIf mkEnableOption;
|
||||||
|
|
||||||
cfg = config.${namespace}.application.chrome;
|
cfg = config.sneeuwvlok.application.chrome;
|
||||||
in
|
in {
|
||||||
{
|
options.sneeuwvlok.application.chrome = {
|
||||||
options.${namespace}.application.chrome = {
|
|
||||||
enable = mkEnableOption "enable chrome";
|
enable = mkEnableOption "enable chrome";
|
||||||
};
|
};
|
||||||
|
|
||||||
19
modules/home/application/discord.nix
Normal file
19
modules/home/application/discord.nix
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
inputs,
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (lib) mkIf mkEnableOption;
|
||||||
|
|
||||||
|
cfg = config.sneeuwvlok.application.discord;
|
||||||
|
in {
|
||||||
|
options.sneeuwvlok.application.discord = {
|
||||||
|
enable = mkEnableOption "enable discord (vesktop)";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
home.packages = with pkgs; [vesktop];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
{ inputs, config, lib, pkgs, namespace, ... }:
|
|
||||||
let
|
|
||||||
inherit (lib) mkIf mkEnableOption;
|
|
||||||
|
|
||||||
cfg = config.${namespace}.application.discord;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.${namespace}.application.discord = {
|
|
||||||
enable = mkEnableOption "enable discord (vesktop)";
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
home.packages = with pkgs; [ vesktop ];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
19
modules/home/application/ladybird.nix
Normal file
19
modules/home/application/ladybird.nix
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
inputs,
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (lib) mkIf mkEnableOption;
|
||||||
|
|
||||||
|
cfg = config.sneeuwvlok.application.ladybird;
|
||||||
|
in {
|
||||||
|
options.sneeuwvlok.application.ladybird = {
|
||||||
|
enable = mkEnableOption "enable ladybird";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
home.packages = with pkgs; [ladybird];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
{ inputs, config, lib, pkgs, namespace, ... }:
|
|
||||||
let
|
|
||||||
inherit (lib) mkIf mkEnableOption;
|
|
||||||
|
|
||||||
cfg = config.${namespace}.application.ladybird;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.${namespace}.application.ladybird = {
|
|
||||||
enable = mkEnableOption "enable ladybird";
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
home.packages = with pkgs; [ ladybird ];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
23
modules/home/application/matix.nix
Normal file
23
modules/home/application/matix.nix
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
osConfig ? {},
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (lib) mkIf mkEnableOption;
|
||||||
|
|
||||||
|
cfg = config.sneeuwvlok.application.matrix;
|
||||||
|
in {
|
||||||
|
options.sneeuwvlok.application.matrix = {
|
||||||
|
enable = mkEnableOption "enable Matrix client (Fractal)";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
home.packages = with pkgs; [fractal element-desktop];
|
||||||
|
|
||||||
|
programs.element-desktop = {
|
||||||
|
enable = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
{ config, lib, pkgs, namespace, osConfig ? {}, ... }:
|
|
||||||
let
|
|
||||||
inherit (lib) mkIf mkEnableOption;
|
|
||||||
|
|
||||||
cfg = config.${namespace}.application.matrix;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.${namespace}.application.matrix = {
|
|
||||||
enable = mkEnableOption "enable Matrix client (Fractal)";
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
home.packages = with pkgs; [ fractal element-desktop ];
|
|
||||||
|
|
||||||
programs.element-desktop = {
|
|
||||||
enable = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +1,15 @@
|
||||||
{ config, lib, pkgs, namespace, osConfig ? {}, ... }:
|
{
|
||||||
let
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
osConfig ? {},
|
||||||
|
...
|
||||||
|
}: let
|
||||||
inherit (lib) mkIf mkEnableOption;
|
inherit (lib) mkIf mkEnableOption;
|
||||||
|
|
||||||
cfg = config.${namespace}.application.obs;
|
cfg = config.sneeuwvlok.application.obs;
|
||||||
in
|
in {
|
||||||
{
|
options.sneeuwvlok.application.obs = {
|
||||||
options.${namespace}.application.obs = {
|
|
||||||
enable = mkEnableOption "enable obs";
|
enable = mkEnableOption "enable obs";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -3,14 +3,13 @@
|
||||||
config,
|
config,
|
||||||
lib,
|
lib,
|
||||||
pkgs,
|
pkgs,
|
||||||
namespace,
|
|
||||||
...
|
...
|
||||||
}: let
|
}: let
|
||||||
inherit (lib) mkIf mkEnableOption;
|
inherit (lib) mkIf mkEnableOption;
|
||||||
|
|
||||||
cfg = config.${namespace}.application.onlyoffice;
|
cfg = config.sneeuwvlok.application.onlyoffice;
|
||||||
in {
|
in {
|
||||||
options.${namespace}.application.onlyoffice = {
|
options.sneeuwvlok.application.onlyoffice = {
|
||||||
enable = mkEnableOption "enable onlyoffice";
|
enable = mkEnableOption "enable onlyoffice";
|
||||||
};
|
};
|
||||||
|
|
||||||
19
modules/home/application/signal.nix
Normal file
19
modules/home/application/signal.nix
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
inputs,
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (lib) mkIf mkEnableOption;
|
||||||
|
|
||||||
|
cfg = config.sneeuwvlok.application.signal;
|
||||||
|
in {
|
||||||
|
options.sneeuwvlok.application.signal = {
|
||||||
|
enable = mkEnableOption "enable signal";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
home.packages = with pkgs; [signal-desktop];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
{ inputs, config, lib, pkgs, namespace, ... }:
|
|
||||||
let
|
|
||||||
inherit (lib) mkIf mkEnableOption;
|
|
||||||
|
|
||||||
cfg = config.${namespace}.application.signal;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.${namespace}.application.signal = {
|
|
||||||
enable = mkEnableOption "enable signal";
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
home.packages = with pkgs; [ signal-desktop ];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +1,15 @@
|
||||||
{ inputs, config, lib, pkgs, namespace, ... }:
|
{
|
||||||
let
|
inputs,
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
inherit (lib) mkIf mkEnableOption;
|
inherit (lib) mkIf mkEnableOption;
|
||||||
|
|
||||||
cfg = config.${namespace}.application.steam;
|
cfg = config.sneeuwvlok.application.steam;
|
||||||
in
|
in {
|
||||||
{
|
options.sneeuwvlok.application.steam = {
|
||||||
options.${namespace}.application.steam = {
|
|
||||||
enable = mkEnableOption "enable steam";
|
enable = mkEnableOption "enable steam";
|
||||||
};
|
};
|
||||||
|
|
||||||
18
modules/home/application/studio.nix
Normal file
18
modules/home/application/studio.nix
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
self,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (lib) mkIf mkEnableOption;
|
||||||
|
|
||||||
|
cfg = config.sneeuwvlok.application.studio;
|
||||||
|
in {
|
||||||
|
options.sneeuwvlok.application.studio = {
|
||||||
|
enable = mkEnableOption "enable Bricklink Studio";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
home.packages = [self.packages.studio];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
{ config, lib, pkgs, namespace, ... }:
|
|
||||||
let
|
|
||||||
inherit (lib) mkIf mkEnableOption;
|
|
||||||
|
|
||||||
cfg = config.${namespace}.application.studio;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.${namespace}.application.studio = {
|
|
||||||
enable = mkEnableOption "enable Bricklink Studio";
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
home.packages = with pkgs.${namespace}; [ studio ];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +1,15 @@
|
||||||
{ inputs, config, lib, pkgs, namespace, ... }:
|
{
|
||||||
let
|
inputs,
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
inherit (lib) mkIf mkEnableOption;
|
inherit (lib) mkIf mkEnableOption;
|
||||||
|
|
||||||
cfg = config.${namespace}.application.teamspeak;
|
cfg = config.sneeuwvlok.application.teamspeak;
|
||||||
in
|
in {
|
||||||
{
|
options.sneeuwvlok.application.teamspeak = {
|
||||||
options.${namespace}.application.teamspeak = {
|
|
||||||
enable = mkEnableOption "enable teamspeak";
|
enable = mkEnableOption "enable teamspeak";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1,11 +1,15 @@
|
||||||
{ inputs, config, lib, pkgs, namespace, ... }:
|
{
|
||||||
let
|
inputs,
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
inherit (lib) mkIf mkEnableOption;
|
inherit (lib) mkIf mkEnableOption;
|
||||||
|
|
||||||
cfg = config.${namespace}.application.thunderbird;
|
cfg = config.sneeuwvlok.application.thunderbird;
|
||||||
in
|
in {
|
||||||
{
|
options.sneeuwvlok.application.thunderbird = {
|
||||||
options.${namespace}.application.thunderbird = {
|
|
||||||
enable = mkEnableOption "enable thunderbird";
|
enable = mkEnableOption "enable thunderbird";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -14,7 +18,7 @@ in
|
||||||
enable = true;
|
enable = true;
|
||||||
package = pkgs.thunderbird-latest;
|
package = pkgs.thunderbird-latest;
|
||||||
|
|
||||||
profiles.${config.snowfallorg.user.name} = {
|
profiles.chris = {
|
||||||
isDefault = true;
|
isDefault = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -30,7 +34,7 @@ in
|
||||||
};
|
};
|
||||||
thunderbird = {
|
thunderbird = {
|
||||||
enable = true;
|
enable = true;
|
||||||
profiles = [ config.snowfallorg.user.name ];
|
profiles = ["chris"];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1,15 +1,14 @@
|
||||||
{ inputs, config, lib, pkgs, namespace, ... }:
|
{
|
||||||
let
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
inherit (lib) mkIf mkEnableOption;
|
inherit (lib) mkIf mkEnableOption;
|
||||||
|
|
||||||
cfg = config.${namespace}.application.zen;
|
cfg = config.sneeuwvlok.application.zen;
|
||||||
in
|
in {
|
||||||
{
|
options.sneeuwvlok.application.zen = {
|
||||||
imports = [
|
|
||||||
inputs.zen-browser.homeModules.default
|
|
||||||
];
|
|
||||||
|
|
||||||
options.${namespace}.application.zen = {
|
|
||||||
enable = mkEnableOption "enable zen";
|
enable = mkEnableOption "enable zen";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -54,8 +53,7 @@ in
|
||||||
install_url = "https://addons.mozilla.org/firefox/downloads/latest/${builtins.toString id}/latest.xpi";
|
install_url = "https://addons.mozilla.org/firefox/downloads/latest/${builtins.toString id}/latest.xpi";
|
||||||
installation_mode = "force_installed";
|
installation_mode = "force_installed";
|
||||||
};
|
};
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
ublock_origin = 4531307;
|
ublock_origin = 4531307;
|
||||||
ghostry = 4562168;
|
ghostry = 4562168;
|
||||||
bitwarden = 4562769;
|
bitwarden = 4562769;
|
||||||
|
|
@ -1,11 +1,15 @@
|
||||||
{ pkgs, config, lib, namespace, ... }:
|
{
|
||||||
let
|
pkgs,
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
inherit (lib) mkOption;
|
inherit (lib) mkOption;
|
||||||
inherit (lib.types) enum;
|
inherit (lib.types) enum;
|
||||||
|
|
||||||
cfg = config.${namespace}.defaults;
|
cfg = config.sneeuwvlok.defaults;
|
||||||
in {
|
in {
|
||||||
options.${namespace}.defaults = {
|
options.sneeuwvlok.defaults = {
|
||||||
editor = mkOption {
|
editor = mkOption {
|
||||||
type = enum ["nano" "nvim" "zed"];
|
type = enum ["nano" "nvim" "zed"];
|
||||||
default = "nano";
|
default = "nano";
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,15 @@
|
||||||
{ config, lib, namespace, osConfig ? {}, ... }:
|
{
|
||||||
let
|
config,
|
||||||
|
lib,
|
||||||
|
osConfig ? {},
|
||||||
|
...
|
||||||
|
}: let
|
||||||
inherit (lib) mkIf;
|
inherit (lib) mkIf;
|
||||||
|
|
||||||
cfg = config.${namespace}.desktop.plasma;
|
cfg = config.sneeuwvlok.desktop.plasma;
|
||||||
osCfg = osConfig.${namespace}.desktop.plasma or { enable = false; };
|
osCfg = osConfig.sneeuwvlok.desktop.plasma or {enable = false;};
|
||||||
in
|
in {
|
||||||
{
|
options.sneeuwvlok.desktop.plasma = {
|
||||||
options.${namespace}.desktop.plasma = {
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf osCfg.enable {
|
config = mkIf osCfg.enable {
|
||||||
|
|
|
||||||
18
modules/home/development/dotnet.nix
Normal file
18
modules/home/development/dotnet.nix
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (lib) mkEnableOption mkIf;
|
||||||
|
|
||||||
|
cfg = config.sneeuwvlok.development.dotnet;
|
||||||
|
in {
|
||||||
|
options.sneeuwvlok.development.dotnet = {
|
||||||
|
enable = mkEnableOption "Enable dotnet development tools";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
home.packages = with pkgs; [dotnet-sdk_8];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
{ config, lib, pkgs, namespace, ... }:
|
|
||||||
let
|
|
||||||
inherit (lib) mkEnableOption mkIf;
|
|
||||||
|
|
||||||
cfg = config.${namespace}.development.dotnet;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.${namespace}.development.dotnet = {
|
|
||||||
enable = mkEnableOption "Enable dotnet development tools";
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
home.packages = with pkgs; [ dotnet-sdk_8 ];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
18
modules/home/development/javascript.nix
Normal file
18
modules/home/development/javascript.nix
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (lib) mkEnableOption mkIf;
|
||||||
|
|
||||||
|
cfg = config.sneeuwvlok.development.javascript;
|
||||||
|
in {
|
||||||
|
options.sneeuwvlok.development.javascript = {
|
||||||
|
enable = mkEnableOption "Enable javascript development tools";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
home.packages = with pkgs; [bun nodejs nodePackages_latest.typescript-language-server];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
{ config, lib, pkgs, namespace, ... }:
|
|
||||||
let
|
|
||||||
inherit (lib) mkEnableOption mkIf;
|
|
||||||
|
|
||||||
cfg = config.${namespace}.development.javascript;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.${namespace}.development.javascript = {
|
|
||||||
enable = mkEnableOption "Enable javascript development tools";
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
home.packages = with pkgs; [ bun nodejs nodePackages_latest.typescript-language-server ];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
18
modules/home/development/rust.nix
Normal file
18
modules/home/development/rust.nix
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (lib) mkEnableOption mkIf;
|
||||||
|
|
||||||
|
cfg = config.sneeuwvlok.development.rust;
|
||||||
|
in {
|
||||||
|
options.sneeuwvlok.development.rust = {
|
||||||
|
enable = mkEnableOption "Enable rust development tools";
|
||||||
|
};
|
||||||
|
|
||||||
|
config =
|
||||||
|
mkIf cfg.enable {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
{ config, lib, pkgs, namespace, ... }:
|
|
||||||
let
|
|
||||||
inherit (lib) mkEnableOption mkIf;
|
|
||||||
|
|
||||||
cfg = config.${namespace}.development.rust;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.${namespace}.development.rust = {
|
|
||||||
enable = mkEnableOption "Enable rust development tools";
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +1,15 @@
|
||||||
{ config, options, lib, pkgs, namespace, ... }:
|
{
|
||||||
let
|
config,
|
||||||
|
options,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
inherit (lib) mkEnableOption mkIf;
|
inherit (lib) mkEnableOption mkIf;
|
||||||
|
|
||||||
cfg = config.${namespace}.editor.nano;
|
cfg = config.sneeuwvlok.editor.nano;
|
||||||
in
|
in {
|
||||||
{
|
options.sneeuwvlok.editor.nano = {
|
||||||
options.${namespace}.editor.nano = {
|
|
||||||
enable = mkEnableOption "nano";
|
enable = mkEnableOption "nano";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1,15 +1,19 @@
|
||||||
{ inputs, config, lib, pkgs, namespace, ... }:
|
{
|
||||||
let
|
inputs,
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
inherit (lib) mkIf mkEnableOption;
|
inherit (lib) mkIf mkEnableOption;
|
||||||
|
|
||||||
cfg = config.${namespace}.editor.nvim;
|
cfg = config.sneeuwvlok.editor.nvim;
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
# imports = [
|
# imports = [
|
||||||
# inputs.nvf.nixosModules.default
|
# inputs.nvf.nixosModules.default
|
||||||
# ];
|
# ];
|
||||||
|
|
||||||
options.${namespace}.editor.nvim = {
|
options.sneeuwvlok.editor.nvim = {
|
||||||
enable = mkEnableOption "enable nvim via nvf on user level";
|
enable = mkEnableOption "enable nvim via nvf on user level";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1,15 +1,23 @@
|
||||||
{ config, lib, pkgs, namespace, ... }: let
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
inherit (lib) mkIf mkEnableOption;
|
inherit (lib) mkIf mkEnableOption;
|
||||||
|
|
||||||
cfg = config.${namespace}.editor.zed;
|
cfg = config.sneeuwvlok.editor.zed;
|
||||||
in {
|
in {
|
||||||
options.${namespace}.editor.zed = {
|
options.sneeuwvlok.editor.zed = {
|
||||||
enable = mkEnableOption "zed";
|
enable = mkEnableOption "zed";
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
home.packages = with pkgs; [
|
home.packages = with pkgs; [
|
||||||
zed-editor nixd nil alejandra
|
zed-editor
|
||||||
|
nixd
|
||||||
|
nil
|
||||||
|
alejandra
|
||||||
];
|
];
|
||||||
|
|
||||||
programs.zed-editor = {
|
programs.zed-editor = {
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
{ inputs, config, lib, pkgs, namespace, ... }:
|
|
||||||
let
|
|
||||||
inherit (lib) mkIf mkEnableOption;
|
|
||||||
|
|
||||||
cfg = config.${namespace}.game.minecraft;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.${namespace}.game.minecraft = {
|
|
||||||
enable = mkEnableOption "enable minecraft";
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
home.packages = with pkgs; [ prismlauncher ];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
19
modules/home/game/minescraft.nix
Normal file
19
modules/home/game/minescraft.nix
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
inputs,
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (lib) mkIf mkEnableOption;
|
||||||
|
|
||||||
|
cfg = config.sneeuwvlok.game.minecraft;
|
||||||
|
in {
|
||||||
|
options.sneeuwvlok.game.minecraft = {
|
||||||
|
enable = mkEnableOption "enable minecraft";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
home.packages = with pkgs; [prismlauncher];
|
||||||
|
};
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue