diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index a614018..c8b0bd8 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -56,6 +56,14 @@ function themeConfigEnglish() {return { { text: "Examples", link: "/modules/examples" } ], }, + { + text: "Hosts", + items: [ + { text: "Introduction", link: "/hosts/introduction" }, + { text: "Structure", link: "/hosts/structure" }, + { text: "Examples", link: "/hosts/examples" } + ], + }, ], } }} @@ -92,6 +100,14 @@ function themeConfigRussian() {return { { text: "Примеры", link: "/ru/modules/examples" } ], }, + { + text: "Хосты", + items: [ + { text: "Вступление", link: "/ru/hosts/introduction" }, + { text: "Структура", link: "/ru/hosts/structure" }, + { text: "Примеры", link: "/ru/hosts/examples" } + ], + }, ], } }} diff --git a/docs/src/hosts/examples.md b/docs/src/hosts/examples.md new file mode 100644 index 0000000..673bcee --- /dev/null +++ b/docs/src/hosts/examples.md @@ -0,0 +1,109 @@ +# Examples {#examples} + +## Minimally Recommended Host Module: {#minimally-recommended} +An example of a minimal host module configuration that serves as a baseline for all further settings: + +```nix +delib.module { + name = "hosts"; + + options = with delib; let + host = { + options = hostSubmoduleOptions; + }; + in { + host = hostOption host; + hosts = hostsOption host; + }; + + home.always = {myconfig, ...}: { + assertions = delib.hostNamesAssertions myconfig.hosts; + }; +} +``` + +## With the `type` Option {#type-option} +The `type` option **is very** useful for default values in your modules. For example, the option `enable = boolOption host.isDesktop` can be used for some GUI programs. This simplifies configuration management based on the type of device. + +```nix +delib.module { + name = "hosts"; + + options = with delib; let + host = {config, ...}: { + options = + hostSubmoduleOptions + // { + type = noDefault (enumOption ["desktop" "server"] null); + + isDesktop = boolOption (config.type == "desktop"); + isServer = boolOption (config.type == "server"); + }; + }; + in { + host = hostOption host; + hosts = hostsOption host; + }; + + home.always = {myconfig, ...}: { + assertions = delib.hostNamesAssertions myconfig.hosts; + }; +} +``` + +## With the `displays` Option {#displays-option} +This option can be useful for configuring monitors; however, it can be implemented as a separate module. + +```nix +delib.module { + name = "hosts"; + + options = with delib; let + host = {config, ...}: { + options = + hostSubmoduleOptions + // { + displays = listOfOption (submodule { + options = { + enable = boolOption true; + touchscreen = boolOption false; + + # e.g. DP-1, HDMI-A-1 + name = noDefault (strOption null); + primary = boolOption (builtins.length config.displays == 1); + refreshRate = intOption 60; + + width = intOption 1920; + height = intOption 1080; + x = intOption 0; + y = intOption 0; + }; + }) []; + }; + }; + in { + host = hostOption host; + hosts = hostsOption host; + }; + + home.always = {myconfig, ...}: { + assertions = delib.hostNamesAssertions myconfig.hosts; + }; +} +``` + +## Short Version {#short-version} +Using `delib.hostNamesAssertions` is strongly recommended, but it can also be omitted. + +```nix +delib.module { + name = "hosts"; + + options = with delib; let + host.options = hostSubmoduleOptions; + in { + host = hostOption host; + hosts = hostsOption host; + }; +} +``` diff --git a/docs/src/hosts/introduction.md b/docs/src/hosts/introduction.md new file mode 100644 index 0000000..4a958aa --- /dev/null +++ b/docs/src/hosts/introduction.md @@ -0,0 +1,32 @@ +# Introduction to Denix Hosts {#introduction} +A Denix host is an attribute set returned by the function [`delib.host`](/hosts/structure), which enables or disables specific configurations depending on the value of the option `${myconfigName}.host`. It also passes the incoming attribute set to the `delib.host` function in the option `${myconfigName}.hosts.${delib.host :: name}`. + +In simple terms, this allows you to separate the NixOS, Home Manager, and custom options configuration into those that apply only to the current host and those that apply to all hosts. For example, the former can be used to enable or disable certain programs, while the latter can be used to add the current host's SSH key to the `authorizedKeys` of all hosts. + +A host can also be compared to a module, because all hosts are imported regardless of which one is active, but the applied configurations depend on the active host. + +## Options {#options} +For hosts to work, the configuration must include the options `${myconfigName}.host` and `${myconfigName}.hosts`, which **you define yourself** in one of the modules. + +Here is an example of a minimal recommended host configuration: + +```nix +delib.module { + name = "hosts"; + + options = with delib; let + host = { + options = hostSubmoduleOptions; + }; + in { + host = hostOption host; + hosts = hostsOption host; + }; + + home.always = {myconfig, ...}: { + assertions = delib.hostNamesAssertions myconfig.hosts; + }; +} +``` + +More examples can be found in the [Examples](/hosts/examples) section. diff --git a/docs/src/hosts/structure.md b/docs/src/hosts/structure.md new file mode 100644 index 0000000..42ce760 --- /dev/null +++ b/docs/src/hosts/structure.md @@ -0,0 +1,50 @@ +# Structure {#structure} + +## Function Arguments {#function-arguments} +- `name`: a string representing the host name. +- `myconfig`: sets its value to `config.${myconfigName}` if `config.${myconfigName}.host` matches the current host. +- `nixos`: sets its value to `config` if `isHomeManager` is `false` and `config.${myconfigName}.host` matches the current host. +- `home`: sets its value to `config` if `isHomeManager` is `true` and `config.${myconfigName}.host` matches the current host. Otherwise, if `config.${myconfigName}.host` matches the current host, sets its value to `config.home-manager.users.${homeManagerUser}`. +- `shared.myconfig`: sets its value to `config.${myconfigName}` for all hosts. +- `shared.nixos`: sets its value to `config` if `isHomeManager` is `false`. Otherwise, does nothing. +- `shared.home`: sets its value to `config` if `isHomeManager` is `true`. Otherwise, sets it to `config.home-manager.users.${homeManagerUser}`. + +## Passed Arguments {#passed-arguments} +A list of arguments passed to `?(shared.)[myconfig|nixos|home]` if their type is `lambda`: +- `name`: the same `name` as in the arguments of `delib.module`. +- `myconfig`: equals `config.${myConfigName}`. +- `cfg`: equals `config.${myConfigName}.hosts.${delib.host :: name}`. + +## Pseudocode {#pseudocode} +```nix +delib.host { + name = ""; + # if config.${myconfigName}.host == name + # then {config.${myConfigName} = ...;} + # else {} + myconfig = {name, cfg, myconfig, ...}: {}; + + # if config.${myconfigName}.host == name + # then {config = ...;} + # else {} + nixos = {name, cfg, myconfig, ...}: {}; + + # if config.${myconfigName}.host == name, then + # if isHomeManager + # then {config = ...;} + # else {config.home-manager.users.${homeManagerUser} = ...;} + # else {} + home = {name, cfg, myconfig, ...}: {}; + + # config.${myConfigName} = ... + shared.myconfig = {name, cfg, myconfig, ...}: {}; + + # config = ... + shared.nixos = {name, cfg, myconfig, ...}: {}; + + # if isHomeManager + # then {} + # else {config = ...;} + shared.home = {name, cfg, myconfig, ...}: {}; +} +``` diff --git a/docs/src/ru/hosts/examples.md b/docs/src/ru/hosts/examples.md new file mode 100644 index 0000000..741c5ee --- /dev/null +++ b/docs/src/ru/hosts/examples.md @@ -0,0 +1,109 @@ +# Примеры {#examples} + +## Минимально рекомендуемый модуль хостов: {#minimally-recommended} +Пример минимальной конфигурации модуля хостов, который является базовой точкой для всех дальнейших настроек: + +```nix +delib.module { + name = "hosts"; + + options = with delib; let + host = { + options = hostSubmoduleOptions; + }; + in { + host = hostOption host; + hosts = hostsOption host; + }; + + home.always = {myconfig, ...}: { + assertions = delib.hostNamesAssertions myconfig.hosts; + }; +} +``` + +## С опцией `type` {#type-option} +Опция `type` **очень** полезна для задания значений по умолчанию в своих модулях. Например, опция `enable = boolOption host.isDesktop` может использоваться для какой-нибудь GUI программы. Это упрощает управление конфигурациями в зависимости от типа устройства. + +```nix +delib.module { + name = "hosts"; + + options = with delib; let + host = {config, ...}: { + options = + hostSubmoduleOptions + // { + type = noDefault (enumOption ["desktop" "server"] null); + + isDesktop = boolOption (config.type == "desktop"); + isServer = boolOption (config.type == "server"); + }; + }; + in { + host = hostOption host; + hosts = hostsOption host; + }; + + home.always = {myconfig, ...}: { + assertions = delib.hostNamesAssertions myconfig.hosts; + }; +} +``` + +## С опцией `displays` {#displays-option} +Эта опция может быть полезна для настройки мониторов, однако её можно реализовать как отдельный модуль. + +```nix +delib.module { + name = "hosts"; + + options = with delib; let + host = {config, ...}: { + options = + hostSubmoduleOptions + // { + displays = listOfOption (submodule { + options = { + enable = boolOption true; + touchscreen = boolOption false; + + # e.g. DP-1, HDMI-A-1 + name = noDefault (strOption null); + primary = boolOption (builtins.length config.displays == 1); + refreshRate = intOption 60; + + width = intOption 1920; + height = intOption 1080; + x = intOption 0; + y = intOption 0; + }; + }) []; + }; + }; + in { + host = hostOption host; + hosts = hostsOption host; + }; + + home.always = {myconfig, ...}: { + assertions = delib.hostNamesAssertions myconfig.hosts; + }; +} +``` + +## Краткая версия {#short-version} +Использование `delib.hostNamesAssertions` настоятельно рекомендуется, но можно обойтись и без него: + +```nix +delib.module { + name = "hosts"; + + options = with delib; let + host.options = hostSubmoduleOptions; + in { + host = hostOption host; + hosts = hostsOption host; + }; +} +``` diff --git a/docs/src/ru/hosts/introduction.md b/docs/src/ru/hosts/introduction.md new file mode 100644 index 0000000..458c296 --- /dev/null +++ b/docs/src/ru/hosts/introduction.md @@ -0,0 +1,32 @@ +# Введение в хосты Denix {#introduction} +Хост (host) Denix - это attribute set, возвращаемый функцией [`delib.host`](/ru/hosts/structure), который включает или отключает определенные конфигурации в зависимости от значения опции `${myconfigName}.host`. Также он передает входящий `attribute set` в функцию `delib.host` в опцию `${myconfigName}.hosts.${delib.host :: name}`. + +Простыми словами, это позволяет разделить конфигурацию NixOS, Home Manager и собственных опций на те, которые применяются только к текущему хосту, и те, которые применяются ко всем хостам. Например, первое может использоваться для включения или отключения определенных программ, а второе - для добавления SSH-ключа текущего хоста в `authorizedKeys` всех хостов. + +Хост также можно сравнить с модулем, потому что все хосты импортируются независимо от того, какой из них активен, но применяемые конфигурации зависят от активного хоста. + +## Опции {#options} +Для работы хостов конфигурация должна включать опции `${myconfigName}.host` и `${myconfigName}.hosts`, которые **вы задаете самостоятельно** в одном из модулей. + +Пример минимальной рекомендуемой конфигурации хостов: + +```nix +delib.module { + name = "hosts"; + + options = with delib; let + host = { + options = hostSubmoduleOptions; + }; + in { + host = hostOption host; + hosts = hostsOption host; + }; + + home.always = {myconfig, ...}: { + assertions = delib.hostNamesAssertions myconfig.hosts; + }; +} +``` + +Другие примеры можно найти в разделе [Примеры](/ru/hosts/examples). diff --git a/docs/src/ru/hosts/structure.md b/docs/src/ru/hosts/structure.md new file mode 100644 index 0000000..2c2ea61 --- /dev/null +++ b/docs/src/ru/hosts/structure.md @@ -0,0 +1,52 @@ +# Структура {#structure} + +## Аргументы функции {#function-arguments} +- `name`: строка, представляющая имя хоста. +- `myconfig`: устанавливает её значение в `config.${myconfigName}`, если `config.${myconfigName}.host` соответствует текущему хосту. +- `nixos`: устанавливает её значение в `config`, если `isHomeManager` равен `false` и `config.${myconfigName}.host` соответствует текущему хосту. +- `home`: устанавливает её значение в `config`, если `isHomeManager` равен `true` и `config.${myconfigName}.host` соответствует текущему хосту. В противном случае, если `config.${myconfigName}.host` соответствует текущему хосту, устанавливает её значение в `config.home-manager.users.${homeManagerUser}`. +- `shared.myconfig`: устанавливает её значение в `config.${myconfigName}` для всех хостов. +- `shared.nixos`: устанавливает её значение в `config`, если `isHomeManager` равен `false`. В противном случае, не выполняется. +- `shared.home`: устанавливает её значение в `config`, если `isHomeManager` равен `true`. В противном случае, устанавливает в `config.home-manager.users.${homeManagerUser}`. + +## Передаваемые аргументы {#passed-arguments} +Список аргументов, которые передаются в `?(shared.)[myconfig|nixos|home]`, если их тип - `lambda`: + +- `name`: тот же `name`, что и в аргументах `delib.module`. +- `myconfig`: равен `config.${myConfigName}`. +- `cfg`: равен `config.${myConfigName}.hosts.${delib.host :: name}`. + +## Псевдокод {#pseudocode} +```nix +delib.host { + name = ""; + + # если config.${myconfigName}.host == name + # то {config.${myConfigName} = ...;} + # иначе {} + myconfig = {name, cfg, myconfig, ...}: {}; + + # если config.${myconfigName}.host == name + # то {config = ...;} + # иначе {} + nixos = {name, cfg, myconfig, ...}: {}; + + # если config.${myconfigName}.host == name, то + # если isHomeManager + # то {config = ...;} + # иначе {config.home-manager.users.${homeManagerUser} = ...;} + # иначе {} + home = {name, cfg, myconfig, ...}: {}; + + # config.${myConfigName} = ... + shared.myconfig = {name, cfg, myconfig, ...}: {}; + + # config = ... + shared.nixos = {name, cfg, myconfig, ...}: {}; + + # если isHomeManager + # то {} + # иначе {config = ...;} + shared.home = {name, cfg, myconfig, ...}: {}; +} +```