0
0
Fork 0
mirror of https://github.com/NixOS/nixpkgs.git synced 2025-07-13 21:50:33 +03:00

treewide/nixos: remove with lib; part 2 (#335618)

This commit is contained in:
Philip Taron 2024-08-30 15:56:57 -07:00 committed by GitHub
commit 9916dc8728
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
143 changed files with 2196 additions and 2601 deletions

View file

@ -1,26 +1,23 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
{ {
###### interface ###### interface
options = { options = {
i18n = { i18n = {
glibcLocales = mkOption { glibcLocales = lib.mkOption {
type = types.path; type = lib.types.path;
default = pkgs.glibcLocales.override { default = pkgs.glibcLocales.override {
allLocales = any (x: x == "all") config.i18n.supportedLocales; allLocales = lib.any (x: x == "all") config.i18n.supportedLocales;
locales = config.i18n.supportedLocales; locales = config.i18n.supportedLocales;
}; };
defaultText = literalExpression '' defaultText = lib.literalExpression ''
pkgs.glibcLocales.override { pkgs.glibcLocales.override {
allLocales = any (x: x == "all") config.i18n.supportedLocales; allLocales = any (x: x == "all") config.i18n.supportedLocales;
locales = config.i18n.supportedLocales; locales = config.i18n.supportedLocales;
} }
''; '';
example = literalExpression "pkgs.glibcLocales"; example = lib.literalExpression "pkgs.glibcLocales";
description = '' description = ''
Customized pkg.glibcLocales package. Customized pkg.glibcLocales package.
@ -29,8 +26,8 @@ with lib;
''; '';
}; };
defaultLocale = mkOption { defaultLocale = lib.mkOption {
type = types.str; type = lib.types.str;
default = "en_US.UTF-8"; default = "en_US.UTF-8";
example = "nl_NL.UTF-8"; example = "nl_NL.UTF-8";
description = '' description = ''
@ -40,8 +37,8 @@ with lib;
''; '';
}; };
extraLocaleSettings = mkOption { extraLocaleSettings = lib.mkOption {
type = types.attrsOf types.str; type = lib.types.attrsOf lib.types.str;
default = {}; default = {};
example = { LC_MESSAGES = "en_US.UTF-8"; LC_TIME = "de_DE.UTF-8"; }; example = { LC_MESSAGES = "en_US.UTF-8"; LC_TIME = "de_DE.UTF-8"; };
description = '' description = ''
@ -51,24 +48,24 @@ with lib;
''; '';
}; };
supportedLocales = mkOption { supportedLocales = lib.mkOption {
type = types.listOf types.str; type = lib.types.listOf lib.types.str;
default = unique default = lib.unique
(builtins.map (l: (replaceStrings [ "utf8" "utf-8" "UTF8" ] [ "UTF-8" "UTF-8" "UTF-8" ] l) + "/UTF-8") ( (builtins.map (l: (lib.replaceStrings [ "utf8" "utf-8" "UTF8" ] [ "UTF-8" "UTF-8" "UTF-8" ] l) + "/UTF-8") (
[ [
"C.UTF-8" "C.UTF-8"
"en_US.UTF-8" "en_US.UTF-8"
config.i18n.defaultLocale config.i18n.defaultLocale
] ++ (attrValues (filterAttrs (n: v: n != "LANGUAGE") config.i18n.extraLocaleSettings)) ] ++ (lib.attrValues (lib.filterAttrs (n: v: n != "LANGUAGE") config.i18n.extraLocaleSettings))
)); ));
defaultText = literalExpression '' defaultText = lib.literalExpression ''
unique lib.unique
(builtins.map (l: (replaceStrings [ "utf8" "utf-8" "UTF8" ] [ "UTF-8" "UTF-8" "UTF-8" ] l) + "/UTF-8") ( (builtins.map (l: (lib.replaceStrings [ "utf8" "utf-8" "UTF8" ] [ "UTF-8" "UTF-8" "UTF-8" ] l) + "/UTF-8") (
[ [
"C.UTF-8" "C.UTF-8"
"en_US.UTF-8" "en_US.UTF-8"
config.i18n.defaultLocale config.i18n.defaultLocale
] ++ (attrValues (filterAttrs (n: v: n != "LANGUAGE") config.i18n.extraLocaleSettings)) ] ++ (lib.attrValues (lib.filterAttrs (n: v: n != "LANGUAGE") config.i18n.extraLocaleSettings))
)) ))
''; '';
example = ["en_US.UTF-8/UTF-8" "nl_NL.UTF-8/UTF-8" "nl_NL/ISO-8859-1"]; example = ["en_US.UTF-8/UTF-8" "nl_NL.UTF-8/UTF-8" "nl_NL/ISO-8859-1"];
@ -91,14 +88,14 @@ with lib;
environment.systemPackages = environment.systemPackages =
# We increase the priority a little, so that plain glibc in systemPackages can't win. # We increase the priority a little, so that plain glibc in systemPackages can't win.
optional (config.i18n.supportedLocales != []) (lib.setPrio (-1) config.i18n.glibcLocales); lib.optional (config.i18n.supportedLocales != []) (lib.setPrio (-1) config.i18n.glibcLocales);
environment.sessionVariables = environment.sessionVariables =
{ LANG = config.i18n.defaultLocale; { LANG = config.i18n.defaultLocale;
LOCALE_ARCHIVE = "/run/current-system/sw/lib/locale/locale-archive"; LOCALE_ARCHIVE = "/run/current-system/sw/lib/locale/locale-archive";
} // config.i18n.extraLocaleSettings; } // config.i18n.extraLocaleSettings;
systemd.globalEnvironment = mkIf (config.i18n.supportedLocales != []) { systemd.globalEnvironment = lib.mkIf (config.i18n.supportedLocales != []) {
LOCALE_ARCHIVE = "${config.i18n.glibcLocales}/lib/locale/locale-archive"; LOCALE_ARCHIVE = "${config.i18n.glibcLocales}/lib/locale/locale-archive";
}; };
@ -106,7 +103,7 @@ with lib;
environment.etc."locale.conf".source = pkgs.writeText "locale.conf" environment.etc."locale.conf".source = pkgs.writeText "locale.conf"
'' ''
LANG=${config.i18n.defaultLocale} LANG=${config.i18n.defaultLocale}
${concatStringsSep "\n" (mapAttrsToList (n: v: "${n}=${v}") config.i18n.extraLocaleSettings)} ${lib.concatStringsSep "\n" (lib.mapAttrsToList (n: v: "${n}=${v}") config.i18n.extraLocaleSettings)}
''; '';
}; };

View file

@ -1,10 +1,6 @@
# This module defines a global environment configuration and # This module defines a global environment configuration and
# a common configuration for all shells. # a common configuration for all shells.
{ config, lib, utils, pkgs, ... }: { config, lib, utils, pkgs, ... }:
with lib;
let let
cfg = config.environment; cfg = config.environment;
@ -12,27 +8,27 @@ let
exportedEnvVars = exportedEnvVars =
let let
absoluteVariables = absoluteVariables =
mapAttrs (n: toList) cfg.variables; lib.mapAttrs (n: lib.toList) cfg.variables;
suffixedVariables = suffixedVariables =
flip mapAttrs cfg.profileRelativeEnvVars (envVar: listSuffixes: lib.flip lib.mapAttrs cfg.profileRelativeEnvVars (envVar: listSuffixes:
concatMap (profile: map (suffix: "${profile}${suffix}") listSuffixes) cfg.profiles lib.concatMap (profile: map (suffix: "${profile}${suffix}") listSuffixes) cfg.profiles
); );
allVariables = allVariables =
zipAttrsWith (n: concatLists) [ absoluteVariables suffixedVariables ]; lib.zipAttrsWith (n: lib.concatLists) [ absoluteVariables suffixedVariables ];
exportVariables = exportVariables =
mapAttrsToList (n: v: ''export ${n}="${concatStringsSep ":" v}"'') allVariables; lib.mapAttrsToList (n: v: ''export ${n}="${lib.concatStringsSep ":" v}"'') allVariables;
in in
concatStringsSep "\n" exportVariables; lib.concatStringsSep "\n" exportVariables;
in in
{ {
options = { options = {
environment.variables = mkOption { environment.variables = lib.mkOption {
default = {}; default = {};
example = { EDITOR = "nvim"; VISUAL = "nvim"; }; example = { EDITOR = "nvim"; VISUAL = "nvim"; };
description = '' description = ''
@ -42,22 +38,22 @@ in
strings. The latter is concatenated, interspersed with colon strings. The latter is concatenated, interspersed with colon
characters. characters.
''; '';
type = with types; attrsOf (oneOf [ (listOf (oneOf [ int str path ])) int str path ]); type = with lib.types; attrsOf (oneOf [ (listOf (oneOf [ int str path ])) int str path ]);
apply = let apply = let
toStr = v: if isPath v then "${v}" else toString v; toStr = v: if lib.isPath v then "${v}" else toString v;
in mapAttrs (n: v: if isList v then concatMapStringsSep ":" toStr v else toStr v); in lib.mapAttrs (n: v: if lib.isList v then lib.concatMapStringsSep ":" toStr v else toStr v);
}; };
environment.profiles = mkOption { environment.profiles = lib.mkOption {
default = []; default = [];
description = '' description = ''
A list of profiles used to setup the global environment. A list of profiles used to setup the global environment.
''; '';
type = types.listOf types.str; type = lib.types.listOf lib.types.str;
}; };
environment.profileRelativeEnvVars = mkOption { environment.profileRelativeEnvVars = lib.mkOption {
type = types.attrsOf (types.listOf types.str); type = lib.types.attrsOf (lib.types.listOf lib.types.str);
example = { PATH = [ "/bin" ]; MANPATH = [ "/man" "/share/man" ]; }; example = { PATH = [ "/bin" ]; MANPATH = [ "/man" "/share/man" ]; };
description = '' description = ''
Attribute set of environment variable. Each attribute maps to a list Attribute set of environment variable. Each attribute maps to a list
@ -68,7 +64,7 @@ in
}; };
# !!! isn't there a better way? # !!! isn't there a better way?
environment.extraInit = mkOption { environment.extraInit = lib.mkOption {
default = ""; default = "";
description = '' description = ''
Shell script code called during global environment initialisation Shell script code called during global environment initialisation
@ -76,40 +72,40 @@ in
This code is assumed to be shell-independent, which means you should This code is assumed to be shell-independent, which means you should
stick to pure sh without sh word split. stick to pure sh without sh word split.
''; '';
type = types.lines; type = lib.types.lines;
}; };
environment.shellInit = mkOption { environment.shellInit = lib.mkOption {
default = ""; default = "";
description = '' description = ''
Shell script code called during shell initialisation. Shell script code called during shell initialisation.
This code is assumed to be shell-independent, which means you should This code is assumed to be shell-independent, which means you should
stick to pure sh without sh word split. stick to pure sh without sh word split.
''; '';
type = types.lines; type = lib.types.lines;
}; };
environment.loginShellInit = mkOption { environment.loginShellInit = lib.mkOption {
default = ""; default = "";
description = '' description = ''
Shell script code called during login shell initialisation. Shell script code called during login shell initialisation.
This code is assumed to be shell-independent, which means you should This code is assumed to be shell-independent, which means you should
stick to pure sh without sh word split. stick to pure sh without sh word split.
''; '';
type = types.lines; type = lib.types.lines;
}; };
environment.interactiveShellInit = mkOption { environment.interactiveShellInit = lib.mkOption {
default = ""; default = "";
description = '' description = ''
Shell script code called during interactive shell initialisation. Shell script code called during interactive shell initialisation.
This code is assumed to be shell-independent, which means you should This code is assumed to be shell-independent, which means you should
stick to pure sh without sh word split. stick to pure sh without sh word split.
''; '';
type = types.lines; type = lib.types.lines;
}; };
environment.shellAliases = mkOption { environment.shellAliases = lib.mkOption {
example = { l = null; ll = "ls -l"; }; example = { l = null; ll = "ls -l"; };
description = '' description = ''
An attribute set that maps aliases (the top level attribute names in An attribute set that maps aliases (the top level attribute names in
@ -117,30 +113,30 @@ in
aliases are added to all users' shells. aliases are added to all users' shells.
Aliases mapped to `null` are ignored. Aliases mapped to `null` are ignored.
''; '';
type = with types; attrsOf (nullOr (either str path)); type = with lib.types; attrsOf (nullOr (either str path));
}; };
environment.homeBinInPath = mkOption { environment.homeBinInPath = lib.mkOption {
description = '' description = ''
Include ~/bin/ in $PATH. Include ~/bin/ in $PATH.
''; '';
default = false; default = false;
type = types.bool; type = lib.types.bool;
}; };
environment.localBinInPath = mkOption { environment.localBinInPath = lib.mkOption {
description = '' description = ''
Add ~/.local/bin/ to $PATH Add ~/.local/bin/ to $PATH
''; '';
default = false; default = false;
type = types.bool; type = lib.types.bool;
}; };
environment.binsh = mkOption { environment.binsh = lib.mkOption {
default = "${config.system.build.binsh}/bin/sh"; default = "${config.system.build.binsh}/bin/sh";
defaultText = literalExpression ''"''${config.system.build.binsh}/bin/sh"''; defaultText = lib.literalExpression ''"''${config.system.build.binsh}/bin/sh"'';
example = literalExpression ''"''${pkgs.dash}/bin/dash"''; example = lib.literalExpression ''"''${pkgs.dash}/bin/dash"'';
type = types.path; type = lib.types.path;
visible = false; visible = false;
description = '' description = ''
The shell executable that is linked system-wide to The shell executable that is linked system-wide to
@ -150,15 +146,15 @@ in
''; '';
}; };
environment.shells = mkOption { environment.shells = lib.mkOption {
default = []; default = [];
example = literalExpression "[ pkgs.bashInteractive pkgs.zsh ]"; example = lib.literalExpression "[ pkgs.bashInteractive pkgs.zsh ]";
description = '' description = ''
A list of permissible login shells for user accounts. A list of permissible login shells for user accounts.
No need to mention `/bin/sh` No need to mention `/bin/sh`
here, it is placed into this list implicitly. here, it is placed into this list implicitly.
''; '';
type = types.listOf (types.either types.shellPackage types.path); type = lib.types.listOf (lib.types.either lib.types.shellPackage lib.types.path);
}; };
}; };
@ -175,7 +171,7 @@ in
environment.profileRelativeEnvVars = config.environment.profileRelativeSessionVariables; environment.profileRelativeEnvVars = config.environment.profileRelativeSessionVariables;
environment.shellAliases = mapAttrs (name: mkDefault) { environment.shellAliases = lib.mapAttrs (name: lib.mkDefault) {
ls = "ls --color=tty"; ls = "ls --color=tty";
ll = "ls -l"; ll = "ls -l";
l = "ls -alh"; l = "ls -alh";
@ -183,7 +179,7 @@ in
environment.etc.shells.text = environment.etc.shells.text =
'' ''
${concatStringsSep "\n" (map utils.toShellPath cfg.shells)} ${lib.concatStringsSep "\n" (map utils.toShellPath cfg.shells)}
/bin/sh /bin/sh
''; '';
@ -202,17 +198,17 @@ in
${cfg.extraInit} ${cfg.extraInit}
${optionalString cfg.homeBinInPath '' ${lib.optionalString cfg.homeBinInPath ''
# ~/bin if it exists overrides other bin directories. # ~/bin if it exists overrides other bin directories.
export PATH="$HOME/bin:$PATH" export PATH="$HOME/bin:$PATH"
''} ''}
${optionalString cfg.localBinInPath '' ${lib.optionalString cfg.localBinInPath ''
export PATH="$HOME/.local/bin:$PATH" export PATH="$HOME/.local/bin:$PATH"
''} ''}
''; '';
system.activationScripts.binsh = stringAfter [ "stdio" ] system.activationScripts.binsh = lib.stringAfter [ "stdio" ]
'' ''
# Create the required /bin/sh symlink; otherwise lots of things # Create the required /bin/sh symlink; otherwise lots of things
# (notably the system() function) won't work. # (notably the system() function) won't work.

View file

@ -1,17 +1,14 @@
{ config, lib, ... }: { config, lib, ... }:
with lib;
let let
sysctlOption = mkOptionType { sysctlOption = lib.mkOptionType {
name = "sysctl option value"; name = "sysctl option value";
check = val: check = val:
let let
checkType = x: isBool x || isString x || isInt x || x == null; checkType = x: lib.isBool x || lib.isString x || lib.isInt x || x == null;
in in
checkType val || (val._type or "" == "override" && checkType val.content); checkType val || (val._type or "" == "override" && checkType val.content);
merge = loc: defs: mergeOneOption loc (filterOverrides defs); merge = loc: defs: lib.mergeOneOption loc (lib.filterOverrides defs);
}; };
in in
@ -20,33 +17,33 @@ in
options = { options = {
boot.kernel.sysctl = mkOption { boot.kernel.sysctl = lib.mkOption {
type = let type = let
highestValueType = types.ints.unsigned // { highestValueType = lib.types.ints.unsigned // {
merge = loc: defs: merge = loc: defs:
foldl lib.foldl
(a: b: if b.value == null then null else lib.max a b.value) (a: b: if b.value == null then null else lib.max a b.value)
0 0
(filterOverrides defs); (lib.filterOverrides defs);
}; };
in types.submodule { in lib.types.submodule {
freeformType = types.attrsOf sysctlOption; freeformType = lib.types.attrsOf sysctlOption;
options = { options = {
"net.core.rmem_max" = mkOption { "net.core.rmem_max" = lib.mkOption {
type = types.nullOr highestValueType; type = lib.types.nullOr highestValueType;
default = null; default = null;
description = "The maximum receive socket buffer size in bytes. In case of conflicting values, the highest will be used."; description = "The maximum receive socket buffer size in bytes. In case of conflicting values, the highest will be used.";
}; };
"net.core.wmem_max" = mkOption { "net.core.wmem_max" = lib.mkOption {
type = types.nullOr highestValueType; type = lib.types.nullOr highestValueType;
default = null; default = null;
description = "The maximum send socket buffer size in bytes. In case of conflicting values, the highest will be used."; description = "The maximum send socket buffer size in bytes. In case of conflicting values, the highest will be used.";
}; };
}; };
}; };
default = {}; default = {};
example = literalExpression '' example = lib.literalExpression ''
{ "net.ipv4.tcp_syncookies" = false; "vm.swappiness" = 60; } { "net.ipv4.tcp_syncookies" = false; "vm.swappiness" = 60; }
''; '';
description = '' description = ''
@ -66,8 +63,8 @@ in
config = { config = {
environment.etc."sysctl.d/60-nixos.conf".text = environment.etc."sysctl.d/60-nixos.conf".text =
concatStrings (mapAttrsToList (n: v: lib.concatStrings (lib.mapAttrsToList (n: v:
optionalString (v != null) "${n}=${if v == false then "0" else toString v}\n" lib.optionalString (v != null) "${n}=${if v == false then "0" else toString v}\n"
) config.boot.kernel.sysctl); ) config.boot.kernel.sysctl);
systemd.services.systemd-sysctl = systemd.services.systemd-sysctl =
@ -77,10 +74,10 @@ in
# Hide kernel pointers (e.g. in /proc/modules) for unprivileged # Hide kernel pointers (e.g. in /proc/modules) for unprivileged
# users as these make it easier to exploit kernel vulnerabilities. # users as these make it easier to exploit kernel vulnerabilities.
boot.kernel.sysctl."kernel.kptr_restrict" = mkDefault 1; boot.kernel.sysctl."kernel.kptr_restrict" = lib.mkDefault 1;
# Improve compatibility with applications that allocate # Improve compatibility with applications that allocate
# a lot of memory, like modern games # a lot of memory, like modern games
boot.kernel.sysctl."vm.max_map_count" = mkDefault 1048576; boot.kernel.sysctl."vm.max_map_count" = lib.mkDefault 1048576;
}; };
} }

View file

@ -1,16 +1,11 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
{ {
###### interface ###### interface
options = { options = {
hardware.cpu.amd.updateMicrocode = mkOption { hardware.cpu.amd.updateMicrocode = lib.mkOption {
default = false; default = false;
type = types.bool; type = lib.types.bool;
description = '' description = ''
Update the CPU microcode for AMD processors. Update the CPU microcode for AMD processors.
''; '';
@ -18,12 +13,10 @@ with lib;
}; };
###### implementation ###### implementation
config = lib.mkIf config.hardware.cpu.amd.updateMicrocode {
config = mkIf config.hardware.cpu.amd.updateMicrocode {
# Microcode updates must be the first item prepended in the initrd # Microcode updates must be the first item prepended in the initrd
boot.initrd.prepend = mkOrder 1 [ "${pkgs.microcodeAmd}/amd-ucode.img" ]; boot.initrd.prepend = lib.mkOrder 1 [ "${pkgs.microcodeAmd}/amd-ucode.img" ];
}; };
} }

View file

@ -1,24 +1,23 @@
{ config, options, lib, ... }: { config, options, lib, ... }:
with lib;
let let
cfgSev = config.hardware.cpu.amd.sev; cfgSev = config.hardware.cpu.amd.sev;
cfgSevGuest = config.hardware.cpu.amd.sevGuest; cfgSevGuest = config.hardware.cpu.amd.sevGuest;
optionsFor = device: group: { optionsFor = device: group: {
enable = mkEnableOption "access to the AMD ${device} device"; enable = lib.mkEnableOption "access to the AMD ${device} device";
user = mkOption { user = lib.mkOption {
description = "Owner to assign to the ${device} device."; description = "Owner to assign to the ${device} device.";
type = types.str; type = lib.types.str;
default = "root"; default = "root";
}; };
group = mkOption { group = lib.mkOption {
description = "Group to assign to the ${device} device."; description = "Group to assign to the ${device} device.";
type = types.str; type = lib.types.str;
default = group; default = group;
}; };
mode = mkOption { mode = lib.mkOption {
description = "Mode to set for the ${device} device."; description = "Mode to set for the ${device} device.";
type = types.str; type = lib.types.str;
default = "0660"; default = "0660";
}; };
}; };
@ -28,16 +27,16 @@ with lib; {
options.hardware.cpu.amd.sevGuest = optionsFor "SEV guest" "sev-guest"; options.hardware.cpu.amd.sevGuest = optionsFor "SEV guest" "sev-guest";
config = mkMerge [ config = lib.mkMerge [
# /dev/sev # /dev/sev
(mkIf cfgSev.enable { (lib.mkIf cfgSev.enable {
assertions = [ assertions = [
{ {
assertion = hasAttr cfgSev.user config.users.users; assertion = lib.hasAttr cfgSev.user config.users.users;
message = "Given user does not exist"; message = "Given user does not exist";
} }
{ {
assertion = (cfgSev.group == options.hardware.cpu.amd.sev.group.default) || (hasAttr cfgSev.group config.users.groups); assertion = (cfgSev.group == options.hardware.cpu.amd.sev.group.default) || (lib.hasAttr cfgSev.group config.users.groups);
message = "Given group does not exist"; message = "Given group does not exist";
} }
]; ];
@ -46,7 +45,7 @@ with lib; {
options kvm_amd sev=1 options kvm_amd sev=1
''; '';
users.groups = optionalAttrs (cfgSev.group == options.hardware.cpu.amd.sev.group.default) { users.groups = lib.optionalAttrs (cfgSev.group == options.hardware.cpu.amd.sev.group.default) {
"${cfgSev.group}" = { }; "${cfgSev.group}" = { };
}; };
@ -56,19 +55,19 @@ with lib; {
}) })
# /dev/sev-guest # /dev/sev-guest
(mkIf cfgSevGuest.enable { (lib.mkIf cfgSevGuest.enable {
assertions = [ assertions = [
{ {
assertion = hasAttr cfgSevGuest.user config.users.users; assertion = lib.hasAttr cfgSevGuest.user config.users.users;
message = "Given user does not exist"; message = "Given user does not exist";
} }
{ {
assertion = (cfgSevGuest.group == options.hardware.cpu.amd.sevGuest.group.default) || (hasAttr cfgSevGuest.group config.users.groups); assertion = (cfgSevGuest.group == options.hardware.cpu.amd.sevGuest.group.default) || (lib.hasAttr cfgSevGuest.group config.users.groups);
message = "Given group does not exist"; message = "Given group does not exist";
} }
]; ];
users.groups = optionalAttrs (cfgSevGuest.group == options.hardware.cpu.amd.sevGuest.group.default) { users.groups = lib.optionalAttrs (cfgSevGuest.group == options.hardware.cpu.amd.sevGuest.group.default) {
"${cfgSevGuest.group}" = { }; "${cfgSevGuest.group}" = { };
}; };

View file

@ -1,16 +1,11 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
{ {
###### interface ###### interface
options = { options = {
hardware.cpu.intel.updateMicrocode = mkOption { hardware.cpu.intel.updateMicrocode = lib.mkOption {
default = false; default = false;
type = types.bool; type = lib.types.bool;
description = '' description = ''
Update the CPU microcode for Intel processors. Update the CPU microcode for Intel processors.
''; '';
@ -18,12 +13,10 @@ with lib;
}; };
###### implementation ###### implementation
config = lib.mkIf config.hardware.cpu.intel.updateMicrocode {
config = mkIf config.hardware.cpu.intel.updateMicrocode {
# Microcode updates must be the first item prepended in the initrd # Microcode updates must be the first item prepended in the initrd
boot.initrd.prepend = mkOrder 1 [ "${pkgs.microcodeIntel}/intel-ucode.img" ]; boot.initrd.prepend = lib.mkOrder 1 [ "${pkgs.microcodeIntel}/intel-ucode.img" ];
}; };
} }

View file

@ -1,11 +1,10 @@
{ config, lib, ... }: { config, lib, ... }:
with lib;
let let
cfg = config.hardware.cpu.intel.sgx; cfg = config.hardware.cpu.intel.sgx;
defaultPrvGroup = "sgx_prv"; defaultPrvGroup = "sgx_prv";
in in
{ {
options.hardware.cpu.intel.sgx.enableDcapCompat = mkOption { options.hardware.cpu.intel.sgx.enableDcapCompat = lib.mkOption {
description = '' description = ''
Whether to enable backward compatibility for SGX software build for the Whether to enable backward compatibility for SGX software build for the
out-of-tree Intel SGX DCAP driver. out-of-tree Intel SGX DCAP driver.
@ -15,43 +14,43 @@ in
`/dev/sgx/enclave` and `/dev/sgx/provision`, `/dev/sgx/enclave` and `/dev/sgx/provision`,
respectively. respectively.
''; '';
type = types.bool; type = lib.types.bool;
default = true; default = true;
}; };
options.hardware.cpu.intel.sgx.provision = { options.hardware.cpu.intel.sgx.provision = {
enable = mkEnableOption "access to the Intel SGX provisioning device"; enable = lib.mkEnableOption "access to the Intel SGX provisioning device";
user = mkOption { user = lib.mkOption {
description = "Owner to assign to the SGX provisioning device."; description = "Owner to assign to the SGX provisioning device.";
type = types.str; type = lib.types.str;
default = "root"; default = "root";
}; };
group = mkOption { group = lib.mkOption {
description = "Group to assign to the SGX provisioning device."; description = "Group to assign to the SGX provisioning device.";
type = types.str; type = lib.types.str;
default = defaultPrvGroup; default = defaultPrvGroup;
}; };
mode = mkOption { mode = lib.mkOption {
description = "Mode to set for the SGX provisioning device."; description = "Mode to set for the SGX provisioning device.";
type = types.str; type = lib.types.str;
default = "0660"; default = "0660";
}; };
}; };
config = mkMerge [ config = lib.mkMerge [
(mkIf cfg.provision.enable { (lib.mkIf cfg.provision.enable {
assertions = [ assertions = [
{ {
assertion = hasAttr cfg.provision.user config.users.users; assertion = lib.hasAttr cfg.provision.user config.users.users;
message = "Given user does not exist"; message = "Given user does not exist";
} }
{ {
assertion = (cfg.provision.group == defaultPrvGroup) || (hasAttr cfg.provision.group config.users.groups); assertion = (cfg.provision.group == defaultPrvGroup) || (lib.hasAttr cfg.provision.group config.users.groups);
message = "Given group does not exist"; message = "Given group does not exist";
} }
]; ];
users.groups = optionalAttrs (cfg.provision.group == defaultPrvGroup) { users.groups = lib.optionalAttrs (cfg.provision.group == defaultPrvGroup) {
"${cfg.provision.group}" = { }; "${cfg.provision.group}" = { };
}; };
@ -59,7 +58,7 @@ in
SUBSYSTEM=="misc", KERNEL=="sgx_provision", OWNER="${user}", GROUP="${group}", MODE="${mode}" SUBSYSTEM=="misc", KERNEL=="sgx_provision", OWNER="${user}", GROUP="${group}", MODE="${mode}"
''; '';
}) })
(mkIf cfg.enableDcapCompat { (lib.mkIf cfg.enableDcapCompat {
services.udev.extraRules = '' services.udev.extraRules = ''
SUBSYSTEM=="misc", KERNEL=="sgx_enclave", SYMLINK+="sgx/enclave" SUBSYSTEM=="misc", KERNEL=="sgx_enclave", SYMLINK+="sgx/enclave"
SUBSYSTEM=="misc", KERNEL=="sgx_provision", SYMLINK+="sgx/provision" SUBSYSTEM=="misc", KERNEL=="sgx_provision", SYMLINK+="sgx/provision"

View file

@ -1,29 +1,26 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.hardware.digitalbitbox; cfg = config.hardware.digitalbitbox;
in in
{ {
options.hardware.digitalbitbox = { options.hardware.digitalbitbox = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Enables udev rules for Digital Bitbox devices. Enables udev rules for Digital Bitbox devices.
''; '';
}; };
package = mkPackageOption pkgs "digitalbitbox" { package = lib.mkPackageOption pkgs "digitalbitbox" {
extraDescription = '' extraDescription = ''
This can be used to install a package with udev rules that differ from the defaults. This can be used to install a package with udev rules that differ from the defaults.
''; '';
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
services.udev.packages = [ cfg.package ]; services.udev.packages = [ cfg.package ];
}; };
} }

View file

@ -1,19 +1,16 @@
{ config, lib, ... }: { config, lib, ... }:
with lib;
let let
cfg = config.hardware.ksm; cfg = config.hardware.ksm;
in { in {
imports = [ imports = [
(mkRenamedOptionModule [ "hardware" "enableKSM" ] [ "hardware" "ksm" "enable" ]) (lib.mkRenamedOptionModule [ "hardware" "enableKSM" ] [ "hardware" "ksm" "enable" ])
]; ];
options.hardware.ksm = { options.hardware.ksm = {
enable = mkEnableOption "Linux kernel Same-Page Merging"; enable = lib.mkEnableOption "Linux kernel Same-Page Merging";
sleep = mkOption { sleep = lib.mkOption {
type = types.nullOr types.int; type = lib.types.nullOr lib.types.int;
default = null; default = null;
description = '' description = ''
How many milliseconds ksmd should sleep between scans. How many milliseconds ksmd should sleep between scans.
@ -22,14 +19,14 @@ in {
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
systemd.services.enable-ksm = { systemd.services.enable-ksm = {
description = "Enable Kernel Same-Page Merging"; description = "Enable Kernel Same-Page Merging";
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
script = script =
'' ''
echo 1 > /sys/kernel/mm/ksm/run echo 1 > /sys/kernel/mm/ksm/run
'' + optionalString (cfg.sleep != null) '' + lib.optionalString (cfg.sleep != null)
'' ''
echo ${toString cfg.sleep} > /sys/kernel/mm/ksm/sleep_millisecs echo ${toString cfg.sleep} > /sys/kernel/mm/ksm/sleep_millisecs
''; '';

View file

@ -1,14 +1,11 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.hardware.ledger; cfg = config.hardware.ledger;
in { in {
options.hardware.ledger.enable = mkEnableOption "udev rules for Ledger devices"; options.hardware.ledger.enable = lib.mkEnableOption "udev rules for Ledger devices";
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
services.udev.packages = [ pkgs.ledger-udev-rules ]; services.udev.packages = [ pkgs.ledger-udev-rules ];
}; };
} }

View file

@ -1,7 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.hardware.logitech; cfg = config.hardware.logitech;
@ -12,25 +9,25 @@ let
in in
{ {
imports = [ imports = [
(mkRenamedOptionModule [ "hardware" "logitech" "enable" ] [ "hardware" "logitech" "wireless" "enable" ]) (lib.mkRenamedOptionModule [ "hardware" "logitech" "enable" ] [ "hardware" "logitech" "wireless" "enable" ])
(mkRenamedOptionModule [ "hardware" "logitech" "enableGraphical" ] [ "hardware" "logitech" "wireless" "enableGraphical" ]) (lib.mkRenamedOptionModule [ "hardware" "logitech" "enableGraphical" ] [ "hardware" "logitech" "wireless" "enableGraphical" ])
]; ];
options.hardware.logitech = { options.hardware.logitech = {
lcd = { lcd = {
enable = mkEnableOption "support for Logitech LCD Devices"; enable = lib.mkEnableOption "support for Logitech LCD Devices";
startWhenNeeded = mkOption { startWhenNeeded = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = true; default = true;
description = '' description = ''
Only run the service when an actual supported device is plugged. Only run the service when an actual supported device is plugged.
''; '';
}; };
devices = mkOption { devices = lib.mkOption {
type = types.listOf types.str; type = lib.types.listOf lib.types.str;
default = [ "0a07" "c222" "c225" "c227" "c251" ]; default = [ "0a07" "c222" "c225" "c227" "c251" ];
description = '' description = ''
List of USB device ids supported by g15daemon. List of USB device ids supported by g15daemon.
@ -41,10 +38,10 @@ in
}; };
wireless = { wireless = {
enable = mkEnableOption "support for Logitech Wireless Devices"; enable = lib.mkEnableOption "support for Logitech Wireless Devices";
enableGraphical = mkOption { enableGraphical = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = "Enable graphical support applications."; description = "Enable graphical support applications.";
}; };

View file

@ -1,14 +1,11 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
{ {
meta.maintainers = with maintainers; [ grahamc ]; meta.maintainers = with lib.maintainers; [ grahamc ];
options = { options = {
hardware.mcelog = { hardware.mcelog = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Enable the Machine Check Exception logger. Enable the Machine Check Exception logger.
@ -18,7 +15,7 @@ with lib;
}; };
config = mkIf config.hardware.mcelog.enable { config = lib.mkIf config.hardware.mcelog.enable {
systemd = { systemd = {
packages = [ pkgs.mcelog ]; packages = [ pkgs.mcelog ];

View file

@ -1,6 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
kernelVersion = config.boot.kernelPackages.kernel.version; kernelVersion = config.boot.kernelPackages.kernel.version;
linuxKernelMinVersion = "5.8"; linuxKernelMinVersion = "5.8";
@ -11,9 +9,9 @@ let
}; };
in in
{ {
options.networking.wireless.athUserRegulatoryDomain = mkOption { options.networking.wireless.athUserRegulatoryDomain = lib.mkOption {
default = false; default = false;
type = types.bool; type = lib.types.bool;
description = '' description = ''
If enabled, sets the ATH_USER_REGD kernel config switch to true to If enabled, sets the ATH_USER_REGD kernel config switch to true to
disable the enforcement of EEPROM regulatory restrictions for ath disable the enforcement of EEPROM regulatory restrictions for ath
@ -21,9 +19,9 @@ in
''; '';
}; };
config = mkIf config.networking.wireless.athUserRegulatoryDomain { config = lib.mkIf config.networking.wireless.athUserRegulatoryDomain {
assertions = singleton { assertions = lib.singleton {
assertion = lessThan 0 (builtins.compareVersions kernelVersion linuxKernelMinVersion); assertion = lib.lessThan 0 (builtins.compareVersions kernelVersion linuxKernelMinVersion);
message = "ATH_USER_REGD patch for kernels older than ${linuxKernelMinVersion} not ported yet!"; message = "ATH_USER_REGD patch for kernels older than ${linuxKernelMinVersion} not ported yet!";
}; };
boot.kernelPatches = [ kernelPatch ]; boot.kernelPatches = [ kernelPatch ];

View file

@ -1,7 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let kernelVersion = config.boot.kernelPackages.kernel.version; in let kernelVersion = config.boot.kernelPackages.kernel.version; in
{ {
@ -10,9 +7,9 @@ let kernelVersion = config.boot.kernelPackages.kernel.version; in
options = { options = {
networking.enableB43Firmware = mkOption { networking.enableB43Firmware = lib.mkOption {
default = false; default = false;
type = types.bool; type = lib.types.bool;
description = '' description = ''
Turn on this option if you want firmware for the NICs supported by the b43 module. Turn on this option if you want firmware for the NICs supported by the b43 module.
''; '';
@ -23,7 +20,7 @@ let kernelVersion = config.boot.kernelPackages.kernel.version; in
###### implementation ###### implementation
config = mkIf config.networking.enableB43Firmware { config = lib.mkIf config.networking.enableB43Firmware {
hardware.firmware = [ pkgs.b43Firmware_5_1_138 ]; hardware.firmware = [ pkgs.b43Firmware_5_1_138 ];
}; };

View file

@ -1,14 +1,11 @@
{ pkgs, lib, config, ... }: { pkgs, lib, config, ... }:
with lib;
let let
cfg = config.hardware.new-lg4ff; cfg = config.hardware.new-lg4ff;
kernelPackages = config.boot.kernelPackages; kernelPackages = config.boot.kernelPackages;
in { in {
options.hardware.new-lg4ff = { options.hardware.new-lg4ff = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Enables improved Linux module drivers for Logitech driving wheels. Enables improved Linux module drivers for Logitech driving wheels.

View file

@ -1,7 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.hardware.nitrokey; cfg = config.hardware.nitrokey;
@ -10,8 +7,8 @@ in
{ {
options.hardware.nitrokey = { options.hardware.nitrokey = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Enables udev rules for Nitrokey devices. By default grants access Enables udev rules for Nitrokey devices. By default grants access
@ -21,7 +18,7 @@ in
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
services.udev.packages = [ pkgs.libnitrokey ]; services.udev.packages = [ pkgs.libnitrokey ];
}; };
} }

View file

@ -1,7 +1,4 @@
{ config, lib, ... }: { config, lib, ... }:
with lib;
{ {
####### interface ####### interface
@ -9,8 +6,8 @@ with lib;
options = { options = {
hardware.onlykey = { hardware.onlykey = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Enable OnlyKey device (https://crp.to/p/) support. Enable OnlyKey device (https://crp.to/p/) support.
@ -25,7 +22,7 @@ with lib;
####### implementation ####### implementation
config = mkIf config.hardware.onlykey.enable { config = lib.mkIf config.hardware.onlykey.enable {
services.udev.extraRules = builtins.readFile ./onlykey.udev; services.udev.extraRules = builtins.readFile ./onlykey.udev;
}; };

View file

@ -1,7 +1,4 @@
{ config, pkgs, lib, ... }: { config, pkgs, lib, ... }:
with lib;
let let
cfg = config.hardware.openrazer; cfg = config.hardware.openrazer;
kernelPackages = config.boot.kernelPackages; kernelPackages = config.boot.kernelPackages;
@ -51,20 +48,20 @@ in
{ {
options = { options = {
hardware.openrazer = { hardware.openrazer = {
enable = mkEnableOption '' enable = lib.mkEnableOption ''
OpenRazer drivers and userspace daemon OpenRazer drivers and userspace daemon
''; '';
verboseLogging = mkOption { verboseLogging = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Whether to enable verbose logging. Logs debug messages. Whether to enable verbose logging. Logs debug messages.
''; '';
}; };
syncEffectsEnabled = mkOption { syncEffectsEnabled = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = true; default = true;
description = '' description = ''
Set the sync effects flag to true so any assignment of Set the sync effects flag to true so any assignment of
@ -72,30 +69,30 @@ in
''; '';
}; };
devicesOffOnScreensaver = mkOption { devicesOffOnScreensaver = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = true; default = true;
description = '' description = ''
Turn off the devices when the systems screensaver kicks in. Turn off the devices when the systems screensaver kicks in.
''; '';
}; };
batteryNotifier = mkOption { batteryNotifier = lib.mkOption {
description = '' description = ''
Settings for device battery notifications. Settings for device battery notifications.
''; '';
default = {}; default = {};
type = types.submodule { type = lib.types.submodule {
options = { options = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = true; default = true;
description = '' description = ''
Mouse battery notifier. Mouse battery notifier.
''; '';
}; };
frequency = mkOption { frequency = lib.mkOption {
type = types.int; type = lib.types.int;
default = 600; default = 600;
description = '' description = ''
How often battery notifications should be shown (in seconds). How often battery notifications should be shown (in seconds).
@ -103,8 +100,8 @@ in
''; '';
}; };
percentage = mkOption { percentage = lib.mkOption {
type = types.int; type = lib.types.int;
default = 33; default = 33;
description = '' description = ''
At what battery percentage the device should reach before At what battery percentage the device should reach before
@ -115,8 +112,8 @@ in
}; };
}; };
keyStatistics = mkOption { keyStatistics = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Collects number of keypresses per hour per key used to Collects number of keypresses per hour per key used to
@ -124,8 +121,8 @@ in
''; '';
}; };
users = mkOption { users = lib.mkOption {
type = with types; listOf str; type = with lib.types; listOf str;
default = []; default = [];
description = '' description = ''
Usernames to be added to the "openrazer" group, so that they Usernames to be added to the "openrazer" group, so that they
@ -136,10 +133,10 @@ in
}; };
imports = [ imports = [
(mkRenamedOptionModule [ "hardware" "openrazer" "mouseBatteryNotifier" ] [ "hardware" "openrazer" "batteryNotifier" "enable" ]) (lib.mkRenamedOptionModule [ "hardware" "openrazer" "mouseBatteryNotifier" ] [ "hardware" "openrazer" "batteryNotifier" "enable" ])
]; ];
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
boot.extraModulePackages = [ kernelPackages.openrazer ]; boot.extraModulePackages = [ kernelPackages.openrazer ];
boot.kernelModules = drivers; boot.kernelModules = drivers;

View file

@ -1,6 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.hardware.opentabletdriver; cfg = config.hardware.opentabletdriver;
in in
@ -9,29 +7,29 @@ in
options = { options = {
hardware.opentabletdriver = { hardware.opentabletdriver = {
enable = mkOption { enable = lib.mkOption {
default = false; default = false;
type = types.bool; type = lib.types.bool;
description = '' description = ''
Enable OpenTabletDriver udev rules, user service and blacklist kernel Enable OpenTabletDriver udev rules, user service and blacklist kernel
modules known to conflict with OpenTabletDriver. modules known to conflict with OpenTabletDriver.
''; '';
}; };
blacklistedKernelModules = mkOption { blacklistedKernelModules = lib.mkOption {
type = types.listOf types.str; type = lib.types.listOf lib.types.str;
default = [ "hid-uclogic" "wacom" ]; default = [ "hid-uclogic" "wacom" ];
description = '' description = ''
Blacklist of kernel modules known to conflict with OpenTabletDriver. Blacklist of kernel modules known to conflict with OpenTabletDriver.
''; '';
}; };
package = mkPackageOption pkgs "opentabletdriver" { }; package = lib.mkPackageOption pkgs "opentabletdriver" { };
daemon = { daemon = {
enable = mkOption { enable = lib.mkOption {
default = true; default = true;
type = types.bool; type = lib.types.bool;
description = '' description = ''
Whether to start OpenTabletDriver daemon as a systemd user service. Whether to start OpenTabletDriver daemon as a systemd user service.
''; '';
@ -40,14 +38,14 @@ in
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
environment.systemPackages = [ cfg.package ]; environment.systemPackages = [ cfg.package ];
services.udev.packages = [ cfg.package ]; services.udev.packages = [ cfg.package ];
boot.blacklistedKernelModules = cfg.blacklistedKernelModules; boot.blacklistedKernelModules = cfg.blacklistedKernelModules;
systemd.user.services.opentabletdriver = with pkgs; mkIf cfg.daemon.enable { systemd.user.services.opentabletdriver = with pkgs; lib.mkIf cfg.daemon.enable {
description = "Open source, cross-platform, user-mode tablet driver"; description = "Open source, cross-platform, user-mode tablet driver";
wantedBy = [ "graphical-session.target" ]; wantedBy = [ "graphical-session.target" ];
partOf = [ "graphical-session.target" ]; partOf = [ "graphical-session.target" ];

View file

@ -1,53 +1,45 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
pcmciaUtils = pkgs.pcmciaUtils.passthru.function { pcmciaUtils = pkgs.pcmciaUtils.passthru.function {
inherit (config.hardware.pcmcia) firmware config; inherit (config.hardware.pcmcia) firmware config;
}; };
in in
{ {
###### interface ###### interface
options = { options = {
hardware.pcmcia = { hardware.pcmcia = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Enable this option to support PCMCIA card. Enable this option to support PCMCIA card.
''; '';
}; };
firmware = mkOption { firmware = lib.mkOption {
type = types.listOf types.path; type = lib.types.listOf lib.types.path;
default = []; default = [];
description = '' description = ''
List of firmware used to handle specific PCMCIA card. List of firmware used to handle specific PCMCIA card.
''; '';
}; };
config = mkOption { config = lib.mkOption {
default = null; default = null;
type = types.nullOr types.path; type = lib.types.nullOr lib.types.path;
description = '' description = ''
Path to the configuration file which maps the memory, IRQs Path to the configuration file which maps the memory, IRQs
and ports used by the PCMCIA hardware. and ports used by the PCMCIA hardware.
''; '';
}; };
}; };
}; };
###### implementation ###### implementation
config = mkIf config.hardware.pcmcia.enable { config = lib.mkIf config.hardware.pcmcia.enable {
boot.kernelModules = [ "pcmcia" ]; boot.kernelModules = [ "pcmcia" ];

View file

@ -1,19 +1,18 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.hardware.printers; cfg = config.hardware.printers;
ensurePrinter = p: let ensurePrinter = p: let
args = cli.toGNUCommandLineShell {} ({ args = lib.cli.toGNUCommandLineShell {} ({
p = p.name; p = p.name;
v = p.deviceUri; v = p.deviceUri;
m = p.model; m = p.model;
} // optionalAttrs (p.location != null) { } // lib.optionalAttrs (p.location != null) {
L = p.location; L = p.location;
} // optionalAttrs (p.description != null) { } // lib.optionalAttrs (p.description != null) {
D = p.description; D = p.description;
} // optionalAttrs (p.ppdOptions != {}) { } // lib.optionalAttrs (p.ppdOptions != {}) {
o = mapAttrsToList (name: value: "${name}=${value}") p.ppdOptions; o = lib.mapAttrsToList (name: value: "${name}=${value}") p.ppdOptions;
}); });
in '' in ''
${pkgs.cups}/bin/lpadmin ${args} -E ${pkgs.cups}/bin/lpadmin ${args} -E
@ -24,22 +23,22 @@ let
''; '';
# "graph but not # or /" can't be implemented as regex alone due to missing lookahead support # "graph but not # or /" can't be implemented as regex alone due to missing lookahead support
noInvalidChars = str: all (c: c != "#" && c != "/") (stringToCharacters str); noInvalidChars = str: lib.all (c: c != "#" && c != "/") (lib.stringToCharacters str);
printerName = (types.addCheck (types.strMatching "[[:graph:]]+") noInvalidChars) printerName = (lib.types.addCheck (lib.types.strMatching "[[:graph:]]+") noInvalidChars)
// { description = "printable string without spaces, # and /"; }; // { description = "printable string without spaces, # and /"; };
in { in {
options = { options = {
hardware.printers = { hardware.printers = {
ensureDefaultPrinter = mkOption { ensureDefaultPrinter = lib.mkOption {
type = types.nullOr printerName; type = lib.types.nullOr printerName;
default = null; default = null;
description = '' description = ''
Ensures the named printer is the default CUPS printer / printer queue. Ensures the named printer is the default CUPS printer / printer queue.
''; '';
}; };
ensurePrinters = mkOption { ensurePrinters = lib.mkOption {
description = '' description = ''
Will regularly ensure that the given CUPS printers are configured as declared here. Will regularly ensure that the given CUPS printers are configured as declared here.
If a printer's options are manually changed afterwards, they will be overwritten eventually. If a printer's options are manually changed afterwards, they will be overwritten eventually.
@ -49,9 +48,9 @@ in {
Printers not listed here can still be manually configured. Printers not listed here can still be manually configured.
''; '';
default = []; default = [];
type = types.listOf (types.submodule { type = lib.types.listOf (lib.types.submodule {
options = { options = {
name = mkOption { name = lib.mkOption {
type = printerName; type = printerName;
example = "BrotherHL_Workroom"; example = "BrotherHL_Workroom";
description = '' description = ''
@ -59,25 +58,25 @@ in {
May contain any printable characters except "/", "#", and space. May contain any printable characters except "/", "#", and space.
''; '';
}; };
location = mkOption { location = lib.mkOption {
type = types.nullOr types.str; type = lib.types.nullOr lib.types.str;
default = null; default = null;
example = "Workroom"; example = "Workroom";
description = '' description = ''
Optional human-readable location. Optional human-readable location.
''; '';
}; };
description = mkOption { description = lib.mkOption {
type = types.nullOr types.str; type = lib.types.nullOr lib.types.str;
default = null; default = null;
example = "Brother HL-5140"; example = "Brother HL-5140";
description = '' description = ''
Optional human-readable description. Optional human-readable description.
''; '';
}; };
deviceUri = mkOption { deviceUri = lib.mkOption {
type = types.str; type = lib.types.str;
example = literalExpression '' example = lib.literalExpression ''
"ipp://printserver.local/printers/BrotherHL_Workroom" "ipp://printserver.local/printers/BrotherHL_Workroom"
"usb://HP/DESKJET%20940C?serial=CN16E6C364BH" "usb://HP/DESKJET%20940C?serial=CN16E6C364BH"
''; '';
@ -86,9 +85,9 @@ in {
{command}`lpinfo -v` shows a list of supported device URIs and schemes. {command}`lpinfo -v` shows a list of supported device URIs and schemes.
''; '';
}; };
model = mkOption { model = lib.mkOption {
type = types.str; type = lib.types.str;
example = literalExpression '' example = lib.literalExpression ''
"gutenprint.''${lib.versions.majorMinor (lib.getVersion pkgs.gutenprint)}://brother-hl-5140/expert" "gutenprint.''${lib.versions.majorMinor (lib.getVersion pkgs.gutenprint)}://brother-hl-5140/expert"
''; '';
description = '' description = ''
@ -96,8 +95,8 @@ in {
{command}`lpinfo -m` shows a list of supported models. {command}`lpinfo -m` shows a list of supported models.
''; '';
}; };
ppdOptions = mkOption { ppdOptions = lib.mkOption {
type = types.attrsOf types.str; type = lib.types.attrsOf lib.types.str;
example = { example = {
PageSize = "A4"; PageSize = "A4";
Duplex = "DuplexNoTumble"; Duplex = "DuplexNoTumble";
@ -114,7 +113,7 @@ in {
}; };
}; };
config = mkIf (cfg.ensurePrinters != [] && config.services.printing.enable) { config = lib.mkIf (cfg.ensurePrinters != [] && config.services.printing.enable) {
systemd.services.ensure-printers = { systemd.services.ensure-printers = {
description = "Ensure NixOS-configured CUPS printers"; description = "Ensure NixOS-configured CUPS printers";
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
@ -126,13 +125,13 @@ in {
RemainAfterExit = true; RemainAfterExit = true;
}; };
script = concatStringsSep "\n" [ script = lib.concatStringsSep "\n" [
(concatMapStrings ensurePrinter cfg.ensurePrinters) (lib.concatMapStrings ensurePrinter cfg.ensurePrinters)
(optionalString (cfg.ensureDefaultPrinter != null) (lib.optionalString (cfg.ensureDefaultPrinter != null)
(ensureDefaultPrinter cfg.ensureDefaultPrinter)) (ensureDefaultPrinter cfg.ensureDefaultPrinter))
# Note: if cupsd is "stateless" the service can't be stopped, # Note: if cupsd is "stateless" the service can't be stopped,
# otherwise the configuration will be wiped on the next start. # otherwise the configuration will be wiped on the next start.
(optionalString (with config.services.printing; startWhenNeeded && !stateless) (lib.optionalString (with config.services.printing; startWhenNeeded && !stateless)
"systemctl stop cups.service") "systemctl stop cups.service")
]; ];
}; };

View file

@ -1,7 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
hpssacli = pkgs.stdenv.mkDerivation rec { hpssacli = pkgs.stdenv.mkDerivation rec {
pname = "hpssacli"; pname = "hpssacli";
@ -48,13 +45,13 @@ in {
options = { options = {
hardware.raid.HPSmartArray = { hardware.raid.HPSmartArray = {
enable = mkEnableOption "HP Smart Array kernel modules and CLI utility"; enable = lib.mkEnableOption "HP Smart Array kernel modules and CLI utility";
}; };
}; };
###### implementation ###### implementation
config = mkIf config.hardware.raid.HPSmartArray.enable { config = lib.mkIf config.hardware.raid.HPSmartArray.enable {
boot.initrd.kernelModules = [ "sg" ]; /* hpssacli wants it */ boot.initrd.kernelModules = [ "sg" ]; /* hpssacli wants it */
boot.initrd.availableKernelModules = [ "hpsa" ]; boot.initrd.availableKernelModules = [ "hpsa" ];

View file

@ -1,20 +1,17 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
{ {
###### interface ###### interface
options = { options = {
hardware.sensor.iio = { hardware.sensor.iio = {
enable = mkOption { enable = lib.mkOption {
description = '' description = ''
Enable this option to support IIO sensors with iio-sensor-proxy. Enable this option to support IIO sensors with iio-sensor-proxy.
IIO sensors are used for orientation and ambient light IIO sensors are used for orientation and ambient light
sensors on some mobile devices. sensors on some mobile devices.
''; '';
type = types.bool; type = lib.types.bool;
default = false; default = false;
}; };
}; };
@ -22,7 +19,7 @@ with lib;
###### implementation ###### implementation
config = mkIf config.hardware.sensor.iio.enable { config = lib.mkIf config.hardware.sensor.iio.enable {
boot.initrd.availableKernelModules = [ "hid-sensor-hub" ]; boot.initrd.availableKernelModules = [ "hid-sensor-hub" ];

View file

@ -1,7 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.hardware.steam-hardware; cfg = config.hardware.steam-hardware;
@ -10,14 +7,14 @@ in
{ {
options.hardware.steam-hardware = { options.hardware.steam-hardware = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = "Enable udev rules for Steam hardware such as the Steam Controller, other supported controllers and the HTC Vive"; description = "Enable udev rules for Steam hardware such as the Steam Controller, other supported controllers and the HTC Vive";
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
services.udev.packages = [ services.udev.packages = [
pkgs.steamPackages.steam pkgs.steamPackages.steam
]; ];

View file

@ -1,14 +1,11 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.hardware.tuxedo-keyboard; cfg = config.hardware.tuxedo-keyboard;
tuxedo-keyboard = config.boot.kernelPackages.tuxedo-keyboard; tuxedo-keyboard = config.boot.kernelPackages.tuxedo-keyboard;
in in
{ {
options.hardware.tuxedo-keyboard = { options.hardware.tuxedo-keyboard = {
enable = mkEnableOption '' enable = lib.mkEnableOption ''
the tuxedo-keyboard driver. the tuxedo-keyboard driver.
To configure the driver, pass the options to the {option}`boot.kernelParams` configuration. To configure the driver, pass the options to the {option}`boot.kernelParams` configuration.
@ -27,7 +24,7 @@ in
''; '';
}; };
config = mkIf cfg.enable config = lib.mkIf cfg.enable
{ {
boot.kernelModules = ["tuxedo_keyboard"]; boot.kernelModules = ["tuxedo_keyboard"];
boot.extraModulePackages = [ tuxedo-keyboard ]; boot.extraModulePackages = [ tuxedo-keyboard ];

View file

@ -1,7 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.hardware.ubertooth; cfg = config.hardware.ubertooth;
@ -10,17 +7,17 @@ let
}; };
in { in {
options.hardware.ubertooth = { options.hardware.ubertooth = {
enable = mkEnableOption "Ubertooth software and its udev rules"; enable = lib.mkEnableOption "Ubertooth software and its udev rules";
group = mkOption { group = lib.mkOption {
type = types.str; type = lib.types.str;
default = "ubertooth"; default = "ubertooth";
example = "wheel"; example = "wheel";
description = "Group for Ubertooth's udev rules."; description = "Group for Ubertooth's udev rules.";
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
environment.systemPackages = [ ubertoothPkg ]; environment.systemPackages = [ ubertoothPkg ];
services.udev.packages = [ ubertoothPkg ]; services.udev.packages = [ ubertoothPkg ];

View file

@ -1,15 +1,12 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
{ {
###### interface ###### interface
options = { options = {
hardware.usb-modeswitch = { hardware.usb-modeswitch = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Enable this option to support certain USB WLAN and WWAN adapters. Enable this option to support certain USB WLAN and WWAN adapters.
@ -24,10 +21,10 @@ with lib;
###### implementation ###### implementation
imports = [ imports = [
(mkRenamedOptionModule ["hardware" "usbWwan" ] ["hardware" "usb-modeswitch" ]) (lib.mkRenamedOptionModule ["hardware" "usbWwan" ] ["hardware" "usb-modeswitch" ])
]; ];
config = mkIf config.hardware.usb-modeswitch.enable { config = lib.mkIf config.hardware.usb-modeswitch.enable {
# Attaches device specific handlers. # Attaches device specific handlers.
services.udev.packages = with pkgs; [ usb-modeswitch-data ]; services.udev.packages = with pkgs; [ usb-modeswitch-data ];

View file

@ -1,9 +1,7 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
{ {
options.hardware.usbStorage.manageStartStop = mkOption { options.hardware.usbStorage.manageStartStop = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = true; default = true;
description = '' description = ''
Enable this option to gracefully spin-down external storage during shutdown. Enable this option to gracefully spin-down external storage during shutdown.
@ -12,7 +10,7 @@ with lib;
''; '';
}; };
config = mkIf config.hardware.usbStorage.manageStartStop { config = lib.mkIf config.hardware.usbStorage.manageStartStop {
services.udev.extraRules = '' services.udev.extraRules = ''
ACTION=="add|change", SUBSYSTEM=="scsi_disk", DRIVERS=="usb-storage", ATTR{manage_system_start_stop}="1" ACTION=="add|change", SUBSYSTEM=="scsi_disk", DRIVERS=="usb-storage", ATTR{manage_system_start_stop}="1"
''; '';

View file

@ -1,6 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.hardware.bumblebee; cfg = config.hardware.bumblebee;
@ -26,9 +24,9 @@ in
options = { options = {
hardware.bumblebee = { hardware.bumblebee = {
enable = mkOption { enable = lib.mkOption {
default = false; default = false;
type = types.bool; type = lib.types.bool;
description = '' description = ''
Enable the bumblebee daemon to manage Optimus hybrid video cards. Enable the bumblebee daemon to manage Optimus hybrid video cards.
This should power off secondary GPU until its use is requested This should power off secondary GPU until its use is requested
@ -36,16 +34,16 @@ in
''; '';
}; };
group = mkOption { group = lib.mkOption {
default = "wheel"; default = "wheel";
example = "video"; example = "video";
type = types.str; type = lib.types.str;
description = "Group for bumblebee socket"; description = "Group for bumblebee socket";
}; };
connectDisplay = mkOption { connectDisplay = lib.mkOption {
default = false; default = false;
type = types.bool; type = lib.types.bool;
description = '' description = ''
Set to true if you intend to connect your discrete card to a Set to true if you intend to connect your discrete card to a
monitor. This option will set up your Nvidia card for EDID monitor. This option will set up your Nvidia card for EDID
@ -55,17 +53,17 @@ in
''; '';
}; };
driver = mkOption { driver = lib.mkOption {
default = "nvidia"; default = "nvidia";
type = types.enum [ "nvidia" "nouveau" ]; type = lib.types.enum [ "nvidia" "nouveau" ];
description = '' description = ''
Set driver used by bumblebeed. Supported are nouveau and nvidia. Set driver used by bumblebeed. Supported are nouveau and nvidia.
''; '';
}; };
pmMethod = mkOption { pmMethod = lib.mkOption {
default = "auto"; default = "auto";
type = types.enum [ "auto" "bbswitch" "switcheroo" "none" ]; type = lib.types.enum [ "auto" "bbswitch" "switcheroo" "none" ];
description = '' description = ''
Set preferred power management method for unused card. Set preferred power management method for unused card.
''; '';
@ -74,10 +72,10 @@ in
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
boot.blacklistedKernelModules = [ "nvidia-drm" "nvidia" "nouveau" ]; boot.blacklistedKernelModules = [ "nvidia-drm" "nvidia" "nouveau" ];
boot.kernelModules = optional useBbswitch "bbswitch"; boot.kernelModules = lib.optional useBbswitch "bbswitch";
boot.extraModulePackages = optional useBbswitch kernel.bbswitch ++ optional useNvidia kernel.nvidia_x11.bin; boot.extraModulePackages = lib.optional useBbswitch kernel.bbswitch ++ lib.optional useNvidia kernel.nvidia_x11.bin;
environment.systemPackages = [ bumblebee primus ]; environment.systemPackages = [ bumblebee primus ];

View file

@ -1,7 +1,4 @@
{ config, lib, ... }: { config, lib, ... }:
with lib;
let let
cfg = config.hardware.mwProCapture; cfg = config.hardware.mwProCapture;
@ -12,9 +9,9 @@ in
{ {
options.hardware.mwProCapture.enable = mkEnableOption "the Magewell Pro Capture family kernel module"; options.hardware.mwProCapture.enable = lib.mkEnableOption "the Magewell Pro Capture family kernel module";
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
boot.kernelModules = [ "ProCapture" ]; boot.kernelModules = [ "ProCapture" ];

View file

@ -1,10 +1,7 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
enabled = elem "displaylink" config.services.xserver.videoDrivers; enabled = lib.elem "displaylink" config.services.xserver.videoDrivers;
evdi = config.boot.kernelPackages.evdi; evdi = config.boot.kernelPackages.evdi;
@ -16,7 +13,7 @@ in
{ {
config = mkIf enabled { config = lib.mkIf enabled {
boot.extraModulePackages = [ evdi ]; boot.extraModulePackages = [ evdi ];
boot.kernelModules = [ "evdi" ]; boot.kernelModules = [ "evdi" ];

View file

@ -1,8 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.uvcvideo; cfg = config.services.uvcvideo;
@ -19,8 +15,8 @@ in
options = { options = {
services.uvcvideo.dynctrl = { services.uvcvideo.dynctrl = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Whether to enable {command}`uvcvideo` dynamic controls. Whether to enable {command}`uvcvideo` dynamic controls.
@ -31,9 +27,9 @@ in
''; '';
}; };
packages = mkOption { packages = lib.mkOption {
type = types.listOf types.path; type = lib.types.listOf lib.types.path;
example = literalExpression "[ pkgs.tiscamera ]"; example = lib.literalExpression "[ pkgs.tiscamera ]";
description = '' description = ''
List of packages containing {command}`uvcvideo` dynamic controls List of packages containing {command}`uvcvideo` dynamic controls
rules. All files found in rules. All files found in
@ -45,12 +41,12 @@ in
the dynamic controls from specified packages to the {command}`uvcvideo` the dynamic controls from specified packages to the {command}`uvcvideo`
driver. driver.
''; '';
apply = map getBin; apply = map lib.getBin;
}; };
}; };
}; };
config = mkIf cfg.dynctrl.enable { config = lib.mkIf cfg.dynctrl.enable {
services.udev.packages = [ services.udev.packages = [
(uvcdynctrl-udev-rules cfg.dynctrl.packages) (uvcdynctrl-udev-rules cfg.dynctrl.packages)

View file

@ -1,7 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.hardware.facetimehd; cfg = config.hardware.facetimehd;
@ -12,12 +9,12 @@ in
{ {
options.hardware.facetimehd.enable = mkEnableOption "the facetimehd kernel module"; options.hardware.facetimehd.enable = lib.mkEnableOption "the facetimehd kernel module";
options.hardware.facetimehd.withCalibration = mkOption { options.hardware.facetimehd.withCalibration = lib.mkOption {
default = false; default = false;
example = true; example = true;
type = types.bool; type = lib.types.bool;
description = '' description = ''
Whether to include sensor calibration files for facetimehd. Whether to include sensor calibration files for facetimehd.
This makes colors look much better but is experimental, see This makes colors look much better but is experimental, see
@ -26,7 +23,7 @@ in
''; '';
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
boot.kernelModules = [ "facetimehd" ]; boot.kernelModules = [ "facetimehd" ];
@ -35,7 +32,7 @@ in
boot.extraModulePackages = [ kernelPackages.facetimehd ]; boot.extraModulePackages = [ kernelPackages.facetimehd ];
hardware.firmware = [ pkgs.facetimehd-firmware ] hardware.firmware = [ pkgs.facetimehd-firmware ]
++ optional cfg.withCalibration pkgs.facetimehd-calibration; ++ lib.optional cfg.withCalibration pkgs.facetimehd-calibration;
# unload module during suspend/hibernate as it crashes the whole system # unload module during suspend/hibernate as it crashes the whole system
powerManagement.powerDownCommands = '' powerManagement.powerDownCommands = ''

View file

@ -1,11 +1,9 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
{ {
options.hardware.wooting.enable = mkEnableOption ''support for Wooting keyboards. options.hardware.wooting.enable = lib.mkEnableOption ''support for Wooting keyboards.
Note that users must be in the "input" group for udev rules to apply''; Note that users must be in the "input" group for udev rules to apply'';
config = mkIf config.hardware.wooting.enable { config = lib.mkIf config.hardware.wooting.enable {
environment.systemPackages = [ pkgs.wootility ]; environment.systemPackages = [ pkgs.wootility ];
services.udev.packages = [ pkgs.wooting-udev-rules ]; services.udev.packages = [ pkgs.wooting-udev-rules ];
}; };

View file

@ -1,15 +1,13 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.hardware.xone; cfg = config.hardware.xone;
in in
{ {
options.hardware.xone = { options.hardware.xone = {
enable = mkEnableOption "the xone driver for Xbox One and Xbox Series X|S accessories"; enable = lib.mkEnableOption "the xone driver for Xbox One and Xbox Series X|S accessories";
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
boot = { boot = {
blacklistedKernelModules = [ "xpad" "mt76x2u" ]; blacklistedKernelModules = [ "xpad" "mt76x2u" ];
extraModulePackages = with config.boot.kernelPackages; [ xone ]; extraModulePackages = with config.boot.kernelPackages; [ xone ];
@ -18,6 +16,6 @@ in
}; };
meta = { meta = {
maintainers = with maintainers; [ rhysmdnz ]; maintainers = with lib.maintainers; [ rhysmdnz ];
}; };
} }

View file

@ -1,20 +1,18 @@
{ config, lib, ... }: { config, lib, ... }:
with lib;
let let
cfg = config.hardware.xpadneo; cfg = config.hardware.xpadneo;
in in
{ {
options.hardware.xpadneo = { options.hardware.xpadneo = {
enable = mkEnableOption "the xpadneo driver for Xbox One wireless controllers"; enable = lib.mkEnableOption "the xpadneo driver for Xbox One wireless controllers";
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
boot = { boot = {
# Must disable Enhanced Retransmission Mode to support bluetooth pairing # Must disable Enhanced Retransmission Mode to support bluetooth pairing
# https://wiki.archlinux.org/index.php/Gamepad#Connect_Xbox_Wireless_Controller_with_Bluetooth # https://wiki.archlinux.org/index.php/Gamepad#Connect_Xbox_Wireless_Controller_with_Bluetooth
extraModprobeConfig = extraModprobeConfig =
mkIf lib.mkIf
(config.hardware.bluetooth.enable && (config.hardware.bluetooth.enable &&
(lib.versionOlder config.boot.kernelPackages.kernel.version "5.12")) (lib.versionOlder config.boot.kernelPackages.kernel.version "5.12"))
"options bluetooth disable_ertm=1"; "options bluetooth disable_ertm=1";
@ -25,6 +23,6 @@ in
}; };
meta = { meta = {
maintainers = with maintainers; [ kira-bruneau ]; maintainers = with lib.maintainers; [ kira-bruneau ];
}; };
} }

View file

@ -1,10 +1,8 @@
{ config, pkgs, lib, ... }: { config, pkgs, lib, ... }:
with lib;
let let
cfg = config.i18n.inputMethod; cfg = config.i18n.inputMethod;
allowedTypes = types.enum [ "ibus" "fcitx5" "nabi" "uim" "hime" "kime" ]; allowedTypes = lib.types.enum [ "ibus" "fcitx5" "nabi" "uim" "hime" "kime" ];
gtk2_cache = pkgs.runCommand "gtk2-immodule.cache" gtk2_cache = pkgs.runCommand "gtk2-immodule.cache"
{ preferLocalBuild = true; { preferLocalBuild = true;
@ -30,22 +28,22 @@ in
{ {
options.i18n = { options.i18n = {
inputMethod = { inputMethod = {
enable = mkEnableOption "an additional input method type" // { enable = lib.mkEnableOption "an additional input method type" // {
default = cfg.enabled != null; default = cfg.enabled != null;
defaultText = literalMD "`true` if the deprecated option `enabled` is set, false otherwise"; defaultText = lib.literalMD "`true` if the deprecated option `enabled` is set, false otherwise";
}; };
enabled = mkOption { enabled = lib.mkOption {
type = types.nullOr allowedTypes; type = lib.types.nullOr allowedTypes;
default = null; default = null;
example = "fcitx5"; example = "fcitx5";
description = "Deprecated - use `type` and `enable = true` instead"; description = "Deprecated - use `type` and `enable = true` instead";
}; };
type = mkOption { type = lib.mkOption {
type = types.nullOr allowedTypes; type = lib.types.nullOr allowedTypes;
default = cfg.enabled; default = cfg.enabled;
defaultText = literalMD "The value of the deprecated option `enabled`, defaulting to null"; defaultText = lib.literalMD "The value of the deprecated option `enabled`, defaulting to null";
example = "fcitx5"; example = "fcitx5";
description = '' description = ''
Select the enabled input method. Input methods is a software to input symbols that are not available on standard input devices. Select the enabled input method. Input methods is a software to input symbols that are not available on standard input devices.
@ -63,9 +61,9 @@ in
''; '';
}; };
package = mkOption { package = lib.mkOption {
internal = true; internal = true;
type = types.nullOr types.path; type = lib.types.nullOr lib.types.path;
default = null; default = null;
description = '' description = ''
The input method method package. The input method method package.
@ -74,8 +72,8 @@ in
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
warnings = optional (cfg.enabled != null) "i18n.inputMethod.enabled will be removed in a future release. Please use .type, and .enable = true instead"; warnings = lib.optional (cfg.enabled != null) "i18n.inputMethod.enabled will be removed in a future release. Please use .type, and .enable = true instead";
environment.systemPackages = [ cfg.package gtk2_cache gtk3_cache ]; environment.systemPackages = [ cfg.package gtk2_cache gtk3_cache ];
}; };

View file

@ -1,7 +1,4 @@
{ config, pkgs, lib, ... }: { config, pkgs, lib, ... }:
with lib;
let let
imcfg = config.i18n.inputMethod; imcfg = config.i18n.inputMethod;
cfg = imcfg.fcitx5; cfg = imcfg.fcitx5;
@ -14,35 +11,35 @@ in
{ {
options = { options = {
i18n.inputMethod.fcitx5 = { i18n.inputMethod.fcitx5 = {
addons = mkOption { addons = lib.mkOption {
type = with types; listOf package; type = with lib.types; listOf package;
default = [ ]; default = [ ];
example = literalExpression "with pkgs; [ fcitx5-rime ]"; example = lib.literalExpression "with pkgs; [ fcitx5-rime ]";
description = '' description = ''
Enabled Fcitx5 addons. Enabled Fcitx5 addons.
''; '';
}; };
waylandFrontend = mkOption { waylandFrontend = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Use the Wayland input method frontend. Use the Wayland input method frontend.
See [Using Fcitx 5 on Wayland](https://fcitx-im.org/wiki/Using_Fcitx_5_on_Wayland). See [Using Fcitx 5 on Wayland](https://fcitx-im.org/wiki/Using_Fcitx_5_on_Wayland).
''; '';
}; };
plasma6Support = mkOption { plasma6Support = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = config.services.desktopManager.plasma6.enable; default = config.services.desktopManager.plasma6.enable;
defaultText = literalExpression "config.services.desktopManager.plasma6.enable"; defaultText = lib.literalExpression "config.services.desktopManager.plasma6.enable";
description = '' description = ''
Use qt6 versions of fcitx5 packages. Use qt6 versions of fcitx5 packages.
Required for configuring fcitx5 in KDE System Settings. Required for configuring fcitx5 in KDE System Settings.
''; '';
}; };
quickPhrase = mkOption { quickPhrase = lib.mkOption {
type = with types; attrsOf str; type = with lib.types; attrsOf str;
default = { }; default = { };
example = literalExpression '' example = lib.literalExpression ''
{ {
smile = ""; smile = "";
angry = "()"; angry = "()";
@ -50,10 +47,10 @@ in
''; '';
description = "Quick phrases."; description = "Quick phrases.";
}; };
quickPhraseFiles = mkOption { quickPhraseFiles = lib.mkOption {
type = with types; attrsOf path; type = with lib.types; attrsOf path;
default = { }; default = { };
example = literalExpression '' example = lib.literalExpression ''
{ {
words = ./words.mb; words = ./words.mb;
numbers = ./numbers.mb; numbers = ./numbers.mb;
@ -87,7 +84,7 @@ in
The addon configures in `conf` folder in ini format with global sections. The addon configures in `conf` folder in ini format with global sections.
Each item is written to the corresponding file. Each item is written to the corresponding file.
''; '';
example = literalExpression "{ pinyin.globalSection.EmojiEnabled = \"True\"; }"; example = lib.literalExpression "{ pinyin.globalSection.EmojiEnabled = \"True\"; }";
}; };
}; };
ignoreUserConfig = lib.mkOption { ignoreUserConfig = lib.mkOption {
@ -103,12 +100,12 @@ in
}; };
imports = [ imports = [
(mkRemovedOptionModule [ "i18n" "inputMethod" "fcitx5" "enableRimeData" ] '' (lib.mkRemovedOptionModule [ "i18n" "inputMethod" "fcitx5" "enableRimeData" ] ''
RIME data is now included in `fcitx5-rime` by default, and can be customized using `fcitx5-rime.override { rimeDataPkgs = ...; }` RIME data is now included in `fcitx5-rime` by default, and can be customized using `fcitx5-rime.override { rimeDataPkgs = ...; }`
'') '')
]; ];
config = mkIf (imcfg.enable && imcfg.type == "fcitx5") { config = lib.mkIf (imcfg.enable && imcfg.type == "fcitx5") {
i18n.inputMethod.package = fcitx5Package; i18n.inputMethod.package = fcitx5Package;
i18n.inputMethod.fcitx5.addons = lib.optionals (cfg.quickPhrase != { }) [ i18n.inputMethod.fcitx5.addons = lib.optionals (cfg.quickPhrase != { }) [
@ -122,15 +119,15 @@ in
]; ];
environment.etc = environment.etc =
let let
optionalFile = p: f: v: lib.optionalAttrs (v != { }) { lib.optionalFile = p: f: v: lib.optionalAttrs (v != { }) {
"xdg/fcitx5/${p}".text = f v; "xdg/fcitx5/${p}".text = f v;
}; };
in in
lib.attrsets.mergeAttrsList [ lib.attrsets.mergeAttrsList [
(optionalFile "config" (lib.generators.toINI { }) cfg.settings.globalOptions) (lib.optionalFile "config" (lib.generators.toINI { }) cfg.settings.globalOptions)
(optionalFile "profile" (lib.generators.toINI { }) cfg.settings.inputMethod) (lib.optionalFile "profile" (lib.generators.toINI { }) cfg.settings.inputMethod)
(lib.concatMapAttrs (lib.concatMapAttrs
(name: value: optionalFile (name: value: lib.optionalFile
"conf/${name}.conf" "conf/${name}.conf"
(lib.generators.toINIWithGlobalSection { }) (lib.generators.toINIWithGlobalSection { })
value) value)

View file

@ -1,6 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.clamsmtp; cfg = config.services.clamsmtp;
clamdSocket = "/run/clamav/clamd.ctl"; # See services/security/clamav.nix clamdSocket = "/run/clamav/clamd.ctl"; # See services/security/clamav.nix
@ -9,17 +7,17 @@ in
##### interface ##### interface
options = { options = {
services.clamsmtp = { services.clamsmtp = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = "Whether to enable clamsmtp."; description = "Whether to enable clamsmtp.";
}; };
instances = mkOption { instances = lib.mkOption {
description = "Instances of clamsmtp to run."; description = "Instances of clamsmtp to run.";
type = types.listOf (types.submodule { options = { type = lib.types.listOf (lib.types.submodule { options = {
action = mkOption { action = lib.mkOption {
type = types.enum [ "bounce" "drop" "pass" ]; type = lib.types.enum [ "bounce" "drop" "pass" ];
default = "drop"; default = "drop";
description = '' description = ''
Action to take when a virus is detected. Action to take when a virus is detected.
@ -29,8 +27,8 @@ in
''; '';
}; };
header = mkOption { header = lib.mkOption {
type = types.str; type = lib.types.str;
default = ""; default = "";
example = "X-Virus-Scanned: ClamAV using ClamSMTP"; example = "X-Virus-Scanned: ClamAV using ClamSMTP";
description = '' description = ''
@ -39,8 +37,8 @@ in
''; '';
}; };
keepAlives = mkOption { keepAlives = lib.mkOption {
type = types.int; type = lib.types.int;
default = 0; default = 0;
description = '' description = ''
Number of seconds to wait between each NOOP sent to the sending Number of seconds to wait between each NOOP sent to the sending
@ -51,8 +49,8 @@ in
''; '';
}; };
listen = mkOption { listen = lib.mkOption {
type = types.str; type = lib.types.str;
example = "127.0.0.1:10025"; example = "127.0.0.1:10025";
description = '' description = ''
Address to wait for incoming SMTP connections on. See Address to wait for incoming SMTP connections on. See
@ -60,8 +58,8 @@ in
''; '';
}; };
quarantine = mkOption { quarantine = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Whether to quarantine files that contain viruses by leaving them Whether to quarantine files that contain viruses by leaving them
@ -69,22 +67,22 @@ in
''; '';
}; };
maxConnections = mkOption { maxConnections = lib.mkOption {
type = types.int; type = lib.types.int;
default = 64; default = 64;
description = "Maximum number of connections to accept at once."; description = "Maximum number of connections to accept at once.";
}; };
outAddress = mkOption { outAddress = lib.mkOption {
type = types.str; type = lib.types.str;
description = '' description = ''
Address of the SMTP server to send email to once it has been Address of the SMTP server to send email to once it has been
scanned. scanned.
''; '';
}; };
tempDirectory = mkOption { tempDirectory = lib.mkOption {
type = types.str; type = lib.types.str;
default = "/tmp"; default = "/tmp";
description = '' description = ''
Temporary directory that needs to be accessible to both clamd Temporary directory that needs to be accessible to both clamd
@ -92,20 +90,20 @@ in
''; '';
}; };
timeout = mkOption { timeout = lib.mkOption {
type = types.int; type = lib.types.int;
default = 180; default = 180;
description = "Time-out for network connections."; description = "Time-out for network connections.";
}; };
transparentProxy = mkOption { transparentProxy = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = "Enable clamsmtp's transparent proxy support."; description = "Enable clamsmtp's transparent proxy support.";
}; };
virusAction = mkOption { virusAction = lib.mkOption {
type = with types; nullOr path; type = with lib.types; nullOr path;
default = null; default = null;
description = '' description = ''
Command to run when a virus is found. Please see VIRUS ACTION in Command to run when a virus is found. Please see VIRUS ACTION in
@ -113,8 +111,8 @@ in
''; '';
}; };
xClient = mkOption { xClient = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Send the XCLIENT command to the receiving server, for forwarding Send the XCLIENT command to the receiving server, for forwarding
@ -143,19 +141,19 @@ in
TimeOut: ${toString conf.timeout} TimeOut: ${toString conf.timeout}
TransparentProxy: ${if conf.transparentProxy then "on" else "off"} TransparentProxy: ${if conf.transparentProxy then "on" else "off"}
User: clamav User: clamav
${optionalString (conf.virusAction != null) "VirusAction: ${conf.virusAction}"} ${lib.optionalString (conf.virusAction != null) "VirusAction: ${conf.virusAction}"}
XClient: ${if conf.xClient then "on" else "off"} XClient: ${if conf.xClient then "on" else "off"}
''; '';
in in
mkIf cfg.enable { lib.mkIf cfg.enable {
assertions = [ assertions = [
{ assertion = config.services.clamav.daemon.enable; { assertion = config.services.clamav.daemon.enable;
message = "clamsmtp requires clamav to be enabled"; message = "clamsmtp requires clamav to be enabled";
} }
]; ];
systemd.services = listToAttrs (imap1 (i: conf: systemd.services = lib.listToAttrs (lib.imap1 (i: conf:
nameValuePair "clamsmtp-${toString i}" { lib.nameValuePair "clamsmtp-${toString i}" {
description = "ClamSMTP instance ${toString i}"; description = "ClamSMTP instance ${toString i}";
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
script = "exec ${pkgs.clamsmtp}/bin/clamsmtpd -f ${configfile conf}"; script = "exec ${pkgs.clamsmtp}/bin/clamsmtpd -f ${configfile conf}";

View file

@ -1,39 +1,36 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.davmail; cfg = config.services.davmail;
configType = with types; configType = with lib.types;
oneOf [ (attrsOf configType) str int bool ] // { oneOf [ (attrsOf configType) str int bool ] // {
description = "davmail config type (str, int, bool or attribute set thereof)"; description = "davmail config type (str, int, bool or attribute set thereof)";
}; };
toStr = val: if isBool val then boolToString val else toString val; toStr = val: if lib.isBool val then lib.boolToString val else toString val;
linesForAttrs = attrs: concatMap (name: let value = attrs.${name}; in linesForAttrs = attrs: lib.concatMap (name: let value = attrs.${name}; in
if isAttrs value if lib.isAttrs value
then map (line: name + "." + line) (linesForAttrs value) then map (line: name + "." + line) (linesForAttrs value)
else [ "${name}=${toStr value}" ] else [ "${name}=${toStr value}" ]
) (attrNames attrs); ) (lib.attrNames attrs);
configFile = pkgs.writeText "davmail.properties" (concatStringsSep "\n" (linesForAttrs cfg.config)); configFile = pkgs.writeText "davmail.properties" (lib.concatStringsSep "\n" (linesForAttrs cfg.config));
in in
{ {
options.services.davmail = { options.services.davmail = {
enable = mkEnableOption "davmail, an MS Exchange gateway"; enable = lib.mkEnableOption "davmail, an MS Exchange gateway";
url = mkOption { url = lib.mkOption {
type = types.str; type = lib.types.str;
description = "Outlook Web Access URL to access the exchange server, i.e. the base webmail URL."; description = "Outlook Web Access URL to access the exchange server, i.e. the base webmail URL.";
example = "https://outlook.office365.com/EWS/Exchange.asmx"; example = "https://outlook.office365.com/EWS/Exchange.asmx";
}; };
config = mkOption { config = lib.mkOption {
type = configType; type = configType;
default = {}; default = {};
description = '' description = ''
@ -42,7 +39,7 @@ in
and <http://davmail.sourceforge.net/advanced.html> and <http://davmail.sourceforge.net/advanced.html>
for details on supported values. for details on supported values.
''; '';
example = literalExpression '' example = lib.literalExpression ''
{ {
davmail.allowRemote = true; davmail.allowRemote = true;
davmail.imapPort = 55555; davmail.imapPort = 55555;
@ -56,10 +53,10 @@ in
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
services.davmail.config = { services.davmail.config = {
davmail = mapAttrs (name: mkDefault) { davmail = lib.mapAttrs (name: lib.mkDefault) {
server = true; server = true;
disableUpdateCheck = true; disableUpdateCheck = true;
logFilePath = "/var/log/davmail/davmail.log"; logFilePath = "/var/log/davmail/davmail.log";
@ -73,10 +70,10 @@ in
smtpPort = 1025; smtpPort = 1025;
}; };
log4j = { log4j = {
logger.davmail = mkDefault "WARN"; logger.davmail = lib.mkDefault "WARN";
logger.httpclient.wire = mkDefault "WARN"; logger.httpclient.wire = lib.mkDefault "WARN";
logger.org.apache.commons.httpclient = mkDefault "WARN"; logger.org.apache.commons.httpclient = lib.mkDefault "WARN";
rootLogger = mkDefault "WARN"; rootLogger = lib.mkDefault "WARN";
}; };
}; };

View file

@ -1,6 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.dkimproxy-out; cfg = config.services.dkimproxy-out;
keydir = "/var/lib/dkimproxy-out"; keydir = "/var/lib/dkimproxy-out";
@ -11,8 +9,8 @@ in
##### interface ##### interface
options = { options = {
services.dkimproxy-out = { services.dkimproxy-out = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Whether to enable dkimproxy_out. Whether to enable dkimproxy_out.
@ -22,26 +20,26 @@ in
''; '';
}; };
listen = mkOption { listen = lib.mkOption {
type = types.str; type = lib.types.str;
example = "127.0.0.1:10027"; example = "127.0.0.1:10027";
description = "Address:port DKIMproxy should listen on."; description = "Address:port DKIMproxy should listen on.";
}; };
relay = mkOption { relay = lib.mkOption {
type = types.str; type = lib.types.str;
example = "127.0.0.1:10028"; example = "127.0.0.1:10028";
description = "Address:port DKIMproxy should forward mail to."; description = "Address:port DKIMproxy should forward mail to.";
}; };
domains = mkOption { domains = lib.mkOption {
type = with types; listOf str; type = with lib.types; listOf str;
example = [ "example.org" "example.com" ]; example = [ "example.org" "example.com" ];
description = "List of domains DKIMproxy can sign for."; description = "List of domains DKIMproxy can sign for.";
}; };
selector = mkOption { selector = lib.mkOption {
type = types.str; type = lib.types.str;
example = "selector1"; example = "selector1";
description = '' description = ''
The selector to use for DKIM key identification. The selector to use for DKIM key identification.
@ -53,8 +51,8 @@ in
''; '';
}; };
keySize = mkOption { keySize = lib.mkOption {
type = types.int; type = lib.types.int;
default = 2048; default = 2048;
description = '' description = ''
Size of the RSA key to use to sign outgoing emails. Note that the Size of the RSA key to use to sign outgoing emails. Note that the
@ -75,7 +73,7 @@ in
listen ${cfg.listen} listen ${cfg.listen}
relay ${cfg.relay} relay ${cfg.relay}
domain ${concatStringsSep "," cfg.domains} domain ${lib.concatStringsSep "," cfg.domains}
selector ${cfg.selector} selector ${cfg.selector}
signature dkim(c=relaxed/relaxed) signature dkim(c=relaxed/relaxed)
@ -83,7 +81,7 @@ in
keyfile ${privkey} keyfile ${privkey}
''; '';
in in
mkIf cfg.enable { lib.mkIf cfg.enable {
users.groups.dkimproxy-out = {}; users.groups.dkimproxy-out = {};
users.users.dkimproxy-out = { users.users.dkimproxy-out = {
description = "DKIMproxy_out daemon"; description = "DKIMproxy_out daemon";

View file

@ -1,7 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.dspam; cfg = config.services.dspam;
@ -19,7 +16,7 @@ let
SystemLog on SystemLog on
UserLog on UserLog on
${optionalString (cfg.domainSocket != null) '' ${lib.optionalString (cfg.domainSocket != null) ''
ServerDomainSocketPath "${cfg.domainSocket}" ServerDomainSocketPath "${cfg.domainSocket}"
ClientHost "${cfg.domainSocket}" ClientHost "${cfg.domainSocket}"
''} ''}
@ -35,44 +32,44 @@ in {
services.dspam = { services.dspam = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = "Whether to enable the dspam spam filter."; description = "Whether to enable the dspam spam filter.";
}; };
user = mkOption { user = lib.mkOption {
type = types.str; type = lib.types.str;
default = "dspam"; default = "dspam";
description = "User for the dspam daemon."; description = "User for the dspam daemon.";
}; };
group = mkOption { group = lib.mkOption {
type = types.str; type = lib.types.str;
default = "dspam"; default = "dspam";
description = "Group for the dspam daemon."; description = "Group for the dspam daemon.";
}; };
storageDriver = mkOption { storageDriver = lib.mkOption {
type = types.str; type = lib.types.str;
default = "hash"; default = "hash";
description = "Storage driver backend to use for dspam."; description = "Storage driver backend to use for dspam.";
}; };
domainSocket = mkOption { domainSocket = lib.mkOption {
type = types.nullOr types.path; type = lib.types.nullOr lib.types.path;
default = defaultSock; default = defaultSock;
description = "Path to local domain socket which is used for communication with the daemon. Set to null to disable UNIX socket."; description = "Path to local domain socket which is used for communication with the daemon. Set to null to disable UNIX socket.";
}; };
extraConfig = mkOption { extraConfig = lib.mkOption {
type = types.lines; type = lib.types.lines;
default = ""; default = "";
description = "Additional dspam configuration."; description = "Additional dspam configuration.";
}; };
maintenanceInterval = mkOption { maintenanceInterval = lib.mkOption {
type = types.nullOr types.str; type = lib.types.nullOr lib.types.str;
default = null; default = null;
description = "If set, maintenance script will be run at specified (in systemd.timer format) interval"; description = "If set, maintenance script will be run at specified (in systemd.timer format) interval";
}; };
@ -84,16 +81,16 @@ in {
###### implementation ###### implementation
config = mkIf cfg.enable (mkMerge [ config = lib.mkIf cfg.enable (lib.mkMerge [
{ {
users.users = optionalAttrs (cfg.user == "dspam") { users.users = lib.optionalAttrs (cfg.user == "dspam") {
dspam = { dspam = {
group = cfg.group; group = cfg.group;
uid = config.ids.uids.dspam; uid = config.ids.uids.dspam;
}; };
}; };
users.groups = optionalAttrs (cfg.group == "dspam") { users.groups = lib.optionalAttrs (cfg.group == "dspam") {
dspam.gid = config.ids.gids.dspam; dspam.gid = config.ids.gids.dspam;
}; };
@ -111,8 +108,8 @@ in {
ExecStart = "${dspam}/bin/dspam --daemon --nofork"; ExecStart = "${dspam}/bin/dspam --daemon --nofork";
User = cfg.user; User = cfg.user;
Group = cfg.group; Group = cfg.group;
RuntimeDirectory = optional (cfg.domainSocket == defaultSock) "dspam"; RuntimeDirectory = lib.optional (cfg.domainSocket == defaultSock) "dspam";
RuntimeDirectoryMode = optional (cfg.domainSocket == defaultSock) "0750"; RuntimeDirectoryMode = lib.optional (cfg.domainSocket == defaultSock) "0750";
StateDirectory = "dspam"; StateDirectory = "dspam";
StateDirectoryMode = "0750"; StateDirectoryMode = "0750";
LogsDirectory = "dspam"; LogsDirectory = "dspam";
@ -124,7 +121,7 @@ in {
}; };
} }
(mkIf (cfg.maintenanceInterval != null) { (lib.mkIf (cfg.maintenanceInterval != null) {
systemd.timers.dspam-maintenance = { systemd.timers.dspam-maintenance = {
description = "Timer for dspam maintenance script"; description = "Timer for dspam maintenance script";
wantedBy = [ "timers.target" ]; wantedBy = [ "timers.target" ];

View file

@ -1,16 +1,13 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.goeland; cfg = config.services.goeland;
tomlFormat = pkgs.formats.toml { }; tomlFormat = pkgs.formats.toml { };
in in
{ {
options.services.goeland = { options.services.goeland = {
enable = mkEnableOption "goeland, an alternative to rss2email"; enable = lib.mkEnableOption "goeland, an alternative to rss2email";
settings = mkOption { settings = lib.mkOption {
description = '' description = ''
Configuration of goeland. Configuration of goeland.
See the [example config file](https://github.com/slurdge/goeland/blob/master/cmd/asset/config.default.toml) for the available options. See the [example config file](https://github.com/slurdge/goeland/blob/master/cmd/asset/config.default.toml) for the available options.
@ -18,14 +15,14 @@ in
default = { }; default = { };
type = tomlFormat.type; type = tomlFormat.type;
}; };
schedule = mkOption { schedule = lib.mkOption {
type = types.str; type = lib.types.str;
default = "12h"; default = "12h";
example = "Mon, 00:00:00"; example = "Mon, 00:00:00";
description = "How often to run goeland, in systemd time format."; description = "How often to run goeland, in systemd time format.";
}; };
stateDir = mkOption { stateDir = lib.mkOption {
type = types.path; type = lib.types.path;
default = "/var/lib/goeland"; default = "/var/lib/goeland";
description = '' description = ''
The data directory for goeland where the database will reside if using the unseen filter. The data directory for goeland where the database will reside if using the unseen filter.
@ -36,17 +33,17 @@ in
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
services.goeland.settings.database = "${cfg.stateDir}/goeland.db"; services.goeland.settings.database = "${cfg.stateDir}/goeland.db";
systemd.services.goeland = { systemd.services.goeland = {
serviceConfig = let confFile = tomlFormat.generate "config.toml" cfg.settings; in mkMerge [ serviceConfig = let confFile = tomlFormat.generate "config.toml" cfg.settings; in lib.mkMerge [
{ {
ExecStart = "${pkgs.goeland}/bin/goeland run -c ${confFile}"; ExecStart = "${pkgs.goeland}/bin/goeland run -c ${confFile}";
User = "goeland"; User = "goeland";
Group = "goeland"; Group = "goeland";
} }
(mkIf (cfg.stateDir == "/var/lib/goeland") { (lib.mkIf (cfg.stateDir == "/var/lib/goeland") {
StateDirectory = "goeland"; StateDirectory = "goeland";
StateDirectoryMode = "0750"; StateDirectoryMode = "0750";
}) })
@ -61,7 +58,7 @@ in
}; };
users.groups.goeland = { }; users.groups.goeland = { };
warnings = optionals (hasAttr "password" cfg.settings.email) [ warnings = lib.optionals (lib.hasAttr "password" cfg.settings.email) [
'' ''
It is not recommended to set the "services.goeland.settings.email.password" It is not recommended to set the "services.goeland.settings.email.password"
option as it will be in cleartext in the Nix store. option as it will be in cleartext in the Nix store.
@ -70,5 +67,5 @@ in
]; ];
}; };
meta.maintainers = with maintainers; [ sweenu ]; meta.maintainers = with lib.maintainers; [ sweenu ];
} }

View file

@ -1,6 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.listmonk; cfg = config.services.listmonk;
tomlFormat = pkgs.formats.toml { }; tomlFormat = pkgs.formats.toml { };
@ -11,7 +9,7 @@ let
lib.replaceStrings [ "'" ] [ "''" ] (builtins.toJSON value) lib.replaceStrings [ "'" ] [ "''" ] (builtins.toJSON value)
}' WHERE key = '${key}';"; }' WHERE key = '${key}';";
updateDatabaseConfigSQL = pkgs.writeText "update-database-config.sql" updateDatabaseConfigSQL = pkgs.writeText "update-database-config.sql"
(concatStringsSep "\n" (mapAttrsToList setDatabaseOption (lib.concatStringsSep "\n" (lib.mapAttrsToList setDatabaseOption
(if (cfg.database.settings != null) then (if (cfg.database.settings != null) then
cfg.database.settings cfg.database.settings
else else
@ -27,53 +25,53 @@ let
"${pkgs.postgresql}/bin/psql -d listmonk -f ${updateDatabaseConfigSQL}"} "${pkgs.postgresql}/bin/psql -d listmonk -f ${updateDatabaseConfigSQL}"}
''; '';
databaseSettingsOpts = with types; { databaseSettingsOpts = with lib.types; {
freeformType = freeformType =
oneOf [ (listOf str) (listOf (attrsOf anything)) str int bool ]; oneOf [ (listOf str) (listOf (attrsOf anything)) str int bool ];
options = { options = {
"app.notify_emails" = mkOption { "app.notify_emails" = lib.mkOption {
type = listOf str; type = listOf str;
default = [ ]; default = [ ];
description = "Administrator emails for system notifications"; description = "Administrator emails for system notifications";
}; };
"privacy.exportable" = mkOption { "privacy.exportable" = lib.mkOption {
type = listOf str; type = listOf str;
default = [ "profile" "subscriptions" "campaign_views" "link_clicks" ]; default = [ "profile" "subscriptions" "campaign_views" "link_clicks" ];
description = description =
"List of fields which can be exported through an automatic export request"; "List of fields which can be exported through an automatic export request";
}; };
"privacy.domain_blocklist" = mkOption { "privacy.domain_blocklist" = lib.mkOption {
type = listOf str; type = listOf str;
default = [ ]; default = [ ];
description = description =
"E-mail addresses with these domains are disallowed from subscribing."; "E-mail addresses with these domains are disallowed from subscribing.";
}; };
smtp = mkOption { smtp = lib.mkOption {
type = listOf (submodule { type = listOf (submodule {
freeformType = with types; attrsOf anything; freeformType = with lib.types; attrsOf anything;
options = { options = {
enabled = mkEnableOption "this SMTP server for listmonk"; enabled = lib.mkEnableOption "this SMTP server for listmonk";
host = mkOption { host = lib.mkOption {
type = types.str; type = lib.types.str;
description = "Hostname for the SMTP server"; description = "Hostname for the SMTP server";
}; };
port = mkOption { port = lib.mkOption {
type = types.port; type = lib.types.port;
description = "Port for the SMTP server"; description = "Port for the SMTP server";
}; };
max_conns = mkOption { max_conns = lib.mkOption {
type = types.int; type = lib.types.int;
description = description =
"Maximum number of simultaneous connections, defaults to 1"; "Maximum number of simultaneous connections, defaults to 1";
default = 1; default = 1;
}; };
tls_type = mkOption { tls_type = lib.mkOption {
type = types.enum [ "none" "STARTTLS" "TLS" ]; type = lib.types.enum [ "none" "STARTTLS" "TLS" ];
description = "Type of TLS authentication with the SMTP server"; description = "Type of TLS authentication with the SMTP server";
}; };
}; };
@ -83,14 +81,14 @@ let
}; };
# TODO: refine this type based on the smtp one. # TODO: refine this type based on the smtp one.
"bounce.mailboxes" = mkOption { "bounce.mailboxes" = lib.mkOption {
type = listOf type = listOf
(submodule { freeformType = with types; listOf (attrsOf anything); }); (submodule { freeformType = with lib.types; listOf (attrsOf anything); });
default = [ ]; default = [ ];
description = "List of bounce mailboxes"; description = "List of bounce mailboxes";
}; };
messengers = mkOption { messengers = lib.mkOption {
type = listOf str; type = listOf str;
default = [ ]; default = [ ];
description = description =
@ -102,23 +100,23 @@ in {
###### interface ###### interface
options = { options = {
services.listmonk = { services.listmonk = {
enable = mkEnableOption "Listmonk, this module assumes a reverse proxy to be set"; enable = lib.mkEnableOption "Listmonk, this module assumes a reverse proxy to be set";
database = { database = {
createLocally = mkOption { createLocally = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = description =
"Create the PostgreSQL database and database user locally."; "Create the PostgreSQL database and database user locally.";
}; };
settings = mkOption { settings = lib.mkOption {
default = null; default = null;
type = with types; nullOr (submodule databaseSettingsOpts); type = with lib.types; nullOr (submodule databaseSettingsOpts);
description = description =
"Dynamic settings in the PostgreSQL database, set by a SQL script, see <https://github.com/knadh/listmonk/blob/master/schema.sql#L177-L230> for details."; "Dynamic settings in the PostgreSQL database, set by a SQL script, see <https://github.com/knadh/listmonk/blob/master/schema.sql#L177-L230> for details.";
}; };
mutableSettings = mkOption { mutableSettings = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = true; default = true;
description = '' description = ''
Database settings will be reset to the value set in this module if this is not enabled. Database settings will be reset to the value set in this module if this is not enabled.
@ -126,16 +124,16 @@ in {
''; '';
}; };
}; };
package = mkPackageOption pkgs "listmonk" {}; package = lib.mkPackageOption pkgs "listmonk" {};
settings = mkOption { settings = lib.mkOption {
type = types.submodule { freeformType = tomlFormat.type; }; type = lib.types.submodule { freeformType = tomlFormat.type; };
description = '' description = ''
Static settings set in the config.toml, see <https://github.com/knadh/listmonk/blob/master/config.toml.sample> for details. Static settings set in the config.toml, see <https://github.com/knadh/listmonk/blob/master/config.toml.sample> for details.
You can set secrets using the secretFile option with environment variables following <https://listmonk.app/docs/configuration/#environment-variables>. You can set secrets using the secretFile option with environment variables following <https://listmonk.app/docs/configuration/#environment-variables>.
''; '';
}; };
secretFile = mkOption { secretFile = lib.mkOption {
type = types.nullOr types.str; type = lib.types.nullOr lib.types.str;
default = null; default = null;
description = description =
"A file containing secrets as environment variables. See <https://listmonk.app/docs/configuration/#environment-variables> for details on supported values."; "A file containing secrets as environment variables. See <https://listmonk.app/docs/configuration/#environment-variables> for details on supported values.";
@ -144,24 +142,24 @@ in {
}; };
###### implementation ###### implementation
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
# Default parameters from https://github.com/knadh/listmonk/blob/master/config.toml.sample # Default parameters from https://github.com/knadh/listmonk/blob/master/config.toml.sample
services.listmonk.settings."app".address = mkDefault "localhost:9000"; services.listmonk.settings."app".address = lib.mkDefault "localhost:9000";
services.listmonk.settings."db" = mkMerge [ services.listmonk.settings."db" = lib.mkMerge [
({ ({
max_open = mkDefault 25; max_open = lib.mkDefault 25;
max_idle = mkDefault 25; max_idle = lib.mkDefault 25;
max_lifetime = mkDefault "300s"; max_lifetime = lib.mkDefault "300s";
}) })
(mkIf cfg.database.createLocally { (lib.mkIf cfg.database.createLocally {
host = mkDefault "/run/postgresql"; host = lib.mkDefault "/run/postgresql";
port = mkDefault 5432; port = lib.mkDefault 5432;
user = mkDefault "listmonk"; user = lib.mkDefault "listmonk";
database = mkDefault "listmonk"; database = lib.mkDefault "listmonk";
}) })
]; ];
services.postgresql = mkIf cfg.database.createLocally { services.postgresql = lib.mkIf cfg.database.createLocally {
enable = true; enable = true;
ensureUsers = [{ ensureUsers = [{
@ -175,11 +173,11 @@ in {
systemd.services.listmonk = { systemd.services.listmonk = {
description = "Listmonk - newsletter and mailing list manager"; description = "Listmonk - newsletter and mailing list manager";
after = [ "network.target" ] after = [ "network.target" ]
++ optional cfg.database.createLocally "postgresql.service"; ++ lib.optional cfg.database.createLocally "postgresql.service";
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
serviceConfig = { serviceConfig = {
Type = "exec"; Type = "exec";
EnvironmentFile = mkIf (cfg.secretFile != null) [ cfg.secretFile ]; EnvironmentFile = lib.mkIf (cfg.secretFile != null) [ cfg.secretFile ];
ExecStartPre = [ ExecStartPre = [
# StateDirectory cannot be used when DynamicUser = true is set this way. # StateDirectory cannot be used when DynamicUser = true is set this way.
# Indeed, it will try to create all the folders and realize one of them already exist. # Indeed, it will try to create all the folders and realize one of them already exist.

View file

@ -1,7 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
name = "maddy"; name = "maddy";
@ -138,11 +135,11 @@ in {
options = { options = {
services.maddy = { services.maddy = {
enable = mkEnableOption "Maddy, a free an open source mail server"; enable = lib.mkEnableOption "Maddy, a free an open source mail server";
user = mkOption { user = lib.mkOption {
default = "maddy"; default = "maddy";
type = with types; uniq str; type = with lib.types; uniq str;
description = '' description = ''
User account under which maddy runs. User account under which maddy runs.
@ -154,9 +151,9 @@ in {
''; '';
}; };
group = mkOption { group = lib.mkOption {
default = "maddy"; default = "maddy";
type = with types; uniq str; type = with lib.types; uniq str;
description = '' description = ''
Group account under which maddy runs. Group account under which maddy runs.
@ -168,26 +165,26 @@ in {
''; '';
}; };
hostname = mkOption { hostname = lib.mkOption {
default = "localhost"; default = "localhost";
type = with types; uniq str; type = with lib.types; uniq str;
example = ''example.com''; example = ''example.com'';
description = '' description = ''
Hostname to use. It should be FQDN. Hostname to use. It should be FQDN.
''; '';
}; };
primaryDomain = mkOption { primaryDomain = lib.mkOption {
default = "localhost"; default = "localhost";
type = with types; uniq str; type = with lib.types; uniq str;
example = ''mail.example.com''; example = ''mail.example.com'';
description = '' description = ''
Primary MX domain to use. It should be FQDN. Primary MX domain to use. It should be FQDN.
''; '';
}; };
localDomains = mkOption { localDomains = lib.mkOption {
type = with types; listOf str; type = with lib.types; listOf str;
default = ["$(primary_domain)"]; default = ["$(primary_domain)"];
example = [ example = [
"$(primary_domain)" "$(primary_domain)"
@ -199,8 +196,8 @@ in {
''; '';
}; };
config = mkOption { config = lib.mkOption {
type = with types; nullOr lines; type = with lib.types; nullOr lines;
default = defaultConfig; default = defaultConfig;
description = '' description = ''
Server configuration, see Server configuration, see
@ -215,8 +212,8 @@ in {
}; };
tls = { tls = {
loader = mkOption { loader = lib.mkOption {
type = with types; nullOr (enum [ "off" "file" "acme" ]); type = with lib.types; nullOr (enum [ "off" "file" "acme" ]);
default = "off"; default = "off";
description = '' description = ''
TLS certificates are obtained by modules called "certificate TLS certificates are obtained by modules called "certificate
@ -237,18 +234,18 @@ in {
''; '';
}; };
certificates = mkOption { certificates = lib.mkOption {
type = with types; listOf (submodule { type = with lib.types; listOf (submodule {
options = { options = {
keyPath = mkOption { keyPath = lib.mkOption {
type = types.path; type = lib.types.path;
example = "/etc/ssl/mx1.example.org.key"; example = "/etc/ssl/mx1.example.org.key";
description = '' description = ''
Path to the private key used for TLS. Path to the private key used for TLS.
''; '';
}; };
certPath = mkOption { certPath = lib.mkOption {
type = types.path; type = lib.types.path;
example = "/etc/ssl/mx1.example.org.crt"; example = "/etc/ssl/mx1.example.org.crt";
description = '' description = ''
Path to the certificate used for TLS. Path to the certificate used for TLS.
@ -269,8 +266,8 @@ in {
''; '';
}; };
extraConfig = mkOption { extraConfig = lib.mkOption {
type = with types; nullOr lines; type = with lib.types; nullOr lines;
description = '' description = ''
Arguments for the specified certificate loader. Arguments for the specified certificate loader.
@ -284,16 +281,16 @@ in {
}; };
}; };
openFirewall = mkOption { openFirewall = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Open the configured incoming and outgoing mail server ports. Open the configured incoming and outgoing mail server ports.
''; '';
}; };
ensureAccounts = mkOption { ensureAccounts = lib.mkOption {
type = with types; listOf str; type = with lib.types; listOf str;
default = []; default = [];
description = '' description = ''
List of IMAP accounts which get automatically created. Note that for List of IMAP accounts which get automatically created. Note that for
@ -307,7 +304,7 @@ in {
]; ];
}; };
ensureCredentials = mkOption { ensureCredentials = lib.mkOption {
default = {}; default = {};
description = '' description = ''
List of user accounts which get automatically created if they don't List of user accounts which get automatically created if they don't
@ -319,10 +316,10 @@ in {
"user1@localhost".passwordFile = /secrets/user1-localhost; "user1@localhost".passwordFile = /secrets/user1-localhost;
"user2@localhost".passwordFile = /secrets/user2-localhost; "user2@localhost".passwordFile = /secrets/user2-localhost;
}; };
type = types.attrsOf (types.submodule { type = lib.types.attrsOf (lib.types.submodule {
options = { options = {
passwordFile = mkOption { passwordFile = lib.mkOption {
type = types.path; type = lib.types.path;
example = "/path/to/file"; example = "/path/to/file";
default = null; default = null;
description = '' description = ''
@ -335,7 +332,7 @@ in {
}; };
secrets = lib.mkOption { secrets = lib.mkOption {
type = with types; listOf path; type = with lib.types; listOf path;
description = '' description = ''
A list of files containing the various secrets. Should be in the format A list of files containing the various secrets. Should be in the format
expected by systemd's `EnvironmentFile` directory. Secrets can be expected by systemd's `EnvironmentFile` directory. Secrets can be
@ -347,7 +344,7 @@ in {
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
assertions = [ assertions = [
{ {
@ -387,17 +384,17 @@ in {
}; };
maddy-ensure-accounts = { maddy-ensure-accounts = {
script = '' script = ''
${optionalString (cfg.ensureAccounts != []) '' ${lib.optionalString (cfg.ensureAccounts != []) ''
${concatMapStrings (account: '' ${lib.concatMapStrings (account: ''
if ! ${pkgs.maddy}/bin/maddyctl imap-acct list | grep "${account}"; then if ! ${pkgs.maddy}/bin/maddyctl imap-acct list | grep "${account}"; then
${pkgs.maddy}/bin/maddyctl imap-acct create ${account} ${pkgs.maddy}/bin/maddyctl imap-acct create ${account}
fi fi
'') cfg.ensureAccounts} '') cfg.ensureAccounts}
''} ''}
${optionalString (cfg.ensureCredentials != {}) '' ${lib.optionalString (cfg.ensureCredentials != {}) ''
${concatStringsSep "\n" (mapAttrsToList (name: cfg: '' ${lib.concatStringsSep "\n" (lib.mapAttrsToList (name: cfg: ''
if ! ${pkgs.maddy}/bin/maddyctl creds list | grep "${name}"; then if ! ${pkgs.maddy}/bin/maddyctl creds list | grep "${name}"; then
${pkgs.maddy}/bin/maddyctl creds create --password $(cat ${escapeShellArg cfg.passwordFile}) ${name} ${pkgs.maddy}/bin/maddyctl creds create --password $(cat ${lib.escapeShellArg cfg.passwordFile}) ${name}
fi fi
'') cfg.ensureCredentials)} '') cfg.ensureCredentials)}
''} ''}
@ -422,9 +419,9 @@ in {
hostname ${cfg.hostname} hostname ${cfg.hostname}
${if (cfg.tls.loader == "file") then '' ${if (cfg.tls.loader == "file") then ''
tls file ${concatStringsSep " " ( tls file ${lib.concatStringsSep " " (
map (x: x.certPath + " " + x.keyPath map (x: x.certPath + " " + x.keyPath
) cfg.tls.certificates)} ${optionalString (cfg.tls.extraConfig != "") '' ) cfg.tls.certificates)} ${lib.optionalString (cfg.tls.extraConfig != "") ''
{ ${cfg.tls.extraConfig} } { ${cfg.tls.extraConfig} }
''} ''}
'' else if (cfg.tls.loader == "acme") then '' '' else if (cfg.tls.loader == "acme") then ''
@ -441,7 +438,7 @@ in {
''; '';
}; };
users.users = optionalAttrs (cfg.user == name) { users.users = lib.optionalAttrs (cfg.user == name) {
${name} = { ${name} = {
isSystemUser = true; isSystemUser = true;
group = cfg.group; group = cfg.group;
@ -449,11 +446,11 @@ in {
}; };
}; };
users.groups = optionalAttrs (cfg.group == name) { users.groups = lib.optionalAttrs (cfg.group == name) {
${cfg.group} = { }; ${cfg.group} = { };
}; };
networking.firewall = mkIf cfg.openFirewall { networking.firewall = lib.mkIf cfg.openFirewall {
allowedTCPPorts = [ 25 143 587 ]; allowedTCPPorts = [ 25 143 587 ];
}; };

View file

@ -1,7 +1,4 @@
{ config, options, lib, ... }: { config, options, lib, ... }:
with lib;
{ {
###### interface ###### interface
@ -10,8 +7,8 @@ with lib;
services.mail = { services.mail = {
sendmailSetuidWrapper = mkOption { sendmailSetuidWrapper = lib.mkOption {
type = types.nullOr options.security.wrappers.type.nestedTypes.elemType; type = lib.types.nullOr options.security.wrappers.type.nestedTypes.elemType;
default = null; default = null;
internal = true; internal = true;
description = '' description = ''
@ -25,7 +22,7 @@ with lib;
###### implementation ###### implementation
config = mkIf (config.services.mail.sendmailSetuidWrapper != null) { config = lib.mkIf (config.services.mail.sendmailSetuidWrapper != null) {
security.wrappers.sendmail = config.services.mail.sendmailSetuidWrapper; security.wrappers.sendmail = config.services.mail.sendmailSetuidWrapper;

View file

@ -1,7 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.mailhog; cfg = config.services.mailhog;
@ -21,40 +18,40 @@ in
###### interface ###### interface
imports = [ imports = [
(mkRemovedOptionModule [ "services" "mailhog" "user" ] "") (lib.mkRemovedOptionModule [ "services" "mailhog" "user" ] "")
]; ];
options = { options = {
services.mailhog = { services.mailhog = {
enable = mkEnableOption "MailHog, web and API based SMTP testing"; enable = lib.mkEnableOption "MailHog, web and API based SMTP testing";
storage = mkOption { storage = lib.mkOption {
type = types.enum [ "maildir" "memory" ]; type = lib.types.enum [ "maildir" "memory" ];
default = "memory"; default = "memory";
description = "Store mails on disk or in memory."; description = "Store mails on disk or in memory.";
}; };
apiPort = mkOption { apiPort = lib.mkOption {
type = types.port; type = lib.types.port;
default = 8025; default = 8025;
description = "Port on which the API endpoint will listen."; description = "Port on which the API endpoint will listen.";
}; };
smtpPort = mkOption { smtpPort = lib.mkOption {
type = types.port; type = lib.types.port;
default = 1025; default = 1025;
description = "Port on which the SMTP endpoint will listen."; description = "Port on which the SMTP endpoint will listen.";
}; };
uiPort = mkOption { uiPort = lib.mkOption {
type = types.port; type = lib.types.port;
default = 8025; default = 8025;
description = "Port on which the HTTP UI will listen."; description = "Port on which the HTTP UI will listen.";
}; };
extraArgs = mkOption { extraArgs = lib.mkOption {
type = types.listOf types.str; type = lib.types.listOf lib.types.str;
default = []; default = [];
description = "List of additional arguments to pass to the MailHog process."; description = "List of additional arguments to pass to the MailHog process.";
}; };
@ -64,7 +61,7 @@ in
###### implementation ###### implementation
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
systemd.services.mailhog = { systemd.services.mailhog = {
description = "MailHog - Web and API based SMTP testing"; description = "MailHog - Web and API based SMTP testing";

View file

@ -1,7 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
concatMapLines = f: l: lib.concatStringsSep "\n" (map f l); concatMapLines = f: l: lib.concatStringsSep "\n" (map f l);
@ -53,38 +50,38 @@ in
services.mlmmj = { services.mlmmj = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = "Enable mlmmj"; description = "Enable mlmmj";
}; };
user = mkOption { user = lib.mkOption {
type = types.str; type = lib.types.str;
default = "mlmmj"; default = "mlmmj";
description = "mailinglist local user"; description = "mailinglist local user";
}; };
group = mkOption { group = lib.mkOption {
type = types.str; type = lib.types.str;
default = "mlmmj"; default = "mlmmj";
description = "mailinglist local group"; description = "mailinglist local group";
}; };
listDomain = mkOption { listDomain = lib.mkOption {
type = types.str; type = lib.types.str;
default = "localhost"; default = "localhost";
description = "Set the mailing list domain"; description = "Set the mailing list domain";
}; };
mailLists = mkOption { mailLists = lib.mkOption {
type = types.listOf types.str; type = lib.types.listOf lib.types.str;
default = []; default = [];
description = "The collection of hosted maillists"; description = "The collection of hosted maillists";
}; };
maintInterval = mkOption { maintInterval = lib.mkOption {
type = types.str; type = lib.types.str;
default = "20min"; default = "20min";
description = '' description = ''
Time interval between mlmmj-maintd runs, see Time interval between mlmmj-maintd runs, see
@ -98,7 +95,7 @@ in
###### implementation ###### implementation
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
users.users.${cfg.user} = { users.users.${cfg.user} = {
description = "mlmmj user"; description = "mlmmj user";

View file

@ -1,42 +1,39 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
{ {
options = { options = {
services.nullmailer = { services.nullmailer = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = "Whether to enable nullmailer daemon."; description = "Whether to enable nullmailer daemon.";
}; };
user = mkOption { user = lib.mkOption {
type = types.str; type = lib.types.str;
default = "nullmailer"; default = "nullmailer";
description = '' description = ''
User to use to run nullmailer-send. User to use to run nullmailer-send.
''; '';
}; };
group = mkOption { group = lib.mkOption {
type = types.str; type = lib.types.str;
default = "nullmailer"; default = "nullmailer";
description = '' description = ''
Group to use to run nullmailer-send. Group to use to run nullmailer-send.
''; '';
}; };
setSendmail = mkOption { setSendmail = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = true; default = true;
description = "Whether to set the system sendmail to nullmailer's."; description = "Whether to set the system sendmail to nullmailer's.";
}; };
remotesFile = mkOption { remotesFile = lib.mkOption {
type = types.nullOr types.str; type = lib.types.nullOr lib.types.str;
default = null; default = null;
description = '' description = ''
Path to the `remotes` control file. This file contains a Path to the `remotes` control file. This file contains a
@ -48,8 +45,8 @@ with lib;
}; };
config = { config = {
adminaddr = mkOption { adminaddr = lib.mkOption {
type = types.nullOr types.str; type = lib.types.nullOr lib.types.str;
default = null; default = null;
description = '' description = ''
If set, all recipients to users at either "localhost" (the literal string) If set, all recipients to users at either "localhost" (the literal string)
@ -61,16 +58,16 @@ with lib;
''; '';
}; };
allmailfrom = mkOption { allmailfrom = lib.mkOption {
type = types.nullOr types.str; type = lib.types.nullOr lib.types.str;
default = null; default = null;
description = '' description = ''
If set, content will override the envelope sender on all messages. If set, content will override the envelope sender on all messages.
''; '';
}; };
defaultdomain = mkOption { defaultdomain = lib.mkOption {
type = types.nullOr types.str; type = lib.types.nullOr lib.types.str;
default = null; default = null;
description = '' description = ''
The content of this attribute is appended to any host name that The content of this attribute is appended to any host name that
@ -80,8 +77,8 @@ with lib;
''; '';
}; };
defaulthost = mkOption { defaulthost = lib.mkOption {
type = types.nullOr types.str; type = lib.types.nullOr lib.types.str;
default = null; default = null;
description = '' description = ''
The content of this attribute is appended to any address that The content of this attribute is appended to any address that
@ -90,8 +87,8 @@ with lib;
''; '';
}; };
doublebounceto = mkOption { doublebounceto = lib.mkOption {
type = types.nullOr types.str; type = lib.types.nullOr lib.types.str;
default = null; default = null;
description = '' description = ''
If the original sender was empty (the original message was a If the original sender was empty (the original message was a
@ -100,8 +97,8 @@ with lib;
''; '';
}; };
helohost = mkOption { helohost = lib.mkOption {
type = types.nullOr types.str; type = lib.types.nullOr lib.types.str;
default = null; default = null;
description = '' description = ''
Sets the environment variable $HELOHOST which is used by the Sets the environment variable $HELOHOST which is used by the
@ -110,8 +107,8 @@ with lib;
''; '';
}; };
idhost = mkOption { idhost = lib.mkOption {
type = types.nullOr types.str; type = lib.types.nullOr lib.types.str;
default = null; default = null;
description = '' description = ''
The content of this attribute is used when building the message-id The content of this attribute is used when building the message-id
@ -119,8 +116,8 @@ with lib;
''; '';
}; };
maxpause = mkOption { maxpause = lib.mkOption {
type = with types; nullOr (oneOf [ str int ]); type = with lib.types; nullOr (oneOf [ str int ]);
default = null; default = null;
description = '' description = ''
The maximum time to pause between successive queue runs, in seconds. The maximum time to pause between successive queue runs, in seconds.
@ -128,8 +125,8 @@ with lib;
''; '';
}; };
me = mkOption { me = lib.mkOption {
type = types.nullOr types.str; type = lib.types.nullOr lib.types.str;
default = null; default = null;
description = '' description = ''
The fully-qualifiled host name of the computer running nullmailer. The fully-qualifiled host name of the computer running nullmailer.
@ -137,8 +134,8 @@ with lib;
''; '';
}; };
pausetime = mkOption { pausetime = lib.mkOption {
type = with types; nullOr (oneOf [ str int ]); type = with lib.types; nullOr (oneOf [ str int ]);
default = null; default = null;
description = '' description = ''
The minimum time to pause between successive queue runs when there The minimum time to pause between successive queue runs when there
@ -150,8 +147,8 @@ with lib;
''; '';
}; };
remotes = mkOption { remotes = lib.mkOption {
type = types.nullOr types.str; type = lib.types.nullOr lib.types.str;
default = null; default = null;
description = '' description = ''
A list of remote servers to which to send each message. Each line A list of remote servers to which to send each message. Each line
@ -167,8 +164,8 @@ with lib;
''; '';
}; };
sendtimeout = mkOption { sendtimeout = lib.mkOption {
type = with types; nullOr (oneOf [ str int ]); type = with lib.types; nullOr (oneOf [ str int ]);
default = null; default = null;
description = '' description = ''
The time to wait for a remote module listed above to complete sending The time to wait for a remote module listed above to complete sending
@ -183,7 +180,7 @@ with lib;
config = let config = let
cfg = config.services.nullmailer; cfg = config.services.nullmailer;
in mkIf cfg.enable { in lib.mkIf cfg.enable {
assertions = [ assertions = [
{ assertion = cfg.config.remotes == null || cfg.remotesFile == null; { assertion = cfg.config.remotes == null || cfg.remotesFile == null;
@ -194,10 +191,10 @@ with lib;
environment = { environment = {
systemPackages = [ pkgs.nullmailer ]; systemPackages = [ pkgs.nullmailer ];
etc = let etc = let
validAttrs = lib.mapAttrs (_: toString) (filterAttrs (_: value: value != null) cfg.config); validAttrs = lib.mapAttrs (_: toString) (lib.filterAttrs (_: value: value != null) cfg.config);
in in
(foldl' (as: name: as // { "nullmailer/${name}".text = validAttrs.${name}; }) {} (attrNames validAttrs)) (lib.foldl' (as: name: as // { "nullmailer/${name}".text = validAttrs.${name}; }) {} (lib.attrNames validAttrs))
// optionalAttrs (cfg.remotesFile != null) { "nullmailer/remotes".source = cfg.remotesFile; }; // lib.optionalAttrs (cfg.remotesFile != null) { "nullmailer/remotes".source = cfg.remotesFile; };
}; };
users = { users = {
@ -234,7 +231,7 @@ with lib;
}; };
}; };
services.mail.sendmailSetuidWrapper = mkIf cfg.setSendmail { services.mail.sendmailSetuidWrapper = lib.mkIf cfg.setSendmail {
program = "sendmail"; program = "sendmail";
source = "${pkgs.nullmailer}/bin/sendmail"; source = "${pkgs.nullmailer}/bin/sendmail";
owner = cfg.user; owner = cfg.user;

View file

@ -1,16 +1,13 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.offlineimap; cfg = config.services.offlineimap;
in { in {
options.services.offlineimap = { options.services.offlineimap = {
enable = mkEnableOption "OfflineIMAP, a software to dispose your mailbox(es) as a local Maildir(s)"; enable = lib.mkEnableOption "OfflineIMAP, a software to dispose your mailbox(es) as a local Maildir(s)";
install = mkOption { install = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Whether to install a user service for Offlineimap. Once Whether to install a user service for Offlineimap. Once
@ -22,28 +19,28 @@ in {
''; '';
}; };
package = mkPackageOption pkgs "offlineimap" { }; package = lib.mkPackageOption pkgs "offlineimap" { };
path = mkOption { path = lib.mkOption {
type = types.listOf types.path; type = lib.types.listOf lib.types.path;
default = []; default = [];
example = literalExpression "[ pkgs.pass pkgs.bash pkgs.notmuch ]"; example = lib.literalExpression "[ pkgs.pass pkgs.bash pkgs.notmuch ]";
description = "List of derivations to put in Offlineimap's path."; description = "List of derivations to put in Offlineimap's path.";
}; };
onCalendar = mkOption { onCalendar = lib.mkOption {
type = types.str; type = lib.types.str;
default = "*:0/3"; # every 3 minutes default = "*:0/3"; # every 3 minutes
description = "How often is offlineimap started. Default is '*:0/3' meaning every 3 minutes. See systemd.time(7) for more information about the format."; description = "How often is offlineimap started. Default is '*:0/3' meaning every 3 minutes. See systemd.time(7) for more information about the format.";
}; };
timeoutStartSec = mkOption { timeoutStartSec = lib.mkOption {
type = types.str; type = lib.types.str;
default = "120sec"; # Kill if still alive after 2 minutes default = "120sec"; # Kill if still alive after 2 minutes
description = "How long waiting for offlineimap before killing it. Default is '120sec' meaning every 2 minutes. See systemd.time(7) for more information about the format."; description = "How long waiting for offlineimap before killing it. Default is '120sec' meaning every 2 minutes. See systemd.time(7) for more information about the format.";
}; };
}; };
config = mkIf (cfg.enable || cfg.install) { config = lib.mkIf (cfg.enable || cfg.install) {
systemd.user.services.offlineimap = { systemd.user.services.offlineimap = {
description = "Offlineimap: a software to dispose your mailbox(es) as a local Maildir(s)"; description = "Offlineimap: a software to dispose your mailbox(es) as a local Maildir(s)";
serviceConfig = { serviceConfig = {
@ -62,6 +59,6 @@ in {
# start immediately after computer is started: # start immediately after computer is started:
Persistent = "true"; Persistent = "true";
}; };
} // optionalAttrs cfg.enable { wantedBy = [ "default.target" ]; }; } // lib.optionalAttrs cfg.enable { wantedBy = [ "default.target" ]; };
}; };
} }

View file

@ -1,7 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.opendkim; cfg = config.services.opendkim;
@ -15,11 +12,11 @@ let
"-d" cfg.domains "-d" cfg.domains
"-k" keyFile "-k" keyFile
"-s" cfg.selector "-s" cfg.selector
] ++ optionals (cfg.configFile != null) [ "-x" cfg.configFile ]; ] ++ lib.optionals (cfg.configFile != null) [ "-x" cfg.configFile ];
in { in {
imports = [ imports = [
(mkRenamedOptionModule [ "services" "opendkim" "keyFile" ] [ "services" "opendkim" "keyPath" ]) (lib.mkRenamedOptionModule [ "services" "opendkim" "keyFile" ] [ "services" "opendkim" "keyPath" ])
]; ];
###### interface ###### interface
@ -28,34 +25,34 @@ in {
services.opendkim = { services.opendkim = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = "Whether to enable the OpenDKIM sender authentication system."; description = "Whether to enable the OpenDKIM sender authentication system.";
}; };
socket = mkOption { socket = lib.mkOption {
type = types.str; type = lib.types.str;
default = defaultSock; default = defaultSock;
description = "Socket which is used for communication with OpenDKIM."; description = "Socket which is used for communication with OpenDKIM.";
}; };
user = mkOption { user = lib.mkOption {
type = types.str; type = lib.types.str;
default = "opendkim"; default = "opendkim";
description = "User for the daemon."; description = "User for the daemon.";
}; };
group = mkOption { group = lib.mkOption {
type = types.str; type = lib.types.str;
default = "opendkim"; default = "opendkim";
description = "Group for the daemon."; description = "Group for the daemon.";
}; };
domains = mkOption { domains = lib.mkOption {
type = types.str; type = lib.types.str;
default = "csl:${config.networking.hostName}"; default = "csl:${config.networking.hostName}";
defaultText = literalExpression ''"csl:''${config.networking.hostName}"''; defaultText = lib.literalExpression ''"csl:''${config.networking.hostName}"'';
example = "csl:example.com,mydomain.net"; example = "csl:example.com,mydomain.net";
description = '' description = ''
Local domains set (see `opendkim(8)` for more information on datasets). Local domains set (see `opendkim(8)` for more information on datasets).
@ -63,8 +60,8 @@ in {
''; '';
}; };
keyPath = mkOption { keyPath = lib.mkOption {
type = types.path; type = lib.types.path;
description = '' description = ''
The path that opendkim should put its generated private keys into. The path that opendkim should put its generated private keys into.
The DNS settings will be found in this directory with the name selector.txt. The DNS settings will be found in this directory with the name selector.txt.
@ -72,13 +69,13 @@ in {
default = "/var/lib/opendkim/keys"; default = "/var/lib/opendkim/keys";
}; };
selector = mkOption { selector = lib.mkOption {
type = types.str; type = lib.types.str;
description = "Selector to use when signing."; description = "Selector to use when signing.";
}; };
configFile = mkOption { configFile = lib.mkOption {
type = types.nullOr types.path; type = lib.types.nullOr lib.types.path;
default = null; default = null;
description = "Additional opendkim configuration."; description = "Additional opendkim configuration.";
}; };
@ -90,16 +87,16 @@ in {
###### implementation ###### implementation
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
users.users = optionalAttrs (cfg.user == "opendkim") { users.users = lib.optionalAttrs (cfg.user == "opendkim") {
opendkim = { opendkim = {
group = cfg.group; group = cfg.group;
uid = config.ids.uids.opendkim; uid = config.ids.uids.opendkim;
}; };
}; };
users.groups = optionalAttrs (cfg.group == "opendkim") { users.groups = lib.optionalAttrs (cfg.group == "opendkim") {
opendkim.gid = config.ids.gids.opendkim; opendkim.gid = config.ids.gids.opendkim;
}; };
@ -126,10 +123,10 @@ in {
''; '';
serviceConfig = { serviceConfig = {
ExecStart = "${pkgs.opendkim}/bin/opendkim ${escapeShellArgs args}"; ExecStart = "${pkgs.opendkim}/bin/opendkim ${lib.escapeShellArgs args}";
User = cfg.user; User = cfg.user;
Group = cfg.group; Group = cfg.group;
RuntimeDirectory = optional (cfg.socket == defaultSock) "opendkim"; RuntimeDirectory = lib.optional (cfg.socket == defaultSock) "opendkim";
StateDirectory = "opendkim"; StateDirectory = "opendkim";
StateDirectoryMode = "0700"; StateDirectoryMode = "0700";
ReadWritePaths = [ cfg.keyPath ]; ReadWritePaths = [ cfg.keyPath ];

View file

@ -1,12 +1,9 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.opensmtpd; cfg = config.services.opensmtpd;
conf = pkgs.writeText "smtpd.conf" cfg.serverConfiguration; conf = pkgs.writeText "smtpd.conf" cfg.serverConfiguration;
args = concatStringsSep " " cfg.extraServerArgs; args = lib.concatStringsSep " " cfg.extraServerArgs;
sendmail = pkgs.runCommand "opensmtpd-sendmail" { preferLocalBuild = true; } '' sendmail = pkgs.runCommand "opensmtpd-sendmail" { preferLocalBuild = true; } ''
mkdir -p $out/bin mkdir -p $out/bin
@ -18,29 +15,29 @@ in {
###### interface ###### interface
imports = [ imports = [
(mkRenamedOptionModule [ "services" "opensmtpd" "addSendmailToSystemPath" ] [ "services" "opensmtpd" "setSendmail" ]) (lib.mkRenamedOptionModule [ "services" "opensmtpd" "addSendmailToSystemPath" ] [ "services" "opensmtpd" "setSendmail" ])
]; ];
options = { options = {
services.opensmtpd = { services.opensmtpd = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = "Whether to enable the OpenSMTPD server."; description = "Whether to enable the OpenSMTPD server.";
}; };
package = mkPackageOption pkgs "opensmtpd" { }; package = lib.mkPackageOption pkgs "opensmtpd" { };
setSendmail = mkOption { setSendmail = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = true; default = true;
description = "Whether to set the system sendmail to OpenSMTPD's."; description = "Whether to set the system sendmail to OpenSMTPD's.";
}; };
extraServerArgs = mkOption { extraServerArgs = lib.mkOption {
type = types.listOf types.str; type = lib.types.listOf lib.types.str;
default = []; default = [];
example = [ "-v" "-P mta" ]; example = [ "-v" "-P mta" ];
description = '' description = ''
@ -49,8 +46,8 @@ in {
''; '';
}; };
serverConfiguration = mkOption { serverConfiguration = lib.mkOption {
type = types.lines; type = lib.types.lines;
example = '' example = ''
listen on lo listen on lo
accept for any deliver to lmtp localhost:24 accept for any deliver to lmtp localhost:24
@ -61,8 +58,8 @@ in {
''; '';
}; };
procPackages = mkOption { procPackages = lib.mkOption {
type = types.listOf types.package; type = lib.types.listOf lib.types.package;
default = []; default = [];
description = '' description = ''
Packages to search for filters, tables, queues, and schedulers. Packages to search for filters, tables, queues, and schedulers.
@ -78,7 +75,7 @@ in {
###### implementation ###### implementation
config = mkIf cfg.enable rec { config = lib.mkIf cfg.enable rec {
users.groups = { users.groups = {
smtpd.gid = config.ids.gids.smtpd; smtpd.gid = config.ids.gids.smtpd;
smtpq.gid = config.ids.gids.smtpq; smtpq.gid = config.ids.gids.smtpq;
@ -105,7 +102,7 @@ in {
source = "${cfg.package}/bin/smtpctl"; source = "${cfg.package}/bin/smtpctl";
}; };
services.mail.sendmailSetuidWrapper = mkIf cfg.setSendmail services.mail.sendmailSetuidWrapper = lib.mkIf cfg.setSendmail
(security.wrappers.smtpctl // { program = "sendmail"; }); (security.wrappers.smtpctl // { program = "sendmail"; });
systemd.tmpfiles.rules = [ systemd.tmpfiles.rules = [

View file

@ -1,7 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
{ {
###### interface ###### interface
@ -9,25 +6,25 @@ with lib;
options = { options = {
services.pfix-srsd = { services.pfix-srsd = {
enable = mkOption { enable = lib.mkOption {
default = false; default = false;
type = types.bool; type = lib.types.bool;
description = "Whether to run the postfix sender rewriting scheme daemon."; description = "Whether to run the postfix sender rewriting scheme daemon.";
}; };
domain = mkOption { domain = lib.mkOption {
description = "The domain for which to enable srs"; description = "The domain for which to enable srs";
type = types.str; type = lib.types.str;
example = "example.com"; example = "example.com";
}; };
secretsFile = mkOption { secretsFile = lib.mkOption {
description = '' description = ''
The secret data used to encode the SRS address. The secret data used to encode the SRS address.
to generate, use a command like: to generate, use a command like:
`for n in $(seq 5); do dd if=/dev/urandom count=1 bs=1024 status=none | sha256sum | sed 's/ -$//' | sed 's/^/ /'; done` `for n in $(seq 5); do dd if=/dev/urandom count=1 bs=1024 status=none | sha256sum | sed 's/ -$//' | sed 's/^/ /'; done`
''; '';
type = types.path; type = lib.types.path;
default = "/var/lib/pfix-srsd/secrets"; default = "/var/lib/pfix-srsd/secrets";
}; };
}; };
@ -35,7 +32,7 @@ with lib;
###### implementation ###### implementation
config = mkIf config.services.pfix-srsd.enable { config = lib.mkIf config.services.pfix-srsd.enable {
environment = { environment = {
systemPackages = [ pkgs.pfixtools ]; systemPackages = [ pkgs.pfixtools ];
}; };

View file

@ -1,7 +1,4 @@
{ lib, config, pkgs, ... }: { lib, config, pkgs, ... }:
with lib;
let let
cfg = config.services.postfixadmin; cfg = config.services.postfixadmin;
fpm = config.services.phpfpm.pools.postfixadmin; fpm = config.services.phpfpm.pools.postfixadmin;
@ -10,8 +7,8 @@ let
in in
{ {
options.services.postfixadmin = { options.services.postfixadmin = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Whether to enable postfixadmin. Whether to enable postfixadmin.
@ -22,14 +19,14 @@ in
''; '';
}; };
hostName = mkOption { hostName = lib.mkOption {
type = types.str; type = lib.types.str;
example = "postfixadmin.example.com"; example = "postfixadmin.example.com";
description = "Hostname to use for the nginx vhost"; description = "Hostname to use for the nginx vhost";
}; };
adminEmail = mkOption { adminEmail = lib.mkOption {
type = types.str; type = lib.types.str;
example = "postmaster@example.com"; example = "postmaster@example.com";
description = '' description = ''
Defines the Site Admin's email address. Defines the Site Admin's email address.
@ -38,8 +35,8 @@ in
''; '';
}; };
setupPasswordFile = mkOption { setupPasswordFile = lib.mkOption {
type = types.path; type = lib.types.path;
description = '' description = ''
Password file for the admin. Password file for the admin.
Generate with `php -r "echo password_hash('some password here', PASSWORD_DEFAULT);"` Generate with `php -r "echo password_hash('some password here', PASSWORD_DEFAULT);"`
@ -47,16 +44,16 @@ in
}; };
database = { database = {
username = mkOption { username = lib.mkOption {
type = types.str; type = lib.types.str;
default = "postfixadmin"; default = "postfixadmin";
description = '' description = ''
Username for the postgresql connection. Username for the postgresql connection.
If `database.host` is set to `localhost`, a unix user and group of the same name will be created as well. If `database.host` is set to `localhost`, a unix user and group of the same name will be created as well.
''; '';
}; };
host = mkOption { host = lib.mkOption {
type = types.str; type = lib.types.str;
default = "localhost"; default = "localhost";
description = '' description = ''
Host of the postgresql server. If this is not set to Host of the postgresql server. If this is not set to
@ -65,25 +62,25 @@ in
permissions. permissions.
''; '';
}; };
passwordFile = mkOption { passwordFile = lib.mkOption {
type = types.path; type = lib.types.path;
description = "Password file for the postgresql connection. Must be readable by user `nginx`."; description = "Password file for the postgresql connection. Must be readable by user `nginx`.";
}; };
dbname = mkOption { dbname = lib.mkOption {
type = types.str; type = lib.types.str;
default = "postfixadmin"; default = "postfixadmin";
description = "Name of the postgresql database"; description = "Name of the postgresql database";
}; };
}; };
extraConfig = mkOption { extraConfig = lib.mkOption {
type = types.lines; type = lib.types.lines;
default = ""; default = "";
description = "Extra configuration for the postfixadmin instance, see postfixadmin's config.inc.php for available options."; description = "Extra configuration for the postfixadmin instance, see postfixadmin's config.inc.php for available options.";
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
environment.etc."postfixadmin/config.local.php".text = '' environment.etc."postfixadmin/config.local.php".text = ''
<?php <?php
@ -91,7 +88,7 @@ in
$CONF['database_type'] = 'pgsql'; $CONF['database_type'] = 'pgsql';
$CONF['database_host'] = ${if localDB then "null" else "'${cfg.database.host}'"}; $CONF['database_host'] = ${if localDB then "null" else "'${cfg.database.host}'"};
${optionalString localDB "$CONF['database_user'] = '${cfg.database.username}';"} ${lib.optionalString localDB "$CONF['database_user'] = '${cfg.database.username}';"}
$CONF['database_password'] = ${if localDB then "'dummy'" else "file_get_contents('${cfg.database.passwordFile}')"}; $CONF['database_password'] = ${if localDB then "'dummy'" else "file_get_contents('${cfg.database.passwordFile}')"};
$CONF['database_name'] = '${cfg.database.dbname}'; $CONF['database_name'] = '${cfg.database.dbname}';
$CONF['configured'] = true; $CONF['configured'] = true;
@ -109,8 +106,8 @@ in
enable = true; enable = true;
virtualHosts = { virtualHosts = {
${cfg.hostName} = { ${cfg.hostName} = {
forceSSL = mkDefault true; forceSSL = lib.mkDefault true;
enableACME = mkDefault true; enableACME = lib.mkDefault true;
locations."/" = { locations."/" = {
root = "${pkgs.postfixadmin}/public"; root = "${pkgs.postfixadmin}/public";
index = "index.php"; index = "index.php";
@ -127,7 +124,7 @@ in
}; };
}; };
services.postgresql = mkIf localDB { services.postgresql = lib.mkIf localDB {
enable = true; enable = true;
ensureUsers = [ { ensureUsers = [ {
name = cfg.database.username; name = cfg.database.username;
@ -136,7 +133,7 @@ in
# The postgresql module doesn't currently support concepts like # The postgresql module doesn't currently support concepts like
# objects owners and extensions; for now we tack on what's needed # objects owners and extensions; for now we tack on what's needed
# here. # here.
systemd.services.postfixadmin-postgres = let pgsql = config.services.postgresql; in mkIf localDB { systemd.services.postfixadmin-postgres = let pgsql = config.services.postgresql; in lib.mkIf localDB {
after = [ "postgresql.service" ]; after = [ "postgresql.service" ];
bindsTo = [ "postgresql.service" ]; bindsTo = [ "postgresql.service" ];
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
@ -172,12 +169,12 @@ in
}; };
}; };
users.users.${user} = mkIf localDB { users.users.${user} = lib.mkIf localDB {
group = user; group = user;
isSystemUser = true; isSystemUser = true;
createHome = false; createHome = false;
}; };
users.groups.${user} = mkIf localDB {}; users.groups.${user} = lib.mkIf localDB {};
services.phpfpm.pools.postfixadmin = { services.phpfpm.pools.postfixadmin = {
user = user; user = user;
@ -186,7 +183,7 @@ in
error_log = 'stderr' error_log = 'stderr'
log_errors = on log_errors = on
''; '';
settings = mapAttrs (name: mkDefault) { settings = lib.mapAttrs (name: lib.mkDefault) {
"listen.owner" = "nginx"; "listen.owner" = "nginx";
"listen.group" = "nginx"; "listen.group" = "nginx";
"listen.mode" = "0660"; "listen.mode" = "0660";

View file

@ -1,7 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.postsrsd; cfg = config.services.postsrsd;
@ -14,67 +11,67 @@ in {
services.postsrsd = { services.postsrsd = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = "Whether to enable the postsrsd SRS server for Postfix."; description = "Whether to enable the postsrsd SRS server for Postfix.";
}; };
secretsFile = mkOption { secretsFile = lib.mkOption {
type = types.path; type = lib.types.path;
default = "/var/lib/postsrsd/postsrsd.secret"; default = "/var/lib/postsrsd/postsrsd.secret";
description = "Secret keys used for signing and verification"; description = "Secret keys used for signing and verification";
}; };
domain = mkOption { domain = lib.mkOption {
type = types.str; type = lib.types.str;
description = "Domain name for rewrite"; description = "Domain name for rewrite";
}; };
separator = mkOption { separator = lib.mkOption {
type = types.enum ["-" "=" "+"]; type = lib.types.enum ["-" "=" "+"];
default = "="; default = "=";
description = "First separator character in generated addresses"; description = "First separator character in generated addresses";
}; };
# bindAddress = mkOption { # uncomment once 1.5 is released # bindAddress = lib.mkOption { # uncomment once 1.5 is released
# type = types.str; # type = lib.types.str;
# default = "127.0.0.1"; # default = "127.0.0.1";
# description = "Socket listen address"; # description = "Socket listen address";
# }; # };
forwardPort = mkOption { forwardPort = lib.mkOption {
type = types.int; type = lib.types.int;
default = 10001; default = 10001;
description = "Port for the forward SRS lookup"; description = "Port for the forward SRS lookup";
}; };
reversePort = mkOption { reversePort = lib.mkOption {
type = types.int; type = lib.types.int;
default = 10002; default = 10002;
description = "Port for the reverse SRS lookup"; description = "Port for the reverse SRS lookup";
}; };
timeout = mkOption { timeout = lib.mkOption {
type = types.int; type = lib.types.int;
default = 1800; default = 1800;
description = "Timeout for idle client connections in seconds"; description = "Timeout for idle client connections in seconds";
}; };
excludeDomains = mkOption { excludeDomains = lib.mkOption {
type = types.listOf types.str; type = lib.types.listOf lib.types.str;
default = []; default = [];
description = "Origin domains to exclude from rewriting in addition to primary domain"; description = "Origin domains to exclude from rewriting in addition to primary domain";
}; };
user = mkOption { user = lib.mkOption {
type = types.str; type = lib.types.str;
default = "postsrsd"; default = "postsrsd";
description = "User for the daemon"; description = "User for the daemon";
}; };
group = mkOption { group = lib.mkOption {
type = types.str; type = lib.types.str;
default = "postsrsd"; default = "postsrsd";
description = "Group for the daemon"; description = "Group for the daemon";
}; };
@ -86,18 +83,18 @@ in {
###### implementation ###### implementation
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
services.postsrsd.domain = mkDefault config.networking.hostName; services.postsrsd.domain = lib.mkDefault config.networking.hostName;
users.users = optionalAttrs (cfg.user == "postsrsd") { users.users = lib.optionalAttrs (cfg.user == "postsrsd") {
postsrsd = { postsrsd = {
group = cfg.group; group = cfg.group;
uid = config.ids.uids.postsrsd; uid = config.ids.uids.postsrsd;
}; };
}; };
users.groups = optionalAttrs (cfg.group == "postsrsd") { users.groups = lib.optionalAttrs (cfg.group == "postsrsd") {
postsrsd.gid = config.ids.gids.postsrsd; postsrsd.gid = config.ids.gids.postsrsd;
}; };
@ -110,7 +107,7 @@ in {
path = [ pkgs.coreutils ]; path = [ pkgs.coreutils ];
serviceConfig = { serviceConfig = {
ExecStart = ''${pkgs.postsrsd}/sbin/postsrsd "-s${cfg.secretsFile}" "-d${cfg.domain}" -a${cfg.separator} -f${toString cfg.forwardPort} -r${toString cfg.reversePort} -t${toString cfg.timeout} "-X${concatStringsSep "," cfg.excludeDomains}"''; ExecStart = ''${pkgs.postsrsd}/sbin/postsrsd "-s${cfg.secretsFile}" "-d${cfg.domain}" -a${cfg.separator} -f${toString cfg.forwardPort} -r${toString cfg.reversePort} -t${toString cfg.timeout} "-X${lib.concatStringsSep "," cfg.excludeDomains}"'';
User = cfg.user; User = cfg.user;
Group = cfg.group; Group = cfg.group;
PermissionsStartOnly = true; PermissionsStartOnly = true;

View file

@ -1,7 +1,4 @@
{ lib, config, pkgs, ... }: { lib, config, pkgs, ... }:
with lib;
let let
cfg = config.services.roundcube; cfg = config.services.roundcube;
fpm = config.services.phpfpm.pools.roundcube; fpm = config.services.phpfpm.pools.roundcube;
@ -11,8 +8,8 @@ let
in in
{ {
options.services.roundcube = { options.services.roundcube = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Whether to enable roundcube. Whether to enable roundcube.
@ -23,27 +20,27 @@ in
''; '';
}; };
hostName = mkOption { hostName = lib.mkOption {
type = types.str; type = lib.types.str;
example = "webmail.example.com"; example = "webmail.example.com";
description = "Hostname to use for the nginx vhost"; description = "Hostname to use for the nginx vhost";
}; };
package = mkPackageOption pkgs "roundcube" { package = lib.mkPackageOption pkgs "roundcube" {
example = "roundcube.withPlugins (plugins: [ plugins.persistent_login ])"; example = "roundcube.withPlugins (plugins: [ plugins.persistent_login ])";
}; };
database = { database = {
username = mkOption { username = lib.mkOption {
type = types.str; type = lib.types.str;
default = "roundcube"; default = "roundcube";
description = '' description = ''
Username for the postgresql connection. Username for the postgresql connection.
If `database.host` is set to `localhost`, a unix user and group of the same name will be created as well. If `database.host` is set to `localhost`, a unix user and group of the same name will be created as well.
''; '';
}; };
host = mkOption { host = lib.mkOption {
type = types.str; type = lib.types.str;
default = "localhost"; default = "localhost";
description = '' description = ''
Host of the postgresql server. If this is not set to Host of the postgresql server. If this is not set to
@ -52,13 +49,13 @@ in
permissions. permissions.
''; '';
}; };
password = mkOption { password = lib.mkOption {
type = types.str; type = lib.types.str;
description = "Password for the postgresql connection. Do not use: the password will be stored world readable in the store; use `passwordFile` instead."; description = "Password for the postgresql connection. Do not use: the password will be stored world readable in the store; use `passwordFile` instead.";
default = ""; default = "";
}; };
passwordFile = mkOption { passwordFile = lib.mkOption {
type = types.str; type = lib.types.str;
description = '' description = ''
Password file for the postgresql connection. Password file for the postgresql connection.
Must be formatted according to PostgreSQL .pgpass standard (see https://www.postgresql.org/docs/current/libpq-pgpass.html) Must be formatted according to PostgreSQL .pgpass standard (see https://www.postgresql.org/docs/current/libpq-pgpass.html)
@ -66,32 +63,32 @@ in
Ignored if `database.host` is set to `localhost`, as peer authentication will be used. Ignored if `database.host` is set to `localhost`, as peer authentication will be used.
''; '';
}; };
dbname = mkOption { dbname = lib.mkOption {
type = types.str; type = lib.types.str;
default = "roundcube"; default = "roundcube";
description = "Name of the postgresql database"; description = "Name of the postgresql database";
}; };
}; };
plugins = mkOption { plugins = lib.mkOption {
type = types.listOf types.str; type = lib.types.listOf lib.types.str;
default = []; default = [];
description = '' description = ''
List of roundcube plugins to enable. Currently, only those directly shipped with Roundcube are supported. List of roundcube plugins to enable. Currently, only those directly shipped with Roundcube are supported.
''; '';
}; };
dicts = mkOption { dicts = lib.mkOption {
type = types.listOf types.package; type = lib.types.listOf lib.types.package;
default = []; default = [];
example = literalExpression "with pkgs.aspellDicts; [ en fr de ]"; example = lib.literalExpression "with pkgs.aspellDicts; [ en fr de ]";
description = '' description = ''
List of aspell dictionaries for spell checking. If empty, spell checking is disabled. List of aspell dictionaries for spell checking. If empty, spell checking is disabled.
''; '';
}; };
maxAttachmentSize = mkOption { maxAttachmentSize = lib.mkOption {
type = types.int; type = lib.types.int;
default = 18; default = 18;
apply = configuredMaxAttachmentSize: "${toString (configuredMaxAttachmentSize * 1.37)}M"; apply = configuredMaxAttachmentSize: "${toString (configuredMaxAttachmentSize * 1.37)}M";
description = '' description = ''
@ -112,16 +109,16 @@ in
description = "Configure nginx as a reverse proxy for roundcube."; description = "Configure nginx as a reverse proxy for roundcube.";
}; };
extraConfig = mkOption { extraConfig = lib.mkOption {
type = types.lines; type = lib.types.lines;
default = ""; default = "";
description = "Extra configuration for roundcube webmail instance"; description = "Extra configuration for roundcube webmail instance";
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
# backward compatibility: if password is set but not passwordFile, make one. # backward compatibility: if password is set but not passwordFile, make one.
services.roundcube.database.passwordFile = mkIf (!localDB && cfg.database.password != "") (mkDefault ("${pkgs.writeText "roundcube-password" cfg.database.password}")); services.roundcube.database.passwordFile = lib.mkIf (!localDB && cfg.database.password != "") (lib.mkDefault ("${pkgs.writeText "roundcube-password" cfg.database.password}"));
warnings = lib.optional (!localDB && cfg.database.password != "") "services.roundcube.database.password is deprecated and insecure; use services.roundcube.database.passwordFile instead"; warnings = lib.optional (!localDB && cfg.database.password != "") "services.roundcube.database.password is deprecated and insecure; use services.roundcube.database.passwordFile instead";
environment.etc."roundcube/config.inc.php".text = '' environment.etc."roundcube/config.inc.php".text = ''
@ -139,7 +136,7 @@ in
$config['db_dsnw'] = 'pgsql://${cfg.database.username}${lib.optionalString (!localDB) ":' . $password . '"}@${if localDB then "unix(/run/postgresql)" else cfg.database.host}/${cfg.database.dbname}'; $config['db_dsnw'] = 'pgsql://${cfg.database.username}${lib.optionalString (!localDB) ":' . $password . '"}@${if localDB then "unix(/run/postgresql)" else cfg.database.host}/${cfg.database.dbname}';
$config['log_driver'] = 'syslog'; $config['log_driver'] = 'syslog';
$config['max_message_size'] = '${cfg.maxAttachmentSize}'; $config['max_message_size'] = '${cfg.maxAttachmentSize}';
$config['plugins'] = [${concatMapStringsSep "," (p: "'${p}'") cfg.plugins}]; $config['plugins'] = [${lib.concatMapStringsSep "," (p: "'${p}'") cfg.plugins}];
$config['des_key'] = file_get_contents('/var/lib/roundcube/des_key'); $config['des_key'] = file_get_contents('/var/lib/roundcube/des_key');
$config['mime_types'] = '${pkgs.nginx}/conf/mime.types'; $config['mime_types'] = '${pkgs.nginx}/conf/mime.types';
# Roundcube uses PHP-FPM which has `PrivateTmp = true;` # Roundcube uses PHP-FPM which has `PrivateTmp = true;`
@ -156,8 +153,8 @@ in
enable = true; enable = true;
virtualHosts = { virtualHosts = {
${cfg.hostName} = { ${cfg.hostName} = {
forceSSL = mkDefault true; forceSSL = lib.mkDefault true;
enableACME = mkDefault true; enableACME = lib.mkDefault true;
root = cfg.package; root = cfg.package;
locations."/" = { locations."/" = {
index = "index.php"; index = "index.php";
@ -201,7 +198,7 @@ in
} }
]; ];
services.postgresql = mkIf localDB { services.postgresql = lib.mkIf localDB {
enable = true; enable = true;
ensureDatabases = [ cfg.database.dbname ]; ensureDatabases = [ cfg.database.dbname ];
ensureUsers = [ { ensureUsers = [ {
@ -210,12 +207,12 @@ in
} ]; } ];
}; };
users.users.${user} = mkIf localDB { users.users.${user} = lib.mkIf localDB {
group = user; group = user;
isSystemUser = true; isSystemUser = true;
createHome = false; createHome = false;
}; };
users.groups.${user} = mkIf localDB {}; users.groups.${user} = lib.mkIf localDB {};
services.phpfpm.pools.roundcube = { services.phpfpm.pools.roundcube = {
user = if localDB then user else "nginx"; user = if localDB then user else "nginx";
@ -225,7 +222,7 @@ in
post_max_size = ${cfg.maxAttachmentSize} post_max_size = ${cfg.maxAttachmentSize}
upload_max_filesize = ${cfg.maxAttachmentSize} upload_max_filesize = ${cfg.maxAttachmentSize}
''; '';
settings = mapAttrs (name: mkDefault) { settings = lib.mapAttrs (name: lib.mkDefault) {
"listen.owner" = "nginx"; "listen.owner" = "nginx";
"listen.group" = "nginx"; "listen.group" = "nginx";
"listen.mode" = "0660"; "listen.mode" = "0660";
@ -247,8 +244,8 @@ in
config.environment.etc."roundcube/config.inc.php".source config.environment.etc."roundcube/config.inc.php".source
]; ];
systemd.services.roundcube-setup = mkMerge [ systemd.services.roundcube-setup = lib.mkMerge [
(mkIf (cfg.database.host == "localhost") { (lib.mkIf (cfg.database.host == "localhost") {
requires = [ "postgresql.service" ]; requires = [ "postgresql.service" ];
after = [ "postgresql.service" ]; after = [ "postgresql.service" ];
}) })

View file

@ -1,7 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.spamassassin; cfg = config.services.spamassassin;
spamassassin-local-cf = pkgs.writeText "local.cf" cfg.config; spamassassin-local-cf = pkgs.writeText "local.cf" cfg.config;
@ -12,16 +9,16 @@ in
options = { options = {
services.spamassassin = { services.spamassassin = {
enable = mkEnableOption "the SpamAssassin daemon"; enable = lib.mkEnableOption "the SpamAssassin daemon";
debug = mkOption { debug = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = "Whether to run the SpamAssassin daemon in debug mode"; description = "Whether to run the SpamAssassin daemon in debug mode";
}; };
config = mkOption { config = lib.mkOption {
type = types.lines; type = lib.types.lines;
description = '' description = ''
The SpamAssassin local.cf config The SpamAssassin local.cf config
@ -55,8 +52,8 @@ in
default = ""; default = "";
}; };
initPreConf = mkOption { initPreConf = lib.mkOption {
type = with types; either str path; type = with lib.types; either str path;
description = "The SpamAssassin init.pre config."; description = "The SpamAssassin init.pre config.";
apply = val: if builtins.isPath val then val else pkgs.writeText "init.pre" val; apply = val: if builtins.isPath val then val else pkgs.writeText "init.pre" val;
default = default =
@ -111,7 +108,7 @@ in
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
environment.etc."mail/spamassassin/init.pre".source = cfg.initPreConf; environment.etc."mail/spamassassin/init.pre".source = cfg.initPreConf;
environment.etc."mail/spamassassin/local.cf".source = spamassassin-local-cf; environment.etc."mail/spamassassin/local.cf".source = spamassassin-local-cf;
@ -185,7 +182,7 @@ in
serviceConfig = { serviceConfig = {
User = "spamd"; User = "spamd";
Group = "spamd"; Group = "spamd";
ExecStart = "+${pkgs.spamassassin}/bin/spamd ${optionalString cfg.debug "-D"} --username=spamd --groupname=spamd --virtual-config-dir=%S/spamassassin/user-%u --allow-tell --pidfile=/run/spamd.pid"; ExecStart = "+${pkgs.spamassassin}/bin/spamd ${lib.optionalString cfg.debug "-D"} --username=spamd --groupname=spamd --virtual-config-dir=%S/spamassassin/user-%u --allow-tell --pidfile=/run/spamd.pid";
ExecReload = "+${pkgs.coreutils}/bin/kill -HUP $MAINPID"; ExecReload = "+${pkgs.coreutils}/bin/kill -HUP $MAINPID";
StateDirectory = "spamassassin"; StateDirectory = "spamassassin";
}; };

View file

@ -1,29 +1,26 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.stalwart-mail; cfg = config.services.stalwart-mail;
configFormat = pkgs.formats.toml { }; configFormat = pkgs.formats.toml { };
configFile = configFormat.generate "stalwart-mail.toml" cfg.settings; configFile = configFormat.generate "stalwart-mail.toml" cfg.settings;
dataDir = "/var/lib/stalwart-mail"; dataDir = "/var/lib/stalwart-mail";
useLegacyStorage = versionOlder config.system.stateVersion "24.11"; useLegacyStorage = lib.versionOlder config.system.stateVersion "24.11";
parsePorts = listeners: let parsePorts = listeners: let
parseAddresses = listeners: lib.flatten(lib.mapAttrsToList (name: value: value.bind) listeners); parseAddresses = listeners: lib.flatten(lib.mapAttrsToList (name: value: value.bind) listeners);
splitAddress = addr: strings.splitString ":" addr; splitAddress = addr: lib.splitString ":" addr;
extractPort = addr: strings.toInt(builtins.foldl' (a: b: b) "" (splitAddress addr)); extractPort = addr: lib.toInt(builtins.foldl' (a: b: b) "" (splitAddress addr));
in in
builtins.map(address: extractPort address) (parseAddresses listeners); builtins.map(address: extractPort address) (parseAddresses listeners);
in { in {
options.services.stalwart-mail = { options.services.stalwart-mail = {
enable = mkEnableOption "the Stalwart all-in-one email server"; enable = lib.mkEnableOption "the Stalwart all-in-one email server";
package = mkPackageOption pkgs "stalwart-mail" { }; package = lib.mkPackageOption pkgs "stalwart-mail" { };
openFirewall = mkOption { openFirewall = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Whether to open TCP firewall ports, which are specified in Whether to open TCP firewall ports, which are specified in
@ -31,7 +28,7 @@ in {
''; '';
}; };
settings = mkOption { settings = lib.mkOption {
inherit (configFormat) type; inherit (configFormat) type;
default = { }; default = { };
description = '' description = ''
@ -43,36 +40,36 @@ in {
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
# Default config: all local # Default config: all local
services.stalwart-mail.settings = { services.stalwart-mail.settings = {
tracer.stdout = { tracer.stdout = {
type = mkDefault "stdout"; type = lib.mkDefault "stdout";
level = mkDefault "info"; level = lib.mkDefault "info";
ansi = mkDefault false; # no colour markers to journald ansi = lib.mkDefault false; # no colour markers to journald
enable = mkDefault true; enable = lib.mkDefault true;
}; };
store = if useLegacyStorage then { store = if useLegacyStorage then {
# structured data in SQLite, blobs on filesystem # structured data in SQLite, blobs on filesystem
db.type = mkDefault "sqlite"; db.type = lib.mkDefault "sqlite";
db.path = mkDefault "${dataDir}/data/index.sqlite3"; db.path = lib.mkDefault "${dataDir}/data/index.sqlite3";
fs.type = mkDefault "fs"; fs.type = lib.mkDefault "fs";
fs.path = mkDefault "${dataDir}/data/blobs"; fs.path = lib.mkDefault "${dataDir}/data/blobs";
} else { } else {
# everything in RocksDB # everything in RocksDB
db.type = mkDefault "rocksdb"; db.type = lib.mkDefault "rocksdb";
db.path = mkDefault "${dataDir}/db"; db.path = lib.mkDefault "${dataDir}/db";
db.compression = mkDefault "lz4"; db.compression = lib.mkDefault "lz4";
}; };
storage.data = mkDefault "db"; storage.data = lib.mkDefault "db";
storage.fts = mkDefault "db"; storage.fts = lib.mkDefault "db";
storage.lookup = mkDefault "db"; storage.lookup = lib.mkDefault "db";
storage.blob = mkDefault (if useLegacyStorage then "fs" else "db"); storage.blob = lib.mkDefault (if useLegacyStorage then "fs" else "db");
directory.internal.type = mkDefault "internal"; directory.internal.type = lib.mkDefault "internal";
directory.internal.store = mkDefault "db"; directory.internal.store = lib.mkDefault "db";
storage.directory = mkDefault "internal"; storage.directory = lib.mkDefault "internal";
resolver.type = mkDefault "system"; resolver.type = lib.mkDefault "system";
resolver.public-suffix = lib.mkDefault [ resolver.public-suffix = lib.mkDefault [
"file://${pkgs.publicsuffix-list}/share/publicsuffix/public_suffix_list.dat" "file://${pkgs.publicsuffix-list}/share/publicsuffix/public_suffix_list.dat"
]; ];
@ -155,13 +152,13 @@ in {
# Make admin commands available in the shell # Make admin commands available in the shell
environment.systemPackages = [ cfg.package ]; environment.systemPackages = [ cfg.package ];
networking.firewall = mkIf (cfg.openFirewall networking.firewall = lib.mkIf (cfg.openFirewall
&& (builtins.hasAttr "listener" cfg.settings.server)) { && (builtins.hasAttr "listener" cfg.settings.server)) {
allowedTCPPorts = parsePorts cfg.settings.server.listener; allowedTCPPorts = parsePorts cfg.settings.server.listener;
}; };
}; };
meta = { meta = {
maintainers = with maintainers; [ happysalada pacien onny ]; maintainers = with lib.maintainers; [ happysalada pacien onny ];
}; };
} }

View file

@ -1,6 +1,4 @@
{ config, pkgs, lib, ... }: { config, pkgs, lib, ... }:
with lib;
let let
cfg = config.services.zeyple; cfg = config.services.zeyple;
ini = pkgs.formats.ini { }; ini = pkgs.formats.ini { };
@ -16,10 +14,10 @@ let
''; '';
in { in {
options.services.zeyple = { options.services.zeyple = {
enable = mkEnableOption "Zeyple, an utility program to automatically encrypt outgoing emails with GPG"; enable = lib.mkEnableOption "Zeyple, an utility program to automatically encrypt outgoing emails with GPG";
user = mkOption { user = lib.mkOption {
type = types.str; type = lib.types.str;
default = "zeyple"; default = "zeyple";
description = '' description = ''
User to run Zeyple as. User to run Zeyple as.
@ -32,8 +30,8 @@ in {
''; '';
}; };
group = mkOption { group = lib.mkOption {
type = types.str; type = lib.types.str;
default = "zeyple"; default = "zeyple";
description = '' description = ''
Group to use to run Zeyple. Group to use to run Zeyple.
@ -46,7 +44,7 @@ in {
''; '';
}; };
settings = mkOption { settings = lib.mkOption {
type = ini.type; type = ini.type;
default = { }; default = { };
description = '' description = ''
@ -56,21 +54,21 @@ in {
''; '';
}; };
keys = mkOption { keys = lib.mkOption {
type = with types; listOf path; type = with lib.types; listOf path;
description = "List of public key files that will be imported by gpg."; description = "List of public key files that will be imported by gpg.";
}; };
rotateLogs = mkOption { rotateLogs = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = true; default = true;
description = "Whether to enable rotation of log files."; description = "Whether to enable rotation of log files.";
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
users.groups = optionalAttrs (cfg.group == "zeyple") { "${cfg.group}" = { }; }; users.groups = lib.optionalAttrs (cfg.group == "zeyple") { "${cfg.group}" = { }; };
users.users = optionalAttrs (cfg.user == "zeyple") { users.users = lib.optionalAttrs (cfg.user == "zeyple") {
"${cfg.user}" = { "${cfg.user}" = {
isSystemUser = true; isSystemUser = true;
group = cfg.group; group = cfg.group;
@ -78,14 +76,14 @@ in {
}; };
services.zeyple.settings = { services.zeyple.settings = {
zeyple = mapAttrs (name: mkDefault) { zeyple = lib.mapAttrs (name: lib.mkDefault) {
log_file = "/var/log/zeyple/zeyple.log"; log_file = "/var/log/zeyple/zeyple.log";
force_encrypt = true; force_encrypt = true;
}; };
gpg = mapAttrs (name: mkDefault) { home = "${gpgHome}"; }; gpg = lib.mapAttrs (name: lib.mkDefault) { home = "${gpgHome}"; };
relay = mapAttrs (name: mkDefault) { relay = lib.mapAttrs (name: lib.mkDefault) {
host = "localhost"; host = "localhost";
port = 10026; port = 10026;
}; };
@ -98,7 +96,7 @@ in {
mode = "0600"; mode = "0600";
}; };
services.logrotate = mkIf cfg.rotateLogs { services.logrotate = lib.mkIf cfg.rotateLogs {
enable = true; enable = true;
settings.zeyple = { settings.zeyple = {
files = cfg.settings.zeyple.log_file; files = cfg.settings.zeyple.log_file;

View file

@ -1,7 +1,4 @@
{ config, options, pkgs, lib, ... }: { config, options, pkgs, lib, ... }:
with lib;
let let
dataDir = "/var/lib/matrix-appservice-discord"; dataDir = "/var/lib/matrix-appservice-discord";
registrationFile = "${dataDir}/discord-registration.yaml"; registrationFile = "${dataDir}/discord-registration.yaml";
@ -13,14 +10,14 @@ let
in { in {
options = { options = {
services.matrix-appservice-discord = { services.matrix-appservice-discord = {
enable = mkEnableOption "a bridge between Matrix and Discord"; enable = lib.mkEnableOption "a bridge between Matrix and Discord";
package = mkPackageOption pkgs "matrix-appservice-discord" { }; package = lib.mkPackageOption pkgs "matrix-appservice-discord" { };
settings = mkOption rec { settings = lib.mkOption rec {
# TODO: switch to types.config.json as prescribed by RFC42 once it's implemented # TODO: switch to lib.types.config.json as prescribed by RFC42 once it's implemented
type = types.attrs; type = lib.types.attrs;
apply = recursiveUpdate default; apply = lib.recursiveUpdate default;
default = { default = {
database = { database = {
filename = "${dataDir}/discord.db"; filename = "${dataDir}/discord.db";
@ -33,7 +30,7 @@ in {
botToken = ""; botToken = "";
}; };
}; };
example = literalExpression '' example = lib.literalExpression ''
{ {
bridge = { bridge = {
domain = "public-domain.tld"; domain = "public-domain.tld";
@ -55,8 +52,8 @@ in {
''; '';
}; };
environmentFile = mkOption { environmentFile = lib.mkOption {
type = types.nullOr types.path; type = lib.types.nullOr lib.types.path;
default = null; default = null;
description = '' description = ''
File containing environment variables to be passed to the matrix-appservice-discord service, File containing environment variables to be passed to the matrix-appservice-discord service,
@ -66,36 +63,36 @@ in {
''; '';
}; };
url = mkOption { url = lib.mkOption {
type = types.str; type = lib.types.str;
default = "http://localhost:${toString cfg.port}"; default = "http://localhost:${toString cfg.port}";
defaultText = literalExpression ''"http://localhost:''${toString config.${opt.port}}"''; defaultText = lib.literalExpression ''"http://localhost:''${toString config.${opt.port}}"'';
description = '' description = ''
The URL where the application service is listening for HS requests. The URL where the application service is listening for HS requests.
''; '';
}; };
port = mkOption { port = lib.mkOption {
type = types.port; type = lib.types.port;
default = 9005; # from https://github.com/Half-Shot/matrix-appservice-discord/blob/master/package.json#L11 default = 9005; # from https://github.com/Half-Shot/matrix-appservice-discord/blob/master/package.json#L11
description = '' description = ''
Port number on which the bridge should listen for internal communication with the Matrix homeserver. Port number on which the bridge should listen for internal communication with the Matrix homeserver.
''; '';
}; };
localpart = mkOption { localpart = lib.mkOption {
type = with types; nullOr str; type = with lib.types; nullOr str;
default = null; default = null;
description = '' description = ''
The user_id localpart to assign to the AS. The user_id localpart to assign to the AS.
''; '';
}; };
serviceDependencies = mkOption { serviceDependencies = lib.mkOption {
type = with types; listOf str; type = with lib.types; listOf str;
default = optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit; default = lib.optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit;
defaultText = literalExpression '' defaultText = lib.literalExpression ''
optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit lib.optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit
''; '';
description = '' description = ''
List of Systemd services to require and wait for when starting the application service, List of Systemd services to require and wait for when starting the application service,
@ -105,7 +102,7 @@ in {
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
systemd.services.matrix-appservice-discord = { systemd.services.matrix-appservice-discord = {
description = "A bridge between Matrix and Discord."; description = "A bridge between Matrix and Discord.";
@ -117,8 +114,8 @@ in {
if [ ! -f '${registrationFile}' ]; then if [ ! -f '${registrationFile}' ]; then
${cfg.package}/bin/matrix-appservice-discord \ ${cfg.package}/bin/matrix-appservice-discord \
--generate-registration \ --generate-registration \
--url=${escapeShellArg cfg.url} \ --url=${lib.escapeShellArg cfg.url} \
${optionalString (cfg.localpart != null) "--localpart=${escapeShellArg cfg.localpart}"} \ ${lib.optionalString (cfg.localpart != null) "--localpart=${lib.escapeShellArg cfg.localpart}"} \
--config='${settingsFile}' \ --config='${settingsFile}' \
--file='${registrationFile}' --file='${registrationFile}'
fi fi
@ -151,5 +148,5 @@ in {
}; };
}; };
meta.maintainers = with maintainers; [ pacien ]; meta.maintainers = with lib.maintainers; [ pacien ];
} }

View file

@ -1,7 +1,4 @@
{ config, pkgs, lib, ... }: { config, pkgs, lib, ... }:
with lib;
let let
cfg = config.services.matrix-appservice-irc; cfg = config.services.matrix-appservice-irc;
@ -25,29 +22,29 @@ let
''; '';
registrationFile = "/var/lib/matrix-appservice-irc/registration.yml"; registrationFile = "/var/lib/matrix-appservice-irc/registration.yml";
in { in {
options.services.matrix-appservice-irc = with types; { options.services.matrix-appservice-irc = with lib.types; {
enable = mkEnableOption "the Matrix/IRC bridge"; enable = lib.mkEnableOption "the Matrix/IRC bridge";
port = mkOption { port = lib.mkOption {
type = port; type = port;
description = "The port to listen on"; description = "The port to listen on";
default = 8009; default = 8009;
}; };
needBindingCap = mkOption { needBindingCap = lib.mkOption {
type = bool; type = bool;
description = "Whether the daemon needs to bind to ports below 1024 (e.g. for the ident service)"; description = "Whether the daemon needs to bind to ports below 1024 (e.g. for the ident service)";
default = false; default = false;
}; };
passwordEncryptionKeyLength = mkOption { passwordEncryptionKeyLength = lib.mkOption {
type = ints.unsigned; type = ints.unsigned;
description = "Length of the key to encrypt IRC passwords with"; description = "Length of the key to encrypt IRC passwords with";
default = 4096; default = 4096;
example = 8192; example = 8192;
}; };
registrationUrl = mkOption { registrationUrl = lib.mkOption {
type = str; type = str;
description = '' description = ''
The URL where the application service is listening for homeserver requests, The URL where the application service is listening for homeserver requests,
@ -56,13 +53,13 @@ in {
example = "http://localhost:8009"; example = "http://localhost:8009";
}; };
localpart = mkOption { localpart = lib.mkOption {
type = str; type = str;
description = "The user_id localpart to assign to the appservice"; description = "The user_id localpart to assign to the appservice";
default = "appservice-irc"; default = "appservice-irc";
}; };
settings = mkOption { settings = lib.mkOption {
description = '' description = ''
Configuration for the appservice, see Configuration for the appservice, see
<https://github.com/matrix-org/matrix-appservice-irc/blob/${pkgs.matrix-appservice-irc.version}/config.sample.yaml> <https://github.com/matrix-org/matrix-appservice-irc/blob/${pkgs.matrix-appservice-irc.version}/config.sample.yaml>
@ -73,19 +70,19 @@ in {
freeformType = jsonType; freeformType = jsonType;
options = { options = {
homeserver = mkOption { homeserver = lib.mkOption {
description = "Homeserver configuration"; description = "Homeserver configuration";
default = {}; default = {};
type = submodule { type = submodule {
freeformType = jsonType; freeformType = jsonType;
options = { options = {
url = mkOption { url = lib.mkOption {
type = str; type = str;
description = "The URL to the home server for client-server API calls"; description = "The URL to the home server for client-server API calls";
}; };
domain = mkOption { domain = lib.mkOption {
type = str; type = str;
description = '' description = ''
The 'domain' part for user IDs on this home server. Usually The 'domain' part for user IDs on this home server. Usually
@ -96,21 +93,21 @@ in {
}; };
}; };
database = mkOption { database = lib.mkOption {
default = {}; default = {};
description = "Configuration for the database"; description = "Configuration for the database";
type = submodule { type = submodule {
freeformType = jsonType; freeformType = jsonType;
options = { options = {
engine = mkOption { engine = lib.mkOption {
type = str; type = str;
description = "Which database engine to use"; description = "Which database engine to use";
default = "nedb"; default = "nedb";
example = "postgres"; example = "postgres";
}; };
connectionString = mkOption { connectionString = lib.mkOption {
type = str; type = str;
description = "The database connection string"; description = "The database connection string";
default = "nedb://var/lib/matrix-appservice-irc/data"; default = "nedb://var/lib/matrix-appservice-irc/data";
@ -120,14 +117,14 @@ in {
}; };
}; };
ircService = mkOption { ircService = lib.mkOption {
default = {}; default = {};
description = "IRC bridge configuration"; description = "IRC bridge configuration";
type = submodule { type = submodule {
freeformType = jsonType; freeformType = jsonType;
options = { options = {
passwordEncryptionKeyPath = mkOption { passwordEncryptionKeyPath = lib.mkOption {
type = str; type = str;
description = '' description = ''
Location of the key with which IRC passwords are encrypted Location of the key with which IRC passwords are encrypted
@ -136,7 +133,7 @@ in {
default = "/var/lib/matrix-appservice-irc/passkey.pem"; default = "/var/lib/matrix-appservice-irc/passkey.pem";
}; };
servers = mkOption { servers = lib.mkOption {
type = submodule { freeformType = jsonType; }; type = submodule { freeformType = jsonType; };
description = "IRC servers to connect to"; description = "IRC servers to connect to";
}; };
@ -147,7 +144,7 @@ in {
}; };
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
systemd.services.matrix-appservice-irc = { systemd.services.matrix-appservice-irc = {
description = "Matrix-IRC bridge"; description = "Matrix-IRC bridge";
before = [ "matrix-synapse.service" ]; # So the registration can be used by Synapse before = [ "matrix-synapse.service" ]; # So the registration can be used by Synapse
@ -206,7 +203,7 @@ in {
User = "matrix-appservice-irc"; User = "matrix-appservice-irc";
Group = "matrix-appservice-irc"; Group = "matrix-appservice-irc";
CapabilityBoundingSet = [ "CAP_CHOWN" ] ++ optional (cfg.needBindingCap) "CAP_NET_BIND_SERVICE"; CapabilityBoundingSet = [ "CAP_CHOWN" ] ++ lib.optional (cfg.needBindingCap) "CAP_NET_BIND_SERVICE";
AmbientCapabilities = CapabilityBoundingSet; AmbientCapabilities = CapabilityBoundingSet;
NoNewPrivileges = true; NoNewPrivileges = true;

View file

@ -1,7 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.matrix-conduit; cfg = config.services.matrix-conduit;
@ -9,67 +6,67 @@ let
configFile = format.generate "conduit.toml" cfg.settings; configFile = format.generate "conduit.toml" cfg.settings;
in in
{ {
meta.maintainers = with maintainers; [ pstn ]; meta.maintainers = with lib.maintainers; [ pstn ];
options.services.matrix-conduit = { options.services.matrix-conduit = {
enable = mkEnableOption "matrix-conduit"; enable = lib.mkEnableOption "matrix-conduit";
extraEnvironment = mkOption { extraEnvironment = lib.mkOption {
type = types.attrsOf types.str; type = lib.types.attrsOf lib.types.str;
description = "Extra Environment variables to pass to the conduit server."; description = "Extra Environment variables to pass to the conduit server.";
default = {}; default = {};
example = { RUST_BACKTRACE="yes"; }; example = { RUST_BACKTRACE="yes"; };
}; };
package = mkPackageOption pkgs "matrix-conduit" { }; package = lib.mkPackageOption pkgs "matrix-conduit" { };
settings = mkOption { settings = lib.mkOption {
type = types.submodule { type = lib.types.submodule {
freeformType = format.type; freeformType = format.type;
options = { options = {
global.server_name = mkOption { global.server_name = lib.mkOption {
type = types.str; type = lib.types.str;
example = "example.com"; example = "example.com";
description = "The server_name is the name of this server. It is used as a suffix for user # and room ids."; description = "The server_name is the name of this server. It is used as a suffix for user # and room ids.";
}; };
global.port = mkOption { global.port = lib.mkOption {
type = types.port; type = lib.types.port;
default = 6167; default = 6167;
description = "The port Conduit will be running on. You need to set up a reverse proxy in your web server (e.g. apache or nginx), so all requests to /_matrix on port 443 and 8448 will be forwarded to the Conduit instance running on this port"; description = "The port Conduit will be running on. You need to set up a reverse proxy in your web server (e.g. apache or nginx), so all requests to /_matrix on port 443 and 8448 will be forwarded to the Conduit instance running on this port";
}; };
global.max_request_size = mkOption { global.max_request_size = lib.mkOption {
type = types.ints.positive; type = lib.types.ints.positive;
default = 20000000; default = 20000000;
description = "Max request size in bytes. Don't forget to also change it in the proxy."; description = "Max request size in bytes. Don't forget to also change it in the proxy.";
}; };
global.allow_registration = mkOption { global.allow_registration = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = "Whether new users can register on this server."; description = "Whether new users can register on this server.";
}; };
global.allow_encryption = mkOption { global.allow_encryption = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = true; default = true;
description = "Whether new encrypted rooms can be created. Note: existing rooms will continue to work."; description = "Whether new encrypted rooms can be created. Note: existing rooms will continue to work.";
}; };
global.allow_federation = mkOption { global.allow_federation = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = true; default = true;
description = '' description = ''
Whether this server federates with other servers. Whether this server federates with other servers.
''; '';
}; };
global.trusted_servers = mkOption { global.trusted_servers = lib.mkOption {
type = types.listOf types.str; type = lib.types.listOf lib.types.str;
default = [ "matrix.org" ]; default = [ "matrix.org" ];
description = "Servers trusted with signing server keys."; description = "Servers trusted with signing server keys.";
}; };
global.address = mkOption { global.address = lib.mkOption {
type = types.str; type = lib.types.str;
default = "::1"; default = "::1";
description = "Address to listen on for connections by the reverse proxy/tls terminator."; description = "Address to listen on for connections by the reverse proxy/tls terminator.";
}; };
global.database_path = mkOption { global.database_path = lib.mkOption {
type = types.str; type = lib.types.str;
default = "/var/lib/matrix-conduit/"; default = "/var/lib/matrix-conduit/";
readOnly = true; readOnly = true;
description = '' description = ''
@ -78,8 +75,8 @@ in
and is set to be read only. and is set to be read only.
''; '';
}; };
global.database_backend = mkOption { global.database_backend = lib.mkOption {
type = types.enum [ "sqlite" "rocksdb" ]; type = lib.types.enum [ "sqlite" "rocksdb" ];
default = "sqlite"; default = "sqlite";
example = "rocksdb"; example = "rocksdb";
description = '' description = ''
@ -87,8 +84,8 @@ in
instance will require manual migration of data. instance will require manual migration of data.
''; '';
}; };
global.allow_check_for_updates = mkOption { global.allow_check_for_updates = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Whether to allow Conduit to automatically contact Whether to allow Conduit to automatically contact
@ -109,7 +106,7 @@ in
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
systemd.services.conduit = { systemd.services.conduit = {
description = "Conduit Matrix Server"; description = "Conduit Matrix Server";
documentation = [ "https://gitlab.com/famedly/conduit/" ]; documentation = [ "https://gitlab.com/famedly/conduit/" ];

View file

@ -1,26 +1,23 @@
{ config, pkgs, lib, ... }: { config, pkgs, lib, ... }:
with lib;
let let
cfg = config.services.mautrix-facebook; cfg = config.services.mautrix-facebook;
settingsFormat = pkgs.formats.json {}; settingsFormat = pkgs.formats.json {};
settingsFile = settingsFormat.generate "mautrix-facebook-config.json" cfg.settings; settingsFile = settingsFormat.generate "mautrix-facebook-config.json" cfg.settings;
puppetRegex = concatStringsSep puppetRegex = lib.concatStringsSep
".*" ".*"
(map (map
escapeRegex lib.escapeRegex
(splitString (lib.splitString
"{userid}" "{userid}"
cfg.settings.bridge.username_template)); cfg.settings.bridge.username_template));
in { in {
options = { options = {
services.mautrix-facebook = { services.mautrix-facebook = {
enable = mkEnableOption "Mautrix-Facebook, a Matrix-Facebook hybrid puppeting/relaybot bridge"; enable = lib.mkEnableOption "Mautrix-Facebook, a Matrix-Facebook hybrid puppeting/relaybot bridge";
settings = mkOption rec { settings = lib.mkOption rec {
apply = recursiveUpdate default; apply = lib.recursiveUpdate default;
type = settingsFormat.type; type = settingsFormat.type;
default = { default = {
homeserver = { homeserver = {
@ -70,7 +67,7 @@ in {
}; };
}; };
}; };
example = literalExpression '' example = lib.literalExpression ''
{ {
homeserver = { homeserver = {
address = "http://localhost:8008"; address = "http://localhost:8008";
@ -93,8 +90,8 @@ in {
''; '';
}; };
environmentFile = mkOption { environmentFile = lib.mkOption {
type = types.nullOr types.path; type = lib.types.nullOr lib.types.path;
default = null; default = null;
description = '' description = ''
File containing environment variables to be passed to the mautrix-facebook service. File containing environment variables to be passed to the mautrix-facebook service.
@ -103,16 +100,16 @@ in {
''; '';
}; };
configurePostgresql = mkOption { configurePostgresql = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = true; default = true;
description = '' description = ''
Enable PostgreSQL and create a user and database for mautrix-facebook. The default `settings` reference this database, if you disable this option you must provide a database URL. Enable PostgreSQL and create a user and database for mautrix-facebook. The default `settings` reference this database, if you disable this option you must provide a database URL.
''; '';
}; };
registrationData = mkOption { registrationData = lib.mkOption {
type = types.attrs; type = lib.types.attrs;
default = {}; default = {};
description = '' description = ''
Output data for appservice registration. Simply make any desired changes and serialize to JSON. Note that this data contains secrets so think twice before putting it into the nix store. Output data for appservice registration. Simply make any desired changes and serialize to JSON. Note that this data contains secrets so think twice before putting it into the nix store.
@ -123,7 +120,7 @@ in {
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
users.groups.mautrix-facebook = {}; users.groups.mautrix-facebook = {};
users.users.mautrix-facebook = { users.users.mautrix-facebook = {
@ -131,7 +128,7 @@ in {
isSystemUser = true; isSystemUser = true;
}; };
services.postgresql = mkIf cfg.configurePostgresql { services.postgresql = lib.mkIf cfg.configurePostgresql {
ensureDatabases = ["mautrix-facebook"]; ensureDatabases = ["mautrix-facebook"];
ensureUsers = [{ ensureUsers = [{
name = "mautrix-facebook"; name = "mautrix-facebook";
@ -143,8 +140,8 @@ in {
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
wants = [ wants = [
"network-online.target" "network-online.target"
] ++ optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit ] ++ lib.optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit
++ optional cfg.configurePostgresql "postgresql.service"; ++ lib.optional cfg.configurePostgresql "postgresql.service";
after = wants; after = wants;
serviceConfig = { serviceConfig = {
@ -176,11 +173,11 @@ in {
users = [ users = [
{ {
exclusive = true; exclusive = true;
regex = escapeRegex "@${cfg.settings.appservice.bot_username}:${cfg.settings.homeserver.domain}"; regex = lib.escapeRegex "@${cfg.settings.appservice.bot_username}:${cfg.settings.homeserver.domain}";
} }
{ {
exclusive = true; exclusive = true;
regex = "@${puppetRegex}:${escapeRegex cfg.settings.homeserver.domain}"; regex = "@${puppetRegex}:${lib.escapeRegex cfg.settings.homeserver.domain}";
} }
]; ];
aliases = []; aliases = [];
@ -196,5 +193,5 @@ in {
}; };
}; };
meta.maintainers = with maintainers; [ kevincox ]; meta.maintainers = with lib.maintainers; [ kevincox ];
} }

View file

@ -1,7 +1,4 @@
{ config, pkgs, lib, ... }: { config, pkgs, lib, ... }:
with lib;
let let
dataDir = "/var/lib/mautrix-telegram"; dataDir = "/var/lib/mautrix-telegram";
registrationFile = "${dataDir}/telegram-registration.yaml"; registrationFile = "${dataDir}/telegram-registration.yaml";
@ -13,10 +10,10 @@ let
in { in {
options = { options = {
services.mautrix-telegram = { services.mautrix-telegram = {
enable = mkEnableOption "Mautrix-Telegram, a Matrix-Telegram hybrid puppeting/relaybot bridge"; enable = lib.mkEnableOption "Mautrix-Telegram, a Matrix-Telegram hybrid puppeting/relaybot bridge";
settings = mkOption rec { settings = lib.mkOption rec {
apply = recursiveUpdate default; apply = lib.recursiveUpdate default;
inherit (settingsFormat) type; inherit (settingsFormat) type;
default = { default = {
homeserver = { homeserver = {
@ -64,7 +61,7 @@ in {
}; };
}; };
}; };
example = literalExpression '' example = lib.literalExpression ''
{ {
homeserver = { homeserver = {
address = "http://localhost:8008"; address = "http://localhost:8008";
@ -95,8 +92,8 @@ in {
''; '';
}; };
environmentFile = mkOption { environmentFile = lib.mkOption {
type = types.nullOr types.path; type = lib.types.nullOr lib.types.path;
default = null; default = null;
description = '' description = ''
File containing environment variables to be passed to the mautrix-telegram service, File containing environment variables to be passed to the mautrix-telegram service,
@ -120,11 +117,11 @@ in {
''; '';
}; };
serviceDependencies = mkOption { serviceDependencies = lib.mkOption {
type = with types; listOf str; type = with lib.types; listOf str;
default = optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit; default = lib.optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit;
defaultText = literalExpression '' defaultText = lib.literalExpression ''
optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit lib.optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit
''; '';
description = '' description = ''
List of Systemd services to require and wait for when starting the application service. List of Systemd services to require and wait for when starting the application service.
@ -133,7 +130,7 @@ in {
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
systemd.services.mautrix-telegram = { systemd.services.mautrix-telegram = {
description = "Mautrix-Telegram, a Matrix-Telegram hybrid puppeting/relaybot bridge."; description = "Mautrix-Telegram, a Matrix-Telegram hybrid puppeting/relaybot bridge.";
@ -192,5 +189,5 @@ in {
}; };
}; };
meta.maintainers = with maintainers; [ pacien vskilet ]; meta.maintainers = with lib.maintainers; [ pacien vskilet ];
} }

View file

@ -1,6 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.mjolnir; cfg = config.services.mjolnir;
@ -25,8 +23,8 @@ let
}; };
moduleConfigFile = pkgs.writeText "module-config.yaml" ( moduleConfigFile = pkgs.writeText "module-config.yaml" (
generators.toYAML { } (filterAttrs (_: v: v != null) lib.generators.toYAML { } (lib.filterAttrs (_: v: v != null)
(fold recursiveUpdate { } [ yamlConfig cfg.settings ]))); (lib.fold lib.recursiveUpdate { } [ yamlConfig cfg.settings ])));
# these config files will be merged one after the other to build the final config # these config files will be merged one after the other to build the final config
configFiles = [ configFiles = [
@ -38,8 +36,8 @@ let
# replace all secret strings using replace-secret # replace all secret strings using replace-secret
generateConfig = pkgs.writeShellScript "mjolnir-generate-config" ( generateConfig = pkgs.writeShellScript "mjolnir-generate-config" (
let let
yqEvalStr = concatImapStringsSep " * " (pos: _: "select(fileIndex == ${toString (pos - 1)})") configFiles; yqEvalStr = lib.concatImapStringsSep " * " (pos: _: "select(fileIndex == ${toString (pos - 1)})") configFiles;
yqEvalArgs = concatStringsSep " " configFiles; yqEvalArgs = lib.concatStringsSep " " configFiles;
in in
'' ''
set -euo pipefail set -euo pipefail
@ -54,10 +52,10 @@ let
# e.g. "eval-all 'select(fileIndex == 0) * select(fileIndex == 1)' filea.yaml fileb.yaml" will merge filea.yaml with fileb.yaml # e.g. "eval-all 'select(fileIndex == 0) * select(fileIndex == 1)' filea.yaml fileb.yaml" will merge filea.yaml with fileb.yaml
${pkgs.yq-go}/bin/yq eval-all -P '${yqEvalStr}' ${yqEvalArgs} > ${cfg.dataPath}/config/default.yaml ${pkgs.yq-go}/bin/yq eval-all -P '${yqEvalStr}' ${yqEvalArgs} > ${cfg.dataPath}/config/default.yaml
${optionalString (cfg.accessTokenFile != null) '' ${lib.optionalString (cfg.accessTokenFile != null) ''
${pkgs.replace-secret}/bin/replace-secret '@ACCESS_TOKEN@' '${cfg.accessTokenFile}' ${cfg.dataPath}/config/default.yaml ${pkgs.replace-secret}/bin/replace-secret '@ACCESS_TOKEN@' '${cfg.accessTokenFile}' ${cfg.dataPath}/config/default.yaml
''} ''}
${optionalString (cfg.pantalaimon.passwordFile != null) '' ${lib.optionalString (cfg.pantalaimon.passwordFile != null) ''
${pkgs.replace-secret}/bin/replace-secret '@PANTALAIMON_PASSWORD@' '${cfg.pantalaimon.passwordFile}' ${cfg.dataPath}/config/default.yaml ${pkgs.replace-secret}/bin/replace-secret '@PANTALAIMON_PASSWORD@' '${cfg.pantalaimon.passwordFile}' ${cfg.dataPath}/config/default.yaml
''} ''}
'' ''
@ -65,10 +63,10 @@ let
in in
{ {
options.services.mjolnir = { options.services.mjolnir = {
enable = mkEnableOption "Mjolnir, a moderation tool for Matrix"; enable = lib.mkEnableOption "Mjolnir, a moderation tool for Matrix";
homeserverUrl = mkOption { homeserverUrl = lib.mkOption {
type = types.str; type = lib.types.str;
default = "https://matrix.org"; default = "https://matrix.org";
description = '' description = ''
Where the homeserver is located (client-server URL). Where the homeserver is located (client-server URL).
@ -78,43 +76,43 @@ in
''; '';
}; };
accessTokenFile = mkOption { accessTokenFile = lib.mkOption {
type = with types; nullOr path; type = with lib.types; nullOr path;
default = null; default = null;
description = '' description = ''
File containing the matrix access token for the `mjolnir` user. File containing the matrix access token for the `mjolnir` user.
''; '';
}; };
pantalaimon = mkOption { pantalaimon = lib.mkOption {
description = '' description = ''
`pantalaimon` options (enables E2E Encryption support). `pantalaimon` options (enables E2E Encryption support).
This will create a `pantalaimon` instance with the name "mjolnir". This will create a `pantalaimon` instance with the name "mjolnir".
''; '';
default = { }; default = { };
type = types.submodule { type = lib.types.submodule {
options = { options = {
enable = mkEnableOption '' enable = lib.mkEnableOption ''
ignoring the accessToken. If true, accessToken is ignored and the username/password below will be ignoring the accessToken. If true, accessToken is ignored and the username/password below will be
used instead. The access token of the bot will be stored in the dataPath used instead. The access token of the bot will be stored in the dataPath
''; '';
username = mkOption { username = lib.mkOption {
type = types.str; type = lib.types.str;
description = "The username to login with."; description = "The username to login with.";
}; };
passwordFile = mkOption { passwordFile = lib.mkOption {
type = with types; nullOr path; type = with lib.types; nullOr path;
default = null; default = null;
description = '' description = ''
File containing the matrix password for the `mjolnir` user. File containing the matrix password for the `mjolnir` user.
''; '';
}; };
options = mkOption { options = lib.mkOption {
type = types.submodule (import ./pantalaimon-options.nix); type = lib.types.submodule (import ./pantalaimon-options.nix);
default = { }; default = { };
description = '' description = ''
passthrough additional options to the `pantalaimon` service. passthrough additional options to the `pantalaimon` service.
@ -124,16 +122,16 @@ in
}; };
}; };
dataPath = mkOption { dataPath = lib.mkOption {
type = types.path; type = lib.types.path;
default = "/var/lib/mjolnir"; default = "/var/lib/mjolnir";
description = '' description = ''
The directory the bot should store various bits of information in. The directory the bot should store various bits of information in.
''; '';
}; };
managementRoom = mkOption { managementRoom = lib.mkOption {
type = types.str; type = lib.types.str;
default = "#moderators:example.org"; default = "#moderators:example.org";
description = '' description = ''
The room ID where people can use the bot. The bot has no access controls, so The room ID where people can use the bot. The bot has no access controls, so
@ -143,10 +141,10 @@ in
''; '';
}; };
protectedRooms = mkOption { protectedRooms = lib.mkOption {
type = types.listOf types.str; type = lib.types.listOf lib.types.str;
default = [ ]; default = [ ];
example = literalExpression '' example = lib.literalExpression ''
[ [
"https://matrix.to/#/#yourroom:example.org" "https://matrix.to/#/#yourroom:example.org"
"https://matrix.to/#/#anotherroom:example.org" "https://matrix.to/#/#anotherroom:example.org"
@ -157,10 +155,10 @@ in
''; '';
}; };
settings = mkOption { settings = lib.mkOption {
default = { }; default = { };
type = (pkgs.formats.yaml { }).type; type = (pkgs.formats.yaml { }).type;
example = literalExpression '' example = lib.literalExpression ''
{ {
autojoinOnlyIfManager = true; autojoinOnlyIfManager = true;
automaticallyRedactForReasons = [ "spam" "advertising" ]; automaticallyRedactForReasons = [ "spam" "advertising" ];
@ -172,7 +170,7 @@ in
}; };
}; };
config = mkIf config.services.mjolnir.enable { config = lib.mkIf config.services.mjolnir.enable {
assertions = [ assertions = [
{ {
assertion = !(cfg.pantalaimon.enable && cfg.pantalaimon.passwordFile == null); assertion = !(cfg.pantalaimon.enable && cfg.pantalaimon.passwordFile == null);
@ -188,15 +186,15 @@ in
} }
]; ];
services.pantalaimon-headless.instances."mjolnir" = mkIf cfg.pantalaimon.enable services.pantalaimon-headless.instances."mjolnir" = lib.mkIf cfg.pantalaimon.enable
{ {
homeserver = cfg.homeserverUrl; homeserver = cfg.homeserverUrl;
} // cfg.pantalaimon.options; } // cfg.pantalaimon.options;
systemd.services.mjolnir = { systemd.services.mjolnir = {
description = "mjolnir - a moderation tool for Matrix"; description = "mjolnir - a moderation tool for Matrix";
wants = [ "network-online.target" ] ++ optionals (cfg.pantalaimon.enable) [ "pantalaimon-mjolnir.service" ]; wants = [ "network-online.target" ] ++ lib.optionals (cfg.pantalaimon.enable) [ "pantalaimon-mjolnir.service" ];
after = [ "network-online.target" ] ++ optionals (cfg.pantalaimon.enable) [ "pantalaimon-mjolnir.service" ]; after = [ "network-online.target" ] ++ lib.optionals (cfg.pantalaimon.enable) [ "pantalaimon-mjolnir.service" ];
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
serviceConfig = { serviceConfig = {
@ -216,10 +214,10 @@ in
/* TODO: wait for #102397 to be resolved. Then load secrets from $CREDENTIALS_DIRECTORY+"/NAME" /* TODO: wait for #102397 to be resolved. Then load secrets from $CREDENTIALS_DIRECTORY+"/NAME"
DynamicUser = true; DynamicUser = true;
LoadCredential = [] ++ LoadCredential = [] ++
optionals (cfg.accessTokenFile != null) [ lib.optionals (cfg.accessTokenFile != null) [
"access_token:${cfg.accessTokenFile}" "access_token:${cfg.accessTokenFile}"
] ++ ] ++
optionals (cfg.pantalaimon.passwordFile != null) [ lib.optionals (cfg.pantalaimon.passwordFile != null) [
"pantalaimon_password:${cfg.pantalaimon.passwordFile}" "pantalaimon_password:${cfg.pantalaimon.passwordFile}"
]; ];
*/ */
@ -237,6 +235,6 @@ in
meta = { meta = {
doc = ./mjolnir.md; doc = ./mjolnir.md;
maintainers = with maintainers; [ jojosch ]; maintainers = with lib.maintainers; [ jojosch ];
}; };
} }

View file

@ -1,7 +1,4 @@
{ config, pkgs, lib, ... }: { config, pkgs, lib, ... }:
with lib;
let let
dataDir = "/var/lib/mx-puppet-discord"; dataDir = "/var/lib/mx-puppet-discord";
registrationFile = "${dataDir}/discord-registration.yaml"; registrationFile = "${dataDir}/discord-registration.yaml";
@ -12,13 +9,13 @@ let
in { in {
options = { options = {
services.mx-puppet-discord = { services.mx-puppet-discord = {
enable = mkEnableOption '' enable = lib.mkEnableOption ''
mx-puppet-discord is a discord puppeting bridge for matrix. mx-puppet-discord is a discord puppeting bridge for matrix.
It handles bridging private and group DMs, as well as Guilds (servers) It handles bridging private and group DMs, as well as Guilds (servers)
''; '';
settings = mkOption rec { settings = lib.mkOption rec {
apply = recursiveUpdate default; apply = lib.recursiveUpdate default;
inherit (settingsFormat) type; inherit (settingsFormat) type;
default = { default = {
bridge.port = 8434; bridge.port = 8434;
@ -45,7 +42,7 @@ in {
lineDateFormat = "MMM-D HH:mm:ss.SSS"; lineDateFormat = "MMM-D HH:mm:ss.SSS";
}; };
}; };
example = literalExpression '' example = lib.literalExpression ''
{ {
bridge = { bridge = {
bindAddress = "localhost"; bindAddress = "localhost";
@ -64,11 +61,11 @@ in {
sample.config.yaml](https://github.com/matrix-discord/mx-puppet-discord/blob/master/sample.config.yaml). sample.config.yaml](https://github.com/matrix-discord/mx-puppet-discord/blob/master/sample.config.yaml).
''; '';
}; };
serviceDependencies = mkOption { serviceDependencies = lib.mkOption {
type = with types; listOf str; type = with lib.types; listOf str;
default = optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit; default = lib.optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit;
defaultText = literalExpression '' defaultText = lib.literalExpression ''
optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit lib.optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit
''; '';
description = '' description = ''
List of Systemd services to require and wait for when starting the application service. List of Systemd services to require and wait for when starting the application service.
@ -77,7 +74,7 @@ in {
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
systemd.services.mx-puppet-discord = { systemd.services.mx-puppet-discord = {
description = "Matrix to Discord puppeting bridge"; description = "Matrix to Discord puppeting bridge";
@ -118,5 +115,5 @@ in {
}; };
}; };
meta.maintainers = with maintainers; [ govanify ]; meta.maintainers = with lib.maintainers; [ govanify ];
} }

View file

@ -1,26 +1,24 @@
{ config, lib, name, ... }: { config, lib, name, ... }:
with lib;
{ {
options = { options = {
dataPath = mkOption { dataPath = lib.mkOption {
type = types.path; type = lib.types.path;
default = "/var/lib/pantalaimon-${name}"; default = "/var/lib/pantalaimon-${name}";
description = '' description = ''
The directory where `pantalaimon` should store its state such as the database file. The directory where `pantalaimon` should store its state such as the database file.
''; '';
}; };
logLevel = mkOption { logLevel = lib.mkOption {
type = types.enum [ "info" "warning" "error" "debug" ]; type = lib.types.enum [ "info" "warning" "error" "debug" ];
default = "warning"; default = "warning";
description = '' description = ''
Set the log level of the daemon. Set the log level of the daemon.
''; '';
}; };
homeserver = mkOption { homeserver = lib.mkOption {
type = types.str; type = lib.types.str;
example = "https://matrix.org"; example = "https://matrix.org";
description = '' description = ''
The URI of the homeserver that the `pantalaimon` proxy should The URI of the homeserver that the `pantalaimon` proxy should
@ -29,8 +27,8 @@ with lib;
''; '';
}; };
ssl = mkOption { ssl = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = true; default = true;
description = '' description = ''
Whether or not SSL verification should be enabled for outgoing Whether or not SSL verification should be enabled for outgoing
@ -38,8 +36,8 @@ with lib;
''; '';
}; };
listenAddress = mkOption { listenAddress = lib.mkOption {
type = types.str; type = lib.types.str;
default = "localhost"; default = "localhost";
description = '' description = ''
The address where the daemon will listen to client connections The address where the daemon will listen to client connections
@ -47,18 +45,18 @@ with lib;
''; '';
}; };
listenPort = mkOption { listenPort = lib.mkOption {
type = types.port; type = lib.types.port;
default = 8009; default = 8009;
description = '' description = ''
The port where the daemon will listen to client connections for The port where the daemon will listen to client connections for
this homeserver. Note that the listen address/port combination this homeserver. Note that the listen address/port combination
needs to be unique between different homeservers. needs to be lib.unique between different homeservers.
''; '';
}; };
extraSettings = mkOption { extraSettings = lib.mkOption {
type = types.attrs; type = lib.types.attrs;
default = { }; default = { };
description = '' description = ''
Extra configuration options. See Extra configuration options. See

View file

@ -1,6 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.pantalaimon-headless; cfg = config.services.pantalaimon-headless;
@ -12,7 +10,7 @@ let
Notifications = false; Notifications = false;
}; };
${name} = (recursiveUpdate ${name} = (lib.recursiveUpdate
{ {
Homeserver = instanceConfig.homeserver; Homeserver = instanceConfig.homeserver;
ListenAddress = instanceConfig.listenAddress; ListenAddress = instanceConfig.listenAddress;
@ -28,7 +26,7 @@ let
}; };
mkPantalaimonService = name: instanceConfig: mkPantalaimonService = name: instanceConfig:
nameValuePair "pantalaimon-${name}" { lib.nameValuePair "pantalaimon-${name}" {
description = "pantalaimon instance ${name} - E2EE aware proxy daemon for matrix clients"; description = "pantalaimon instance ${name} - E2EE aware proxy daemon for matrix clients";
wants = [ "network-online.target" ]; wants = [ "network-online.target" ];
after = [ "network-online.target" ]; after = [ "network-online.target" ];
@ -48,9 +46,9 @@ let
}; };
in in
{ {
options.services.pantalaimon-headless.instances = mkOption { options.services.pantalaimon-headless.instances = lib.mkOption {
default = { }; default = { };
type = types.attrsOf (types.submodule (import ./pantalaimon-options.nix)); type = lib.types.attrsOf (lib.types.submodule (import ./pantalaimon-options.nix));
description = '' description = ''
Declarative instance config. Declarative instance config.
@ -59,12 +57,12 @@ in
''; '';
}; };
config = mkIf (config.services.pantalaimon-headless.instances != { }) config = lib.mkIf (config.services.pantalaimon-headless.instances != { })
{ {
systemd.services = mapAttrs' mkPantalaimonService config.services.pantalaimon-headless.instances; systemd.services = lib.mapAttrs' mkPantalaimonService config.services.pantalaimon-headless.instances;
}; };
meta = { meta = {
maintainers = with maintainers; [ jojosch ]; maintainers = with lib.maintainers; [ jojosch ];
}; };
} }

View file

@ -1,7 +1,4 @@
{ config, lib, options, pkgs, ... }: { config, lib, options, pkgs, ... }:
with lib;
let let
cfg = config.services.airsonic; cfg = config.services.airsonic;
opt = options.services.airsonic; opt = options.services.airsonic;
@ -9,16 +6,16 @@ in {
options = { options = {
services.airsonic = { services.airsonic = {
enable = mkEnableOption "Airsonic, the Free and Open Source media streaming server (fork of Subsonic and Libresonic)"; enable = lib.mkEnableOption "Airsonic, the Free and Open Source media streaming server (fork of Subsonic and Libresonic)";
user = mkOption { user = lib.mkOption {
type = types.str; type = lib.types.str;
default = "airsonic"; default = "airsonic";
description = "User account under which airsonic runs."; description = "User account under which airsonic runs.";
}; };
home = mkOption { home = lib.mkOption {
type = types.path; type = lib.types.path;
default = "/var/lib/airsonic"; default = "/var/lib/airsonic";
description = '' description = ''
The directory where Airsonic will create files. The directory where Airsonic will create files.
@ -26,16 +23,16 @@ in {
''; '';
}; };
virtualHost = mkOption { virtualHost = lib.mkOption {
type = types.nullOr types.str; type = lib.types.nullOr lib.types.str;
default = null; default = null;
description = '' description = ''
Name of the nginx virtualhost to use and setup. If null, do not setup any virtualhost. Name of the nginx virtualhost to use and setup. If null, do not setup any virtualhost.
''; '';
}; };
listenAddress = mkOption { listenAddress = lib.mkOption {
type = types.str; type = lib.types.str;
default = "127.0.0.1"; default = "127.0.0.1";
description = '' description = ''
The host name or IP address on which to bind Airsonic. The host name or IP address on which to bind Airsonic.
@ -47,8 +44,8 @@ in {
''; '';
}; };
port = mkOption { port = lib.mkOption {
type = types.port; type = lib.types.port;
default = 4040; default = 4040;
description = '' description = ''
The port on which Airsonic will listen for The port on which Airsonic will listen for
@ -56,8 +53,8 @@ in {
''; '';
}; };
contextPath = mkOption { contextPath = lib.mkOption {
type = types.path; type = lib.types.path;
default = "/"; default = "/";
description = '' description = ''
The context path, i.e., the last part of the Airsonic The context path, i.e., the last part of the Airsonic
@ -65,8 +62,8 @@ in {
''; '';
}; };
maxMemory = mkOption { maxMemory = lib.mkOption {
type = types.int; type = lib.types.int;
default = 100; default = 100;
description = '' description = ''
The memory limit (max Java heap size) in megabytes. The memory limit (max Java heap size) in megabytes.
@ -74,10 +71,10 @@ in {
''; '';
}; };
transcoders = mkOption { transcoders = lib.mkOption {
type = types.listOf types.path; type = lib.types.listOf lib.types.path;
default = [ "${pkgs.ffmpeg.bin}/bin/ffmpeg" ]; default = [ "${pkgs.ffmpeg.bin}/bin/ffmpeg" ];
defaultText = literalExpression ''[ "''${pkgs.ffmpeg.bin}/bin/ffmpeg" ]''; defaultText = lib.literalExpression ''[ "''${pkgs.ffmpeg.bin}/bin/ffmpeg" ]'';
description = '' description = ''
List of paths to transcoder executables that should be accessible List of paths to transcoder executables that should be accessible
from Airsonic. Symlinks will be created to each executable inside from Airsonic. Symlinks will be created to each executable inside
@ -85,7 +82,7 @@ in {
''; '';
}; };
jre = mkPackageOption pkgs "jre8" { jre = lib.mkPackageOption pkgs "jre8" {
extraDescription = '' extraDescription = ''
::: {.note} ::: {.note}
Airsonic only supports Java 8, airsonic-advanced requires at least Airsonic only supports Java 8, airsonic-advanced requires at least
@ -94,14 +91,14 @@ in {
''; '';
}; };
war = mkOption { war = lib.mkOption {
type = types.path; type = lib.types.path;
default = "${pkgs.airsonic}/webapps/airsonic.war"; default = "${pkgs.airsonic}/webapps/airsonic.war";
defaultText = literalExpression ''"''${pkgs.airsonic}/webapps/airsonic.war"''; defaultText = lib.literalExpression ''"''${pkgs.airsonic}/webapps/airsonic.war"'';
description = "Airsonic war file to use."; description = "Airsonic war file to use.";
}; };
jvmOptions = mkOption { jvmOptions = lib.mkOption {
description = '' description = ''
Extra command line options for the JVM running AirSonic. Extra command line options for the JVM running AirSonic.
Useful for sending jukebox output to non-default alsa Useful for sending jukebox output to non-default alsa
@ -109,7 +106,7 @@ in {
''; '';
default = [ default = [
]; ];
type = types.listOf types.str; type = lib.types.listOf lib.types.str;
example = [ example = [
"-Djavax.sound.sampled.Clip='#CODEC [plughw:1,0]'" "-Djavax.sound.sampled.Clip='#CODEC [plughw:1,0]'"
"-Djavax.sound.sampled.Port='#Port CODEC [hw:1]'" "-Djavax.sound.sampled.Port='#Port CODEC [hw:1]'"
@ -121,7 +118,7 @@ in {
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
systemd.services.airsonic = { systemd.services.airsonic = {
description = "Airsonic Media Server"; description = "Airsonic Media Server";
after = [ "network.target" ]; after = [ "network.target" ];
@ -143,7 +140,7 @@ in {
-Dserver.port=${toString cfg.port} \ -Dserver.port=${toString cfg.port} \
-Dserver.context-path=${cfg.contextPath} \ -Dserver.context-path=${cfg.contextPath} \
-Djava.awt.headless=true \ -Djava.awt.headless=true \
${optionalString (cfg.virtualHost != null) ${lib.optionalString (cfg.virtualHost != null)
"-Dserver.use-forward-headers=true"} \ "-Dserver.use-forward-headers=true"} \
${toString cfg.jvmOptions} \ ${toString cfg.jvmOptions} \
-verbose:gc \ -verbose:gc \
@ -155,7 +152,7 @@ in {
}; };
}; };
services.nginx = mkIf (cfg.virtualHost != null) { services.nginx = lib.mkIf (cfg.virtualHost != null) {
enable = true; enable = true;
recommendedProxySettings = true; recommendedProxySettings = true;
virtualHosts.${cfg.virtualHost} = { virtualHosts.${cfg.virtualHost} = {

View file

@ -1,6 +1,4 @@
{ config, pkgs, lib, ... }: { config, pkgs, lib, ... }:
with lib;
let let
cfg = config.services.amazon-ssm-agent; cfg = config.services.amazon-ssm-agent;
@ -22,16 +20,16 @@ let
}; };
in { in {
imports = [ imports = [
(mkRenamedOptionModule [ "services" "ssm-agent" "enable" ] [ "services" "amazon-ssm-agent" "enable" ]) (lib.mkRenamedOptionModule [ "services" "ssm-agent" "enable" ] [ "services" "amazon-ssm-agent" "enable" ])
(mkRenamedOptionModule [ "services" "ssm-agent" "package" ] [ "services" "amazon-ssm-agent" "package" ]) (lib.mkRenamedOptionModule [ "services" "ssm-agent" "package" ] [ "services" "amazon-ssm-agent" "package" ])
]; ];
options.services.amazon-ssm-agent = { options.services.amazon-ssm-agent = {
enable = mkEnableOption "Amazon SSM agent"; enable = lib.mkEnableOption "Amazon SSM agent";
package = mkPackageOption pkgs "amazon-ssm-agent" {}; package = lib.mkPackageOption pkgs "amazon-ssm-agent" {};
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
# See https://github.com/aws/amazon-ssm-agent/blob/mainline/packaging/linux/amazon-ssm-agent.service # See https://github.com/aws/amazon-ssm-agent/blob/mainline/packaging/linux/amazon-ssm-agent.service
systemd.services.amazon-ssm-agent = { systemd.services.amazon-ssm-agent = {
inherit (cfg.package.meta) description; inherit (cfg.package.meta) description;

View file

@ -1,7 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.ankisyncd; cfg = config.services.ankisyncd;
@ -22,37 +19,37 @@ let
in in
{ {
options.services.ankisyncd = { options.services.ankisyncd = {
enable = mkEnableOption "ankisyncd, a standalone unofficial anky sync server"; enable = lib.mkEnableOption "ankisyncd, a standalone unofficial anky sync server";
package = mkPackageOption pkgs "ankisyncd" { }; package = lib.mkPackageOption pkgs "ankisyncd" { };
host = mkOption { host = lib.mkOption {
type = types.str; type = lib.types.str;
default = "localhost"; default = "localhost";
description = "ankisyncd host"; description = "ankisyncd host";
}; };
port = mkOption { port = lib.mkOption {
type = types.port; type = lib.types.port;
default = 27701; default = 27701;
description = "ankisyncd port"; description = "ankisyncd port";
}; };
openFirewall = mkOption { openFirewall = lib.mkOption {
default = false; default = false;
type = types.bool; type = lib.types.bool;
description = "Whether to open the firewall for the specified port."; description = "Whether to open the firewall for the specified port.";
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
warnings = [ warnings = [
'' ''
`services.ankisyncd` has been replaced by `services.anki-sync-server` and will be removed after `services.ankisyncd` has been replaced by `services.anki-sync-server` and will be removed after
24.05 because anki-sync-server(-rs and python) are not maintained. 24.05 because anki-sync-server(-rs and python) are not maintained.
'' ''
]; ];
networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ]; networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [ cfg.port ];
systemd.services.ankisyncd = { systemd.services.ankisyncd = {
description = "ankisyncd - Anki sync server"; description = "ankisyncd - Anki sync server";

View file

@ -1,7 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.apache-kafka; cfg = config.services.apache-kafka;
@ -17,24 +14,24 @@ let
mkPropertyString = let mkPropertyString = let
render = { render = {
bool = boolToString; bool = lib.boolToString;
int = toString; int = toString;
list = concatMapStringsSep "," mkPropertyString; list = lib.concatMapStringsSep "," mkPropertyString;
string = id; string = lib.id;
}; };
in in
v: render.${builtins.typeOf v} v; v: render.${builtins.typeOf v} v;
stringlySettings = mapAttrs (_: mkPropertyString) stringlySettings = lib.mapAttrs (_: mkPropertyString)
(filterAttrs (_: v: v != null) cfg.settings); (lib.filterAttrs (_: v: v != null) cfg.settings);
generator = (pkgs.formats.javaProperties {}).generate; generator = (pkgs.formats.javaProperties {}).generate;
in { in {
options.services.apache-kafka = { options.services.apache-kafka = {
enable = mkEnableOption "Apache Kafka event streaming broker"; enable = lib.mkEnableOption "Apache Kafka event streaming broker";
settings = mkOption { settings = lib.mkOption {
description = '' description = ''
[Kafka broker configuration](https://kafka.apache.org/documentation.html#brokerconfigs) [Kafka broker configuration](https://kafka.apache.org/documentation.html#brokerconfigs)
{file}`server.properties`. {file}`server.properties`.
@ -44,81 +41,81 @@ in {
but instead as quoted strings (ie. `settings."broker.id"`, NOT but instead as quoted strings (ie. `settings."broker.id"`, NOT
`settings.broker.id`). `settings.broker.id`).
''; '';
type = types.submodule { type = lib.types.submodule {
freeformType = with types; let freeformType = with lib.types; let
primitive = oneOf [bool int str]; primitive = oneOf [bool int str];
in lazyAttrsOf (nullOr (either primitive (listOf primitive))); in lazyAttrsOf (nullOr (either primitive (listOf primitive)));
options = { options = {
"broker.id" = mkOption { "broker.id" = lib.mkOption {
description = "Broker ID. -1 or null to auto-allocate in zookeeper mode."; description = "Broker ID. -1 or null to auto-allocate in zookeeper mode.";
default = null; default = null;
type = with types; nullOr int; type = with lib.types; nullOr int;
}; };
"log.dirs" = mkOption { "log.dirs" = lib.mkOption {
description = "Log file directories."; description = "Log file directories.";
# Deliberaly leave out old default and use the rewrite opportunity # Deliberaly leave out old default and use the rewrite opportunity
# to have users choose a safer value -- /tmp might be volatile and is a # to have users choose a safer value -- /tmp might be volatile and is a
# slightly scary default choice. # slightly scary default choice.
# default = [ "/tmp/apache-kafka" ]; # default = [ "/tmp/apache-kafka" ];
type = with types; listOf path; type = with lib.types; listOf path;
}; };
"listeners" = mkOption { "listeners" = lib.mkOption {
description = '' description = ''
Kafka Listener List. Kafka Listener List.
See [listeners](https://kafka.apache.org/documentation/#brokerconfigs_listeners). See [listeners](https://kafka.apache.org/documentation/#brokerconfigs_listeners).
''; '';
type = types.listOf types.str; type = lib.types.listOf lib.types.str;
default = [ "PLAINTEXT://localhost:9092" ]; default = [ "PLAINTEXT://localhost:9092" ];
}; };
}; };
}; };
}; };
clusterId = mkOption { clusterId = lib.mkOption {
description = '' description = ''
KRaft mode ClusterId used for formatting log directories. Can be generated with `kafka-storage.sh random-uuid` KRaft mode ClusterId used for formatting log directories. Can be generated with `kafka-storage.sh random-uuid`
''; '';
type = with types; nullOr str; type = with lib.types; nullOr str;
default = null; default = null;
}; };
configFiles.serverProperties = mkOption { configFiles.serverProperties = lib.mkOption {
description = '' description = ''
Kafka server.properties configuration file path. Kafka server.properties configuration file path.
Defaults to the rendered `settings`. Defaults to the rendered `settings`.
''; '';
type = types.path; type = lib.types.path;
}; };
configFiles.log4jProperties = mkOption { configFiles.log4jProperties = lib.mkOption {
description = "Kafka log4j property configuration file path"; description = "Kafka log4j property configuration file path";
type = types.path; type = lib.types.path;
default = pkgs.writeText "log4j.properties" cfg.log4jProperties; default = pkgs.writeText "log4j.properties" cfg.log4jProperties;
defaultText = ''pkgs.writeText "log4j.properties" cfg.log4jProperties''; defaultText = ''pkgs.writeText "log4j.properties" cfg.log4jProperties'';
}; };
formatLogDirs = mkOption { formatLogDirs = lib.mkOption {
description = '' description = ''
Whether to format log dirs in KRaft mode if all log dirs are Whether to format log dirs in KRaft mode if all log dirs are
unformatted, ie. they contain no meta.properties. unformatted, ie. they contain no meta.properties.
''; '';
type = types.bool; type = lib.types.bool;
default = false; default = false;
}; };
formatLogDirsIgnoreFormatted = mkOption { formatLogDirsIgnoreFormatted = lib.mkOption {
description = '' description = ''
Whether to ignore already formatted log dirs when formatting log dirs, Whether to ignore already formatted log dirs when formatting log dirs,
instead of failing. Useful when replacing or adding disks. instead of failing. Useful when replacing or adding disks.
''; '';
type = types.bool; type = lib.types.bool;
default = false; default = false;
}; };
log4jProperties = mkOption { log4jProperties = lib.mkOption {
description = "Kafka log4j property configuration."; description = "Kafka log4j property configuration.";
default = '' default = ''
log4j.rootLogger=INFO, stdout log4j.rootLogger=INFO, stdout
@ -127,13 +124,13 @@ in {
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%d] %p %m (%c)%n log4j.appender.stdout.layout.ConversionPattern=[%d] %p %m (%c)%n
''; '';
type = types.lines; type = lib.types.lines;
}; };
jvmOptions = mkOption { jvmOptions = lib.mkOption {
description = "Extra command line options for the JVM running Kafka."; description = "Extra command line options for the JVM running Kafka.";
default = []; default = [];
type = types.listOf types.str; type = lib.types.listOf lib.types.str;
example = [ example = [
"-Djava.net.preferIPv4Stack=true" "-Djava.net.preferIPv4Stack=true"
"-Dcom.sun.management.jmxremote" "-Dcom.sun.management.jmxremote"
@ -141,38 +138,38 @@ in {
]; ];
}; };
package = mkPackageOption pkgs "apacheKafka" { }; package = lib.mkPackageOption pkgs "apacheKafka" { };
jre = mkOption { jre = lib.mkOption {
description = "The JRE with which to run Kafka"; description = "The JRE with which to run Kafka";
default = cfg.package.passthru.jre; default = cfg.package.passthru.jre;
defaultText = literalExpression "pkgs.apacheKafka.passthru.jre"; defaultText = lib.literalExpression "pkgs.apacheKafka.passthru.jre";
type = types.package; type = lib.types.package;
}; };
}; };
imports = [ imports = [
(mkRenamedOptionModule (lib.mkRenamedOptionModule
[ "services" "apache-kafka" "brokerId" ] [ "services" "apache-kafka" "brokerId" ]
[ "services" "apache-kafka" "settings" ''broker.id'' ]) [ "services" "apache-kafka" "settings" ''broker.id'' ])
(mkRenamedOptionModule (lib.mkRenamedOptionModule
[ "services" "apache-kafka" "logDirs" ] [ "services" "apache-kafka" "logDirs" ]
[ "services" "apache-kafka" "settings" ''log.dirs'' ]) [ "services" "apache-kafka" "settings" ''log.dirs'' ])
(mkRenamedOptionModule (lib.mkRenamedOptionModule
[ "services" "apache-kafka" "zookeeper" ] [ "services" "apache-kafka" "zookeeper" ]
[ "services" "apache-kafka" "settings" ''zookeeper.connect'' ]) [ "services" "apache-kafka" "settings" ''zookeeper.connect'' ])
(mkRemovedOptionModule [ "services" "apache-kafka" "port" ] (lib.mkRemovedOptionModule [ "services" "apache-kafka" "port" ]
"Please see services.apache-kafka.settings.listeners and its documentation instead") "Please see services.apache-kafka.settings.listeners and its documentation instead")
(mkRemovedOptionModule [ "services" "apache-kafka" "hostname" ] (lib.mkRemovedOptionModule [ "services" "apache-kafka" "hostname" ]
"Please see services.apache-kafka.settings.listeners and its documentation instead") "Please see services.apache-kafka.settings.listeners and its documentation instead")
(mkRemovedOptionModule [ "services" "apache-kafka" "extraProperties" ] (lib.mkRemovedOptionModule [ "services" "apache-kafka" "extraProperties" ]
"Please see services.apache-kafka.settings and its documentation instead") "Please see services.apache-kafka.settings and its documentation instead")
(mkRemovedOptionModule [ "services" "apache-kafka" "serverProperties" ] (lib.mkRemovedOptionModule [ "services" "apache-kafka" "serverProperties" ]
"Please see services.apache-kafka.settings and its documentation instead") "Please see services.apache-kafka.settings and its documentation instead")
]; ];
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
services.apache-kafka.configFiles.serverProperties = generator "server.properties" stringlySettings; services.apache-kafka.configFiles.serverProperties = generator "server.properties" stringlySettings;
users.users.apache-kafka = { users.users.apache-kafka = {
@ -188,11 +185,11 @@ in {
description = "Apache Kafka Daemon"; description = "Apache Kafka Daemon";
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
after = [ "network.target" ]; after = [ "network.target" ];
preStart = mkIf cfg.formatLogDirs preStart = lib.mkIf cfg.formatLogDirs
(if cfg.formatLogDirsIgnoreFormatted then '' (if cfg.formatLogDirsIgnoreFormatted then ''
${cfg.package}/bin/kafka-storage.sh format -t "${cfg.clusterId}" -c ${cfg.configFiles.serverProperties} --ignore-formatted ${cfg.package}/bin/kafka-storage.sh format -t "${cfg.clusterId}" -c ${cfg.configFiles.serverProperties} --ignore-formatted
'' else '' '' else ''
if ${concatMapStringsSep " && " (l: ''[ ! -f "${l}/meta.properties" ]'') cfg.settings."log.dirs"}; then if ${lib.concatMapStringsSep " && " (l: ''[ ! -f "${l}/meta.properties" ]'') cfg.settings."log.dirs"}; then
${cfg.package}/bin/kafka-storage.sh format -t "${cfg.clusterId}" -c ${cfg.configFiles.serverProperties} ${cfg.package}/bin/kafka-storage.sh format -t "${cfg.clusterId}" -c ${cfg.configFiles.serverProperties}
fi fi
''); '');

View file

@ -1,7 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.autofs; cfg = config.services.autofs;
@ -18,8 +15,8 @@ in
services.autofs = { services.autofs = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Mount filesystems on demand. Unmount them automatically. Mount filesystems on demand. Unmount them automatically.
@ -27,9 +24,9 @@ in
''; '';
}; };
autoMaster = mkOption { autoMaster = lib.mkOption {
type = types.str; type = lib.types.str;
example = literalExpression '' example = lib.literalExpression ''
let let
mapConf = pkgs.writeText "auto" ''' mapConf = pkgs.writeText "auto" '''
kernel -ro,soft,intr ftp.kernel.org:/pub/linux kernel -ro,soft,intr ftp.kernel.org:/pub/linux
@ -51,14 +48,14 @@ in
''; '';
}; };
timeout = mkOption { timeout = lib.mkOption {
type = types.int; type = lib.types.int;
default = 600; default = 600;
description = "Set the global minimum timeout, in seconds, until directories are unmounted"; description = "Set the global minimum timeout, in seconds, until directories are unmounted";
}; };
debug = mkOption { debug = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Pass -d and -7 to automount and write log to the system journal. Pass -d and -7 to automount and write log to the system journal.
@ -72,7 +69,7 @@ in
###### implementation ###### implementation
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
boot.kernelModules = [ "autofs" ]; boot.kernelModules = [ "autofs" ];
@ -90,7 +87,7 @@ in
serviceConfig = { serviceConfig = {
Type = "forking"; Type = "forking";
PIDFile = "/run/autofs.pid"; PIDFile = "/run/autofs.pid";
ExecStart = "${pkgs.autofs5}/bin/automount ${optionalString cfg.debug "-d"} -p /run/autofs.pid -t ${builtins.toString cfg.timeout} ${autoMaster}"; ExecStart = "${pkgs.autofs5}/bin/automount ${lib.optionalString cfg.debug "-d"} -p /run/autofs.pid -t ${builtins.toString cfg.timeout} ${autoMaster}";
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
}; };
}; };

View file

@ -1,42 +1,39 @@
{ config, pkgs, lib, ... }: { config, pkgs, lib, ... }:
with lib;
let let
cfg = config.services.bazarr; cfg = config.services.bazarr;
in in
{ {
options = { options = {
services.bazarr = { services.bazarr = {
enable = mkEnableOption "bazarr, a subtitle manager for Sonarr and Radarr"; enable = lib.mkEnableOption "bazarr, a subtitle manager for Sonarr and Radarr";
openFirewall = mkOption { openFirewall = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = "Open ports in the firewall for the bazarr web interface."; description = "Open ports in the firewall for the bazarr web interface.";
}; };
listenPort = mkOption { listenPort = lib.mkOption {
type = types.port; type = lib.types.port;
default = 6767; default = 6767;
description = "Port on which the bazarr web interface should listen"; description = "Port on which the bazarr web interface should listen";
}; };
user = mkOption { user = lib.mkOption {
type = types.str; type = lib.types.str;
default = "bazarr"; default = "bazarr";
description = "User account under which bazarr runs."; description = "User account under which bazarr runs.";
}; };
group = mkOption { group = lib.mkOption {
type = types.str; type = lib.types.str;
default = "bazarr"; default = "bazarr";
description = "Group under which bazarr runs."; description = "Group under which bazarr runs.";
}; };
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
systemd.services.bazarr = { systemd.services.bazarr = {
description = "bazarr"; description = "bazarr";
after = [ "network.target" ]; after = [ "network.target" ];
@ -58,11 +55,11 @@ in
}; };
}; };
networking.firewall = mkIf cfg.openFirewall { networking.firewall = lib.mkIf cfg.openFirewall {
allowedTCPPorts = [ cfg.listenPort ]; allowedTCPPorts = [ cfg.listenPort ];
}; };
users.users = mkIf (cfg.user == "bazarr") { users.users = lib.mkIf (cfg.user == "bazarr") {
bazarr = { bazarr = {
isSystemUser = true; isSystemUser = true;
group = cfg.group; group = cfg.group;
@ -70,7 +67,7 @@ in
}; };
}; };
users.groups = mkIf (cfg.group == "bazarr") { users.groups = lib.mkIf (cfg.group == "bazarr") {
bazarr = {}; bazarr = {};
}; };
}; };

View file

@ -4,13 +4,10 @@
pkgs, pkgs,
... ...
}: }:
with lib;
let let
cfg = config.services.bcg; cfg = config.services.bcg;
configFile = (pkgs.formats.yaml {}).generate "bcg.conf.yaml" ( configFile = (pkgs.formats.yaml {}).generate "bcg.conf.yaml" (
filterAttrsRecursive (n: v: v != null) { lib.filterAttrsRecursive (n: v: v != null) {
inherit (cfg) device name mqtt; inherit (cfg) device name mqtt;
retain_node_messages = cfg.retainNodeMessages; retain_node_messages = cfg.retainNodeMessages;
qos_node_messages = cfg.qosNodeMessages; qos_node_messages = cfg.qosNodeMessages;
@ -25,10 +22,10 @@ in
{ {
options = { options = {
services.bcg = { services.bcg = {
enable = mkEnableOption "BigClown gateway"; enable = lib.mkEnableOption "BigClown gateway";
package = mkPackageOption pkgs [ "python3Packages" "bcg" ] { }; package = lib.mkPackageOption pkgs [ "python3Packages" "bcg" ] { };
environmentFiles = mkOption { environmentFiles = lib.mkOption {
type = types.listOf types.path; type = lib.types.listOf lib.types.path;
default = []; default = [];
example = [ "/run/keys/bcg.env" ]; example = [ "/run/keys/bcg.env" ];
description = '' description = ''
@ -38,17 +35,17 @@ in
This is useful to avoid putting secrets into the nix store. This is useful to avoid putting secrets into the nix store.
''; '';
}; };
verbose = mkOption { verbose = lib.mkOption {
type = types.enum ["CRITICAL" "ERROR" "WARNING" "INFO" "DEBUG"]; type = lib.types.enum ["CRITICAL" "ERROR" "WARNING" "INFO" "DEBUG"];
default = "WARNING"; default = "WARNING";
description = "Verbosity level."; description = "Verbosity level.";
}; };
device = mkOption { device = lib.mkOption {
type = types.str; type = lib.types.str;
description = "Device name to configure gateway to use."; description = "Device name to configure gateway to use.";
}; };
name = mkOption { name = lib.mkOption {
type = with types; nullOr str; type = with lib.types; nullOr str;
default = null; default = null;
description = '' description = ''
Name for the device. Name for the device.
@ -61,86 +58,86 @@ in
''; '';
}; };
mqtt = { mqtt = {
host = mkOption { host = lib.mkOption {
type = types.str; type = lib.types.str;
default = "127.0.0.1"; default = "127.0.0.1";
description = "Host where MQTT server is running."; description = "Host where MQTT server is running.";
}; };
port = mkOption { port = lib.mkOption {
type = types.port; type = lib.types.port;
default = 1883; default = 1883;
description = "Port of MQTT server."; description = "Port of MQTT server.";
}; };
username = mkOption { username = lib.mkOption {
type = with types; nullOr str; type = with lib.types; nullOr str;
default = null; default = null;
description = "MQTT server access username."; description = "MQTT server access username.";
}; };
password = mkOption { password = lib.mkOption {
type = with types; nullOr str; type = with lib.types; nullOr str;
default = null; default = null;
description = "MQTT server access password."; description = "MQTT server access password.";
}; };
cafile = mkOption { cafile = lib.mkOption {
type = with types; nullOr str; type = with lib.types; nullOr str;
default = null; default = null;
description = "Certificate Authority file for MQTT server access."; description = "Certificate Authority file for MQTT server access.";
}; };
certfile = mkOption { certfile = lib.mkOption {
type = with types; nullOr str; type = with lib.types; nullOr str;
default = null; default = null;
description = "Certificate file for MQTT server access."; description = "Certificate file for MQTT server access.";
}; };
keyfile = mkOption { keyfile = lib.mkOption {
type = with types; nullOr str; type = with lib.types; nullOr str;
default = null; default = null;
description = "Key file for MQTT server access."; description = "Key file for MQTT server access.";
}; };
}; };
retainNodeMessages = mkOption { retainNodeMessages = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = "Specify that node messages should be retaied in MQTT broker."; description = "Specify that node messages should be retaied in MQTT broker.";
}; };
qosNodeMessages = mkOption { qosNodeMessages = lib.mkOption {
type = types.int; type = lib.types.int;
default = 1; default = 1;
description = "Set the guarantee of MQTT message delivery."; description = "Set the guarantee of MQTT message delivery.";
}; };
baseTopicPrefix = mkOption { baseTopicPrefix = lib.mkOption {
type = types.str; type = lib.types.str;
default = ""; default = "";
description = "Topic prefix added to all MQTT messages."; description = "Topic prefix added to all MQTT messages.";
}; };
automaticRemoveKitFromNames = mkOption { automaticRemoveKitFromNames = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = true; default = true;
description = "Automatically remove kits."; description = "Automatically remove kits.";
}; };
automaticRenameKitNodes = mkOption { automaticRenameKitNodes = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = true; default = true;
description = "Automatically rename kit's nodes."; description = "Automatically rename kit's nodes.";
}; };
automaticRenameGenericNodes = mkOption { automaticRenameGenericNodes = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = true; default = true;
description = "Automatically rename generic nodes."; description = "Automatically rename generic nodes.";
}; };
automaticRenameNodes = mkOption { automaticRenameNodes = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = true; default = true;
description = "Automatically rename all nodes."; description = "Automatically rename all nodes.";
}; };
rename = mkOption { rename = lib.mkOption {
type = with types; attrsOf str; type = with lib.types; attrsOf str;
default = {}; default = {};
description = "Rename nodes to different name."; description = "Rename nodes to different name.";
}; };
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
python3Packages.bcg python3Packages.bcg
python3Packages.bch python3Packages.bch
@ -156,7 +153,7 @@ in
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ] ++ lib.optional config.services.mosquitto.enable "mosquitto.service"; wants = [ "network-online.target" ] ++ lib.optional config.services.mosquitto.enable "mosquitto.service";
after = [ "network-online.target" ]; after = [ "network-online.target" ];
preStart = mkIf envConfig '' preStart = lib.mkIf envConfig ''
umask 077 umask 077
${pkgs.envsubst}/bin/envsubst -i "${configFile}" -o "${finalConfig}" ${pkgs.envsubst}/bin/envsubst -i "${configFile}" -o "${finalConfig}"
''; '';

View file

@ -1,7 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.beanstalkd; cfg = config.services.beanstalkd;
pkg = pkgs.beanstalkd; pkg = pkgs.beanstalkd;
@ -12,25 +9,25 @@ in
options = { options = {
services.beanstalkd = { services.beanstalkd = {
enable = mkEnableOption "the Beanstalk work queue"; enable = lib.mkEnableOption "the Beanstalk work queue";
listen = { listen = {
port = mkOption { port = lib.mkOption {
type = types.port; type = lib.types.port;
description = "TCP port that will be used to accept client connections."; description = "TCP port that will be used to accept client connections.";
default = 11300; default = 11300;
}; };
address = mkOption { address = lib.mkOption {
type = types.str; type = lib.types.str;
description = "IP address to listen on."; description = "IP address to listen on.";
default = "127.0.0.1"; default = "127.0.0.1";
example = "0.0.0.0"; example = "0.0.0.0";
}; };
}; };
openFirewall = mkOption { openFirewall = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = "Whether to open ports in the firewall for the server."; description = "Whether to open ports in the firewall for the server.";
}; };
@ -39,9 +36,9 @@ in
# implementation # implementation
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
networking.firewall = mkIf cfg.openFirewall { networking.firewall = lib.mkIf cfg.openFirewall {
allowedTCPPorts = [ cfg.listen.port ]; allowedTCPPorts = [ cfg.listen.port ];
}; };

View file

@ -1,15 +1,12 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.beesd; cfg = config.services.beesd;
logLevels = { emerg = 0; alert = 1; crit = 2; err = 3; warning = 4; notice = 5; info = 6; debug = 7; }; logLevels = { emerg = 0; alert = 1; crit = 2; err = 3; warning = 4; notice = 5; info = 6; debug = 7; };
fsOptions = with types; { fsOptions = with lib.types; {
options.spec = mkOption { options.spec = lib.mkOption {
type = str; type = str;
description = '' description = ''
Description of how to identify the filesystem to be duplicated by this Description of how to identify the filesystem to be duplicated by this
@ -25,8 +22,8 @@ let
''; '';
example = "LABEL=MyBulkDataDrive"; example = "LABEL=MyBulkDataDrive";
}; };
options.hashTableSizeMB = mkOption { options.hashTableSizeMB = lib.mkOption {
type = types.addCheck types.int (n: mod n 16 == 0); type = lib.types.addCheck lib.types.int (n: mod n 16 == 0);
default = 1024; # 1GB; default from upstream beesd script default = 1024; # 1GB; default from upstream beesd script
description = '' description = ''
Hash table size in MB; must be a multiple of 16. Hash table size in MB; must be a multiple of 16.
@ -40,13 +37,13 @@ let
will recognize only aligned duplicate blocks of 16KB. will recognize only aligned duplicate blocks of 16KB.
''; '';
}; };
options.verbosity = mkOption { options.verbosity = lib.mkOption {
type = types.enum (attrNames logLevels ++ attrValues logLevels); type = lib.types.enum (lib.attrNames logLevels ++ lib.attrValues logLevels);
apply = v: if isString v then logLevels.${v} else v; apply = v: if lib.isString v then logLevels.${v} else v;
default = "info"; default = "info";
description = "Log verbosity (syslog keyword/level)."; description = "Log verbosity (syslog keyword/level).";
}; };
options.workDir = mkOption { options.workDir = lib.mkOption {
type = str; type = str;
default = ".beeshome"; default = ".beeshome";
description = '' description = ''
@ -54,13 +51,13 @@ let
the hash table will be stored. the hash table will be stored.
''; '';
}; };
options.extraOptions = mkOption { options.extraOptions = lib.mkOption {
type = listOf str; type = listOf str;
default = [ ]; default = [ ];
description = '' description = ''
Extra command-line options passed to the daemon. See upstream bees documentation. Extra command-line options passed to the daemon. See upstream bees documentation.
''; '';
example = literalExpression '' example = lib.literalExpression ''
[ "--thread-count" "4" ] [ "--thread-count" "4" ]
''; '';
}; };
@ -70,11 +67,11 @@ in
{ {
options.services.beesd = { options.services.beesd = {
filesystems = mkOption { filesystems = lib.mkOption {
type = with types; attrsOf (submodule fsOptions); type = with lib.types; attrsOf (submodule fsOptions);
description = "BTRFS filesystems to run block-level deduplication on."; description = "BTRFS filesystems to run block-level deduplication on.";
default = { }; default = { };
example = literalExpression '' example = lib.literalExpression ''
{ {
root = { root = {
spec = "LABEL=root"; spec = "LABEL=root";
@ -87,8 +84,8 @@ in
}; };
}; };
config = { config = {
systemd.services = mapAttrs' systemd.services = lib.mapAttrs'
(name: fs: nameValuePair "beesd@${name}" { (name: fs: lib.nameValuePair "beesd@${name}" {
description = "Block-level BTRFS deduplication for %i"; description = "Block-level BTRFS deduplication for %i";
after = [ "sysinit.target" ]; after = [ "sysinit.target" ];
@ -100,11 +97,11 @@ in
"idxSizeMB=${toString fs.hashTableSizeMB}" "idxSizeMB=${toString fs.hashTableSizeMB}"
"workDir=${fs.workDir}" "workDir=${fs.workDir}"
]; ];
configOptsStr = escapeShellArgs configOpts; configOptsStr = lib.escapeShellArgs configOpts;
in in
{ {
# Values from https://github.com/Zygo/bees/blob/v0.6.5/scripts/beesd@.service.in # Values from https://github.com/Zygo/bees/blob/v0.6.5/scripts/beesd@.service.in
ExecStart = "${pkgs.bees}/bin/bees-service-wrapper run ${configOptsStr} -- --no-timestamps ${escapeShellArgs fs.extraOptions}"; ExecStart = "${pkgs.bees}/bin/bees-service-wrapper run ${configOptsStr} -- --no-timestamps ${lib.escapeShellArgs fs.extraOptions}";
ExecStopPost = "${pkgs.bees}/bin/bees-service-wrapper cleanup ${configOptsStr}"; ExecStopPost = "${pkgs.bees}/bin/bees-service-wrapper cleanup ${configOptsStr}";
CPUAccounting = true; CPUAccounting = true;
CPUSchedulingPolicy = "batch"; CPUSchedulingPolicy = "batch";

View file

@ -1,6 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
gunicorn = pkgs.python3Packages.gunicorn; gunicorn = pkgs.python3Packages.gunicorn;
bepasty = pkgs.bepasty; bepasty = pkgs.bepasty;
@ -13,20 +11,20 @@ let
in in
{ {
options.services.bepasty = { options.services.bepasty = {
enable = mkEnableOption "bepasty, a binary pastebin server"; enable = lib.mkEnableOption "bepasty, a binary pastebin server";
servers = mkOption { servers = lib.mkOption {
default = {}; default = {};
description = '' description = ''
configure a number of bepasty servers which will be started with configure a number of bepasty servers which will be started with
gunicorn. gunicorn.
''; '';
type = with types ; attrsOf (submodule ({ config, ... } : { type = with lib.types ; attrsOf (submodule ({ config, ... } : {
options = { options = {
bind = mkOption { bind = lib.mkOption {
type = types.str; type = lib.types.str;
description = '' description = ''
Bind address to be used for this server. Bind address to be used for this server.
''; '';
@ -34,16 +32,16 @@ in
default = "127.0.0.1:8000"; default = "127.0.0.1:8000";
}; };
dataDir = mkOption { dataDir = lib.mkOption {
type = types.str; type = lib.types.str;
description = '' description = ''
Path to the directory where the pastes will be saved to Path to the directory where the pastes will be saved to
''; '';
default = default_home+"/data"; default = default_home+"/data";
}; };
defaultPermissions = mkOption { defaultPermissions = lib.mkOption {
type = types.str; type = lib.types.str;
description = '' description = ''
default permissions for all unauthenticated accesses. default permissions for all unauthenticated accesses.
''; '';
@ -51,8 +49,8 @@ in
default = "read"; default = "read";
}; };
extraConfig = mkOption { extraConfig = lib.mkOption {
type = types.lines; type = lib.types.lines;
description = '' description = ''
Extra configuration for bepasty server to be appended on the Extra configuration for bepasty server to be appended on the
configuration. configuration.
@ -68,8 +66,8 @@ in
''; '';
}; };
secretKey = mkOption { secretKey = lib.mkOption {
type = types.str; type = lib.types.str;
description = '' description = ''
server secret for safe session cookies, must be set. server secret for safe session cookies, must be set.
@ -81,8 +79,8 @@ in
default = ""; default = "";
}; };
secretKeyFile = mkOption { secretKeyFile = lib.mkOption {
type = types.nullOr types.str; type = lib.types.nullOr lib.types.str;
default = null; default = null;
description = '' description = ''
A file that contains the server secret for safe session cookies, must be set. A file that contains the server secret for safe session cookies, must be set.
@ -94,8 +92,8 @@ in
''; '';
}; };
workDir = mkOption { workDir = lib.mkOption {
type = types.str; type = lib.types.str;
description = '' description = ''
Path to the working directory (used for config and pidfile). Path to the working directory (used for config and pidfile).
Defaults to the users home directory. Defaults to the users home directory.
@ -105,7 +103,7 @@ in
}; };
config = { config = {
secretKeyFile = mkDefault ( secretKeyFile = lib.mkDefault (
if config.secretKey != "" if config.secretKey != ""
then toString (pkgs.writeTextFile { then toString (pkgs.writeTextFile {
name = "bepasty-secret-key"; name = "bepasty-secret-key";
@ -118,13 +116,13 @@ in
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
environment.systemPackages = [ bepasty ]; environment.systemPackages = [ bepasty ];
# creates gunicorn systemd service for each configured server # creates gunicorn systemd service for each configured server
systemd.services = mapAttrs' (name: server: systemd.services = lib.mapAttrs' (name: server:
nameValuePair ("bepasty-server-${name}-gunicorn") lib.nameValuePair ("bepasty-server-${name}-gunicorn")
({ ({
description = "Bepasty Server ${name}"; description = "Bepasty Server ${name}";
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];

View file

@ -1,7 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.calibre-server; cfg = config.services.calibre-server;
@ -9,21 +6,21 @@ let
documentationLink = "https://manual.calibre-ebook.com"; documentationLink = "https://manual.calibre-ebook.com";
generatedDocumentationLink = documentationLink + "/generated/en/calibre-server.html"; generatedDocumentationLink = documentationLink + "/generated/en/calibre-server.html";
execFlags = (concatStringsSep " " execFlags = (lib.concatStringsSep " "
(mapAttrsToList (k: v: "${k} ${toString v}") (filterAttrs (name: value: value != null) { (lib.mapAttrsToList (k: v: "${k} ${toString v}") (lib.filterAttrs (name: value: value != null) {
"--listen-on" = cfg.host; "--listen-on" = cfg.host;
"--port" = cfg.port; "--port" = cfg.port;
"--auth-mode" = cfg.auth.mode; "--auth-mode" = cfg.auth.mode;
"--userdb" = cfg.auth.userDb; "--userdb" = cfg.auth.userDb;
}) ++ [(optionalString (cfg.auth.enable == true) "--enable-auth")]) }) ++ [(lib.optionalString (cfg.auth.enable == true) "--enable-auth")])
); );
in in
{ {
imports = [ imports = [
(mkChangedOptionModule [ "services" "calibre-server" "libraryDir" ] [ "services" "calibre-server" "libraries" ] (lib.mkChangedOptionModule [ "services" "calibre-server" "libraryDir" ] [ "services" "calibre-server" "libraries" ]
(config: (config:
let libraryDir = getAttrFromPath [ "services" "calibre-server" "libraryDir" ] config; let libraryDir = lib.getAttrFromPath [ "services" "calibre-server" "libraryDir" ] config;
in [ libraryDir ] in [ libraryDir ]
) )
) )
@ -32,11 +29,11 @@ in
options = { options = {
services.calibre-server = { services.calibre-server = {
enable = mkEnableOption "calibre-server (e-book software)"; enable = lib.mkEnableOption "calibre-server (e-book software)";
package = lib.mkPackageOption pkgs "calibre" { }; package = lib.mkPackageOption pkgs "calibre" { };
libraries = mkOption { libraries = lib.mkOption {
type = types.listOf types.path; type = lib.types.listOf lib.types.path;
default = [ "/var/lib/calibre-server" ]; default = [ "/var/lib/calibre-server" ];
description = '' description = ''
Make sure each library path is initialized before service startup. Make sure each library path is initialized before service startup.
@ -45,20 +42,20 @@ in
''; '';
}; };
user = mkOption { user = lib.mkOption {
type = types.str; type = lib.types.str;
default = "calibre-server"; default = "calibre-server";
description = "The user under which calibre-server runs."; description = "The user under which calibre-server runs.";
}; };
group = mkOption { group = lib.mkOption {
type = types.str; type = lib.types.str;
default = "calibre-server"; default = "calibre-server";
description = "The group under which calibre-server runs."; description = "The group under which calibre-server runs.";
}; };
host = mkOption { host = lib.mkOption {
type = types.str; type = lib.types.str;
default = "0.0.0.0"; default = "0.0.0.0";
example = "::1"; example = "::1";
description = '' description = ''
@ -67,9 +64,9 @@ in
''; '';
}; };
port = mkOption { port = lib.mkOption {
default = 8080; default = 8080;
type = types.port; type = lib.types.port;
description = '' description = ''
The port on which to listen for connections. The port on which to listen for connections.
See the [calibre-server documentation](${generatedDocumentationLink}#cmdoption-calibre-server-port) for details. See the [calibre-server documentation](${generatedDocumentationLink}#cmdoption-calibre-server-port) for details.
@ -77,8 +74,8 @@ in
}; };
auth = { auth = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Password based authentication to access the server. Password based authentication to access the server.
@ -86,8 +83,8 @@ in
''; '';
}; };
mode = mkOption { mode = lib.mkOption {
type = types.enum [ "auto" "basic" "digest" ]; type = lib.types.enum [ "auto" "basic" "digest" ];
default = "auto"; default = "auto";
description = '' description = ''
Choose the type of authentication used. Choose the type of authentication used.
@ -96,9 +93,9 @@ in
''; '';
}; };
userDb = mkOption { userDb = lib.mkOption {
default = null; default = null;
type = types.nullOr types.path; type = lib.types.nullOr lib.types.path;
description = '' description = ''
Choose users database file to use for authentication. Choose users database file to use for authentication.
Make sure users database file is initialized before service startup. Make sure users database file is initialized before service startup.
@ -109,7 +106,7 @@ in
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
systemd.services.calibre-server = { systemd.services.calibre-server = {
description = "Calibre Server"; description = "Calibre Server";
@ -125,7 +122,7 @@ in
environment.systemPackages = [ pkgs.calibre ]; environment.systemPackages = [ pkgs.calibre ];
users.users = optionalAttrs (cfg.user == "calibre-server") { users.users = lib.optionalAttrs (cfg.user == "calibre-server") {
calibre-server = { calibre-server = {
home = "/var/lib/calibre-server"; home = "/var/lib/calibre-server";
createHome = true; createHome = true;
@ -134,7 +131,7 @@ in
}; };
}; };
users.groups = optionalAttrs (cfg.group == "calibre-server") { users.groups = lib.optionalAttrs (cfg.group == "calibre-server") {
calibre-server = { calibre-server = {
gid = config.ids.gids.calibre-server; gid = config.ids.gids.calibre-server;
}; };

View file

@ -1,7 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.canto-daemon; cfg = config.services.canto-daemon;
@ -13,8 +10,8 @@ in {
options = { options = {
services.canto-daemon = { services.canto-daemon = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = "Whether to enable the canto RSS daemon."; description = "Whether to enable the canto RSS daemon.";
}; };
@ -24,7 +21,7 @@ in {
##### implementation ##### implementation
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
systemd.user.services.canto-daemon = { systemd.user.services.canto-daemon = {
description = "Canto RSS Daemon"; description = "Canto RSS Daemon";

View file

@ -1,50 +1,47 @@
{ config, pkgs, lib, ... }: { config, pkgs, lib, ... }:
with lib;
let let
cfg = config.services.cfdyndns; cfg = config.services.cfdyndns;
in in
{ {
imports = [ imports = [
(mkRemovedOptionModule (lib.mkRemovedOptionModule
[ "services" "cfdyndns" "apikey" ] [ "services" "cfdyndns" "apikey" ]
"Use services.cfdyndns.apikeyFile instead.") "Use services.cfdyndns.apikeyFile instead.")
]; ];
options = { options = {
services.cfdyndns = { services.cfdyndns = {
enable = mkEnableOption "Cloudflare Dynamic DNS Client"; enable = lib.mkEnableOption "Cloudflare Dynamic DNS Client";
email = mkOption { email = lib.mkOption {
type = types.str; type = lib.types.str;
description = '' description = ''
The email address to use to authenticate to CloudFlare. The email address to use to authenticate to CloudFlare.
''; '';
}; };
apiTokenFile = mkOption { apiTokenFile = lib.mkOption {
default = null; default = null;
type = types.nullOr types.str; type = lib.types.nullOr lib.types.str;
description = '' description = ''
The path to a file containing the API Token The path to a file containing the API Token
used to authenticate with CloudFlare. used to authenticate with CloudFlare.
''; '';
}; };
apikeyFile = mkOption { apikeyFile = lib.mkOption {
default = null; default = null;
type = types.nullOr types.str; type = lib.types.nullOr lib.types.str;
description = '' description = ''
The path to a file containing the API Key The path to a file containing the API Key
used to authenticate with CloudFlare. used to authenticate with CloudFlare.
''; '';
}; };
records = mkOption { records = lib.mkOption {
default = []; default = [];
example = [ "host.tld" ]; example = [ "host.tld" ];
type = types.listOf types.str; type = lib.types.listOf lib.types.str;
description = '' description = ''
The records to update in CloudFlare. The records to update in CloudFlare.
''; '';
@ -52,7 +49,7 @@ in
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
systemd.services.cfdyndns = { systemd.services.cfdyndns = {
description = "CloudFlare Dynamic DNS Client"; description = "CloudFlare Dynamic DNS Client";
after = [ "network.target" ]; after = [ "network.target" ];
@ -64,14 +61,14 @@ in
DynamicUser = true; DynamicUser = true;
}; };
environment = { environment = {
CLOUDFLARE_RECORDS="${concatStringsSep "," cfg.records}"; CLOUDFLARE_RECORDS="${lib.concatStringsSep "," cfg.records}";
}; };
script = '' script = ''
${optionalString (cfg.apikeyFile != null) '' ${lib.optionalString (cfg.apikeyFile != null) ''
export CLOUDFLARE_APIKEY="$(cat ${escapeShellArg cfg.apikeyFile})" export CLOUDFLARE_APIKEY="$(cat ${lib.escapeShellArg cfg.apikeyFile})"
export CLOUDFLARE_EMAIL="${cfg.email}" export CLOUDFLARE_EMAIL="${cfg.email}"
''} ''}
${optionalString (cfg.apiTokenFile != null) '' ${lib.optionalString (cfg.apiTokenFile != null) ''
export CLOUDFLARE_APITOKEN=$(${pkgs.systemd}/bin/systemd-creds cat CLOUDFLARE_APITOKEN_FILE) export CLOUDFLARE_APITOKEN=$(${pkgs.systemd}/bin/systemd-creds cat CLOUDFLARE_APITOKEN_FILE)
''} ''}
${pkgs.cfdyndns}/bin/cfdyndns ${pkgs.cfdyndns}/bin/cfdyndns

View file

@ -1,25 +1,22 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.cgminer; cfg = config.services.cgminer;
convType = with builtins; convType = with builtins;
v: if isBool v then boolToString v else toString v; v: if lib.isBool v then lib.boolToString v else toString v;
mergedHwConfig = mergedHwConfig =
mapAttrsToList (n: v: ''"${n}": "${(concatStringsSep "," (map convType v))}"'') lib.mapAttrsToList (n: v: ''"${n}": "${(lib.concatStringsSep "," (map convType v))}"'')
(foldAttrs (n: a: [n] ++ a) [] cfg.hardware); (lib.foldAttrs (n: a: [n] ++ a) [] cfg.hardware);
mergedConfig = with builtins; mergedConfig = with builtins;
mapAttrsToList (n: v: ''"${n}": ${if isBool v then convType v else ''"${convType v}"''}'') lib.mapAttrsToList (n: v: ''"${n}": ${if lib.isBool v then convType v else ''"${convType v}"''}'')
cfg.config; cfg.config;
cgminerConfig = pkgs.writeText "cgminer.conf" '' cgminerConfig = pkgs.writeText "cgminer.conf" ''
{ {
${concatStringsSep ",\n" mergedHwConfig}, ${lib.concatStringsSep ",\n" mergedHwConfig},
${concatStringsSep ",\n" mergedConfig}, ${lib.concatStringsSep ",\n" mergedConfig},
"pools": [ "pools": [
${concatStringsSep ",\n" ${lib.concatStringsSep ",\n"
(map (v: ''{"url": "${v.url}", "user": "${v.user}", "pass": "${v.pass}"}'') (map (v: ''{"url": "${v.url}", "user": "${v.user}", "pass": "${v.pass}"}'')
cfg.pools)}] cfg.pools)}]
} }
@ -31,19 +28,19 @@ in
services.cgminer = { services.cgminer = {
enable = mkEnableOption "cgminer, an ASIC/FPGA/GPU miner for bitcoin and litecoin"; enable = lib.mkEnableOption "cgminer, an ASIC/FPGA/GPU miner for bitcoin and litecoin";
package = mkPackageOption pkgs "cgminer" { }; package = lib.mkPackageOption pkgs "cgminer" { };
user = mkOption { user = lib.mkOption {
type = types.str; type = lib.types.str;
default = "cgminer"; default = "cgminer";
description = "User account under which cgminer runs"; description = "User account under which cgminer runs";
}; };
pools = mkOption { pools = lib.mkOption {
default = []; # Run benchmark default = []; # Run benchmark
type = types.listOf (types.attrsOf types.str); type = lib.types.listOf (lib.types.attrsOf lib.types.str);
description = "List of pools where to mine"; description = "List of pools where to mine";
example = [{ example = [{
url = "http://p2pool.org:9332"; url = "http://p2pool.org:9332";
@ -52,9 +49,9 @@ in
}]; }];
}; };
hardware = mkOption { hardware = lib.mkOption {
default = []; # Run without options default = []; # Run without options
type = types.listOf (types.attrsOf (types.either types.str types.int)); type = lib.types.listOf (lib.types.attrsOf (lib.types.either lib.types.str lib.types.int));
description= "List of config options for every GPU"; description= "List of config options for every GPU";
example = [ example = [
{ {
@ -79,9 +76,9 @@ in
}]; }];
}; };
config = mkOption { config = lib.mkOption {
default = {}; default = {};
type = types.attrsOf (types.either types.bool types.int); type = lib.types.attrsOf (lib.types.either lib.types.bool lib.types.int);
description = "Additional config"; description = "Additional config";
example = { example = {
auto-fan = true; auto-fan = true;
@ -101,16 +98,16 @@ in
###### implementation ###### implementation
config = mkIf config.services.cgminer.enable { config = lib.mkIf config.services.cgminer.enable {
users.users = optionalAttrs (cfg.user == "cgminer") { users.users = lib.optionalAttrs (cfg.user == "cgminer") {
cgminer = { cgminer = {
isSystemUser = true; isSystemUser = true;
group = "cgminer"; group = "cgminer";
description = "Cgminer user"; description = "Cgminer user";
}; };
}; };
users.groups = optionalAttrs (cfg.user == "cgminer") { users.groups = lib.optionalAttrs (cfg.user == "cgminer") {
cgminer = {}; cgminer = {};
}; };

View file

@ -1,18 +1,15 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.clipcat; cfg = config.services.clipcat;
in { in {
options.services.clipcat= { options.services.clipcat= {
enable = mkEnableOption "Clipcat clipboard daemon"; enable = lib.mkEnableOption "Clipcat clipboard daemon";
package = mkPackageOption pkgs "clipcat" { }; package = lib.mkPackageOption pkgs "clipcat" { };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
systemd.user.services.clipcat = { systemd.user.services.clipcat = {
enable = true; enable = true;
description = "clipcat daemon"; description = "clipcat daemon";

View file

@ -1,18 +1,15 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.clipmenu; cfg = config.services.clipmenu;
in { in {
options.services.clipmenu = { options.services.clipmenu = {
enable = mkEnableOption "clipmenu, the clipboard management daemon"; enable = lib.mkEnableOption "clipmenu, the clipboard management daemon";
package = mkPackageOption pkgs "clipmenu" { }; package = lib.mkPackageOption pkgs "clipmenu" { };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
systemd.user.services.clipmenu = { systemd.user.services.clipmenu = {
enable = true; enable = true;
description = "Clipboard management daemon"; description = "Clipboard management daemon";

View file

@ -1,7 +1,4 @@
{ config, pkgs, lib, ... }: { config, pkgs, lib, ... }:
with lib;
let let
cfg = config.services.confd; cfg = config.services.confd;
@ -9,62 +6,62 @@ let
backend = "${cfg.backend}" backend = "${cfg.backend}"
confdir = "${cfg.confDir}" confdir = "${cfg.confDir}"
interval = ${toString cfg.interval} interval = ${toString cfg.interval}
nodes = [ ${concatMapStringsSep "," (s: ''"${s}"'') cfg.nodes}, ] nodes = [ ${lib.concatMapStringsSep "," (s: ''"${s}"'') cfg.nodes}, ]
prefix = "${cfg.prefix}" prefix = "${cfg.prefix}"
log-level = "${cfg.logLevel}" log-level = "${cfg.logLevel}"
watch = ${boolToString cfg.watch} watch = ${lib.boolToString cfg.watch}
''; '';
in { in {
options.services.confd = { options.services.confd = {
enable = mkEnableOption "confd, a service to manage local application configuration files using templates and data from etcd/consul/redis/zookeeper"; enable = lib.mkEnableOption "confd, a service to manage local application configuration files using templates and data from etcd/consul/redis/zookeeper";
backend = mkOption { backend = lib.mkOption {
description = "Confd config storage backend to use."; description = "Confd config storage backend to use.";
default = "etcd"; default = "etcd";
type = types.enum ["etcd" "consul" "redis" "zookeeper"]; type = lib.types.enum ["etcd" "consul" "redis" "zookeeper"];
}; };
interval = mkOption { interval = lib.mkOption {
description = "Confd check interval."; description = "Confd check interval.";
default = 10; default = 10;
type = types.int; type = lib.types.int;
}; };
nodes = mkOption { nodes = lib.mkOption {
description = "Confd list of nodes to connect to."; description = "Confd list of nodes to connect to.";
default = [ "http://127.0.0.1:2379" ]; default = [ "http://127.0.0.1:2379" ];
type = types.listOf types.str; type = lib.types.listOf lib.types.str;
}; };
watch = mkOption { watch = lib.mkOption {
description = "Confd, whether to watch etcd config for changes."; description = "Confd, whether to watch etcd config for changes.";
default = true; default = true;
type = types.bool; type = lib.types.bool;
}; };
prefix = mkOption { prefix = lib.mkOption {
description = "The string to prefix to keys."; description = "The string to prefix to keys.";
default = "/"; default = "/";
type = types.path; type = lib.types.path;
}; };
logLevel = mkOption { logLevel = lib.mkOption {
description = "Confd log level."; description = "Confd log level.";
default = "info"; default = "info";
type = types.enum ["info" "debug"]; type = lib.types.enum ["info" "debug"];
}; };
confDir = mkOption { confDir = lib.mkOption {
description = "The path to the confd configs."; description = "The path to the confd configs.";
default = "/etc/confd"; default = "/etc/confd";
type = types.path; type = lib.types.path;
}; };
package = mkPackageOption pkgs "confd" { }; package = lib.mkPackageOption pkgs "confd" { };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
systemd.services.confd = { systemd.services.confd = {
description = "Confd Service."; description = "Confd Service.";
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
@ -80,6 +77,6 @@ in {
environment.systemPackages = [ cfg.package ]; environment.systemPackages = [ cfg.package ];
services.etcd.enable = mkIf (cfg.backend == "etcd") (mkDefault true); services.etcd.enable = lib.mkIf (cfg.backend == "etcd") (lib.mkDefault true);
}; };
} }

View file

@ -1,7 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.cpuminer-cryptonight; cfg = config.services.cpuminer-cryptonight;
@ -20,28 +17,28 @@ in
options = { options = {
services.cpuminer-cryptonight = { services.cpuminer-cryptonight = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Whether to enable the cpuminer cryptonight miner. Whether to enable the cpuminer cryptonight miner.
''; '';
}; };
url = mkOption { url = lib.mkOption {
type = types.str; type = lib.types.str;
description = "URL of mining server"; description = "URL of mining server";
}; };
user = mkOption { user = lib.mkOption {
type = types.str; type = lib.types.str;
description = "Username for mining server"; description = "Username for mining server";
}; };
pass = mkOption { pass = lib.mkOption {
type = types.str; type = lib.types.str;
default = "x"; default = "x";
description = "Password for mining server"; description = "Password for mining server";
}; };
threads = mkOption { threads = lib.mkOption {
type = types.int; type = lib.types.int;
default = 0; default = 0;
description = "Number of miner threads, defaults to available processors"; description = "Number of miner threads, defaults to available processors";
}; };
@ -49,7 +46,7 @@ in
}; };
config = mkIf config.services.cpuminer-cryptonight.enable { config = lib.mkIf config.services.cpuminer-cryptonight.enable {
systemd.services.cpuminer-cryptonight = { systemd.services.cpuminer-cryptonight = {
description = "Cryptonight cpuminer"; description = "Cryptonight cpuminer";

View file

@ -1,18 +1,15 @@
{ pkgs, config, lib, ... }: { pkgs, config, lib, ... }:
with lib;
let let
cfg = config.services.devmon; cfg = config.services.devmon;
in { in {
options = { options = {
services.devmon = { services.devmon = {
enable = mkEnableOption "devmon, an automatic device mounting daemon"; enable = lib.mkEnableOption "devmon, an automatic device mounting daemon";
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
systemd.user.services.devmon = { systemd.user.services.devmon = {
description = "devmon automatic device mounting daemon"; description = "devmon automatic device mounting daemon";
wantedBy = [ "default.target" ]; wantedBy = [ "default.target" ];

View file

@ -4,7 +4,6 @@
config, config,
... ...
}: }:
with lib;
let let
cfg = config.services.devpi-server; cfg = config.services.devpi-server;
@ -17,17 +16,17 @@ let
in in
{ {
options.services.devpi-server = { options.services.devpi-server = {
enable = mkEnableOption "Devpi Server"; enable = lib.mkEnableOption "Devpi Server";
package = mkPackageOption pkgs "devpi-server" { }; package = lib.mkPackageOption pkgs "devpi-server" { };
primaryUrl = mkOption { primaryUrl = lib.mkOption {
type = types.str; type = lib.types.str;
description = "Url for the primary node. Required option for replica nodes."; description = "Url for the primary node. Required option for replica nodes.";
}; };
replica = mkOption { replica = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Run node as a replica. Run node as a replica.
@ -35,8 +34,8 @@ in
''; '';
}; };
secretFile = mkOption { secretFile = lib.mkOption {
type = types.nullOr types.path; type = lib.types.nullOr lib.types.path;
default = null; default = null;
description = '' description = ''
Path to a shared secret file used for synchronization, Path to a shared secret file used for synchronization,
@ -44,24 +43,24 @@ in
''; '';
}; };
host = mkOption { host = lib.mkOption {
type = types.str; type = lib.types.str;
default = "localhost"; default = "localhost";
description = '' description = ''
domain/ip address to listen on domain/ip address to listen on
''; '';
}; };
port = mkOption { port = lib.mkOption {
type = types.port; type = lib.types.port;
default = 3141; default = 3141;
description = "The port on which Devpi Server will listen."; description = "The port on which Devpi Server will listen.";
}; };
openFirewall = mkEnableOption "opening the default ports in the firewall for Devpi Server"; openFirewall = lib.mkEnableOption "opening the default ports in the firewall for Devpi Server";
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
systemd.services.devpi-server = { systemd.services.devpi-server = {
enable = true; enable = true;
@ -74,7 +73,7 @@ in
# have 0600 permissions. # have 0600 permissions.
preStart = preStart =
'' ''
${optionalString (!isNull cfg.secretFile) ${lib.optionalString (!isNull cfg.secretFile)
"install -Dm 0600 \${CREDENTIALS_DIRECTORY}/devpi-secret ${runtimeDir}/${secretsFileName}" "install -Dm 0600 \${CREDENTIALS_DIRECTORY}/devpi-secret ${runtimeDir}/${secretsFileName}"
} }
@ -83,7 +82,7 @@ in
exit 0 exit 0
fi fi
${cfg.package}/bin/devpi-init --serverdir ${serverDir} '' ${cfg.package}/bin/devpi-init --serverdir ${serverDir} ''
+ strings.optionalString cfg.replica "--role=replica --master-url=${cfg.primaryUrl}"; + lib.optionalString cfg.replica "--role=replica --master-url=${cfg.primaryUrl}";
serviceConfig = { serviceConfig = {
LoadCredential = lib.mkIf (! isNull cfg.secretFile) [ LoadCredential = lib.mkIf (! isNull cfg.secretFile) [
@ -112,7 +111,7 @@ in
[ "--role=master" ] [ "--role=master" ]
); );
in in
"${cfg.package}/bin/devpi-server ${concatStringsSep " " args}"; "${cfg.package}/bin/devpi-server ${lib.concatStringsSep " " args}";
DynamicUser = true; DynamicUser = true;
StateDirectory = stateDirName; StateDirectory = stateDirName;
RuntimeDirectory = stateDirName; RuntimeDirectory = stateDirName;
@ -123,10 +122,10 @@ in
}; };
}; };
networking.firewall = mkIf cfg.openFirewall { networking.firewall = lib.mkIf cfg.openFirewall {
allowedTCPPorts = [ cfg.port ]; allowedTCPPorts = [ cfg.port ];
}; };
meta.maintainers = [ cafkafk ]; meta.maintainers = [ lib.maintainers.cafkafk ];
}; };
} }

View file

@ -1,7 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.dictd; cfg = config.services.dictd;
in in
@ -14,19 +11,19 @@ in
services.dictd = { services.dictd = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Whether to enable the DICT.org dictionary server. Whether to enable the DICT.org dictionary server.
''; '';
}; };
DBs = mkOption { DBs = lib.mkOption {
type = types.listOf types.package; type = lib.types.listOf lib.types.package;
default = with pkgs.dictdDBs; [ wiktionary wordnet ]; default = with pkgs.dictdDBs; [ wiktionary wordnet ];
defaultText = literalExpression "with pkgs.dictdDBs; [ wiktionary wordnet ]"; defaultText = lib.literalExpression "with pkgs.dictdDBs; [ wiktionary wordnet ]";
example = literalExpression "[ pkgs.dictdDBs.nld2eng ]"; example = lib.literalExpression "[ pkgs.dictdDBs.nld2eng ]";
description = "List of databases to make available."; description = "List of databases to make available.";
}; };
@ -40,7 +37,7 @@ in
config = let dictdb = pkgs.dictDBCollector { dictlist = map (x: { config = let dictdb = pkgs.dictDBCollector { dictlist = map (x: {
name = x.name; name = x.name;
filename = x; } ) cfg.DBs; }; filename = x; } ) cfg.DBs; };
in mkIf cfg.enable { in lib.mkIf cfg.enable {
# get the command line client on system path to make some use of the service # get the command line client on system path to make some use of the service
environment.systemPackages = [ pkgs.dict ]; environment.systemPackages = [ pkgs.dict ];

View file

@ -1,8 +1,5 @@
# Disnix server # Disnix server
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.disnix; cfg = config.services.disnix;
@ -17,22 +14,22 @@ in
services.disnix = { services.disnix = {
enable = mkEnableOption "Disnix"; enable = lib.mkEnableOption "Disnix";
enableMultiUser = mkOption { enableMultiUser = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = true; default = true;
description = "Whether to support multi-user mode by enabling the Disnix D-Bus service"; description = "Whether to support multi-user mode by enabling the Disnix D-Bus service";
}; };
useWebServiceInterface = mkEnableOption "the DisnixWebService interface running on Apache Tomcat"; useWebServiceInterface = lib.mkEnableOption "the DisnixWebService interface running on Apache Tomcat";
package = mkPackageOption pkgs "disnix" {}; package = lib.mkPackageOption pkgs "disnix" {};
enableProfilePath = mkEnableOption "exposing the Disnix profiles in the system's PATH"; enableProfilePath = lib.mkEnableOption "exposing the Disnix profiles in the system's PATH";
profiles = mkOption { profiles = lib.mkOption {
type = types.listOf types.str; type = lib.types.listOf lib.types.str;
default = [ "default" ]; default = [ "default" ];
description = "Names of the Disnix profiles to expose in the system's PATH"; description = "Names of the Disnix profiles to expose in the system's PATH";
}; };
@ -42,10 +39,10 @@ in
###### implementation ###### implementation
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
dysnomia.enable = true; dysnomia.enable = true;
environment.systemPackages = [ pkgs.disnix ] ++ optional cfg.useWebServiceInterface pkgs.DisnixWebService; environment.systemPackages = [ pkgs.disnix ] ++ lib.optional cfg.useWebServiceInterface pkgs.DisnixWebService;
environment.variables.PATH = lib.optionals cfg.enableProfilePath (map (profileName: "/nix/var/nix/profiles/disnix/${profileName}/bin" ) cfg.profiles); environment.variables.PATH = lib.optionals cfg.enableProfilePath (map (profileName: "/nix/var/nix/profiles/disnix/${profileName}/bin" ) cfg.profiles);
environment.variables.DISNIX_REMOTE_CLIENT = lib.optionalString (cfg.enableMultiUser) "disnix-client"; environment.variables.DISNIX_REMOTE_CLIENT = lib.optionalString (cfg.enableMultiUser) "disnix-client";
@ -54,26 +51,26 @@ in
services.tomcat.enable = cfg.useWebServiceInterface; services.tomcat.enable = cfg.useWebServiceInterface;
services.tomcat.extraGroups = [ "disnix" ]; services.tomcat.extraGroups = [ "disnix" ];
services.tomcat.javaOpts = "${optionalString cfg.useWebServiceInterface "-Djava.library.path=${pkgs.libmatthew_java}/lib/jni"} "; services.tomcat.javaOpts = "${lib.optionalString cfg.useWebServiceInterface "-Djava.library.path=${pkgs.libmatthew_java}/lib/jni"} ";
services.tomcat.sharedLibs = optional cfg.useWebServiceInterface "${pkgs.DisnixWebService}/share/java/DisnixConnection.jar" services.tomcat.sharedLibs = lib.optional cfg.useWebServiceInterface "${pkgs.DisnixWebService}/share/java/DisnixConnection.jar"
++ optional cfg.useWebServiceInterface "${pkgs.dbus_java}/share/java/dbus.jar"; ++ lib.optional cfg.useWebServiceInterface "${pkgs.dbus_java}/share/java/dbus.jar";
services.tomcat.webapps = optional cfg.useWebServiceInterface pkgs.DisnixWebService; services.tomcat.webapps = lib.optional cfg.useWebServiceInterface pkgs.DisnixWebService;
users.groups.disnix.gid = config.ids.gids.disnix; users.groups.disnix.gid = config.ids.gids.disnix;
systemd.services = { systemd.services = {
disnix = mkIf cfg.enableMultiUser { disnix = lib.mkIf cfg.enableMultiUser {
description = "Disnix server"; description = "Disnix server";
wants = [ "dysnomia.target" ]; wants = [ "dysnomia.target" ];
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
after = [ "dbus.service" ] after = [ "dbus.service" ]
++ optional config.services.httpd.enable "httpd.service" ++ lib.optional config.services.httpd.enable "httpd.service"
++ optional config.services.mysql.enable "mysql.service" ++ lib.optional config.services.mysql.enable "mysql.service"
++ optional config.services.postgresql.enable "postgresql.service" ++ lib.optional config.services.postgresql.enable "postgresql.service"
++ optional config.services.tomcat.enable "tomcat.service" ++ lib.optional config.services.tomcat.enable "tomcat.service"
++ optional config.services.svnserve.enable "svnserve.service" ++ lib.optional config.services.svnserve.enable "svnserve.service"
++ optional config.services.mongodb.enable "mongodb.service" ++ lib.optional config.services.mongodb.enable "mongodb.service"
++ optional config.services.influxdb.enable "influxdb.service"; ++ lib.optional config.services.influxdb.enable "influxdb.service";
restartIfChanged = false; restartIfChanged = false;
@ -82,8 +79,8 @@ in
environment = { environment = {
HOME = "/root"; HOME = "/root";
} }
// (optionalAttrs (config.environment.variables ? DYSNOMIA_CONTAINERS_PATH) { inherit (config.environment.variables) DYSNOMIA_CONTAINERS_PATH; }) // (lib.optionalAttrs (config.environment.variables ? DYSNOMIA_CONTAINERS_PATH) { inherit (config.environment.variables) DYSNOMIA_CONTAINERS_PATH; })
// (optionalAttrs (config.environment.variables ? DYSNOMIA_MODULES_PATH) { inherit (config.environment.variables) DYSNOMIA_MODULES_PATH; }); // (lib.optionalAttrs (config.environment.variables ? DYSNOMIA_MODULES_PATH) { inherit (config.environment.variables) DYSNOMIA_MODULES_PATH; });
serviceConfig.ExecStart = "${cfg.package}/bin/disnix-service"; serviceConfig.ExecStart = "${cfg.package}/bin/disnix-service";
}; };

View file

@ -1,7 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.dockerRegistry; cfg = config.services.dockerRegistry;
@ -15,7 +12,7 @@ let
storage = { storage = {
cache.blobdescriptor = blobCache; cache.blobdescriptor = blobCache;
delete.enabled = cfg.enableDelete; delete.enabled = cfg.enableDelete;
} // (optionalAttrs (cfg.storagePath != null) { filesystem.rootdirectory = cfg.storagePath; }); } // (lib.optionalAttrs (cfg.storagePath != null) { filesystem.rootdirectory = cfg.storagePath; });
http = { http = {
addr = "${cfg.listenAddress}:${builtins.toString cfg.port}"; addr = "${cfg.listenAddress}:${builtins.toString cfg.port}";
headers.X-Content-Type-Options = ["nosniff"]; headers.X-Content-Type-Options = ["nosniff"];
@ -27,7 +24,7 @@ let
}; };
}; };
registryConfig.redis = mkIf cfg.enableRedisCache { registryConfig.redis = lib.mkIf cfg.enableRedisCache {
addr = "${cfg.redisUrl}"; addr = "${cfg.redisUrl}";
password = "${cfg.redisPassword}"; password = "${cfg.redisPassword}";
db = 0; db = 0;
@ -44,32 +41,32 @@ let
configFile = cfg.configFile; configFile = cfg.configFile;
in { in {
options.services.dockerRegistry = { options.services.dockerRegistry = {
enable = mkEnableOption "Docker Registry"; enable = lib.mkEnableOption "Docker Registry";
package = mkPackageOption pkgs "docker-distribution" { package = lib.mkPackageOption pkgs "docker-distribution" {
example = "gitlab-container-registry"; example = "gitlab-container-registry";
}; };
listenAddress = mkOption { listenAddress = lib.mkOption {
description = "Docker registry host or ip to bind to."; description = "Docker registry host or ip to bind to.";
default = "127.0.0.1"; default = "127.0.0.1";
type = types.str; type = lib.types.str;
}; };
port = mkOption { port = lib.mkOption {
description = "Docker registry port to bind to."; description = "Docker registry port to bind to.";
default = 5000; default = 5000;
type = types.port; type = lib.types.port;
}; };
openFirewall = mkOption { openFirewall = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = "Opens the port used by the firewall."; description = "Opens the port used by the firewall.";
}; };
storagePath = mkOption { storagePath = lib.mkOption {
type = types.nullOr types.path; type = lib.types.nullOr lib.types.path;
default = "/var/lib/docker-registry"; default = "/var/lib/docker-registry";
description = '' description = ''
Docker registry storage path for the filesystem storage backend. Set to Docker registry storage path for the filesystem storage backend. Set to
@ -77,50 +74,50 @@ in {
''; '';
}; };
enableDelete = mkOption { enableDelete = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = "Enable delete for manifests and blobs."; description = "Enable delete for manifests and blobs.";
}; };
enableRedisCache = mkEnableOption "redis as blob cache"; enableRedisCache = lib.mkEnableOption "redis as blob cache";
redisUrl = mkOption { redisUrl = lib.mkOption {
type = types.str; type = lib.types.str;
default = "localhost:6379"; default = "localhost:6379";
description = "Set redis host and port."; description = "Set redis host and port.";
}; };
redisPassword = mkOption { redisPassword = lib.mkOption {
type = types.str; type = lib.types.str;
default = ""; default = "";
description = "Set redis password."; description = "Set redis password.";
}; };
extraConfig = mkOption { extraConfig = lib.mkOption {
description = '' description = ''
Docker extra registry configuration via environment variables. Docker extra registry configuration via environment variables.
''; '';
default = {}; default = {};
type = types.attrs; type = lib.types.attrs;
}; };
configFile = lib.mkOption { configFile = lib.mkOption {
default = pkgs.writeText "docker-registry-config.yml" (builtins.toJSON (recursiveUpdate registryConfig cfg.extraConfig)); default = pkgs.writeText "docker-registry-config.yml" (builtins.toJSON (lib.recursiveUpdate registryConfig cfg.extraConfig));
defaultText = literalExpression ''pkgs.writeText "docker-registry-config.yml" "# my custom docker-registry-config.yml ..."''; defaultText = lib.literalExpression ''pkgs.writeText "docker-registry-config.yml" "# my custom docker-registry-config.yml ..."'';
description = '' description = ''
Path to CNCF distribution config file. Path to CNCF distribution config file.
Setting this option will override any configuration applied by the extraConfig option. Setting this option will override any configuration applied by the extraConfig option.
''; '';
type = types.path; type = lib.types.path;
}; };
enableGarbageCollect = mkEnableOption "garbage collect"; enableGarbageCollect = lib.mkEnableOption "garbage collect";
garbageCollectDates = mkOption { garbageCollectDates = lib.mkOption {
default = "daily"; default = "daily";
type = types.str; type = lib.types.str;
description = '' description = ''
Specification (in the format described by Specification (in the format described by
{manpage}`systemd.time(7)`) of the time at {manpage}`systemd.time(7)`) of the time at
@ -129,7 +126,7 @@ in {
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
systemd.services.docker-registry = { systemd.services.docker-registry = {
description = "Docker Container Registry"; description = "Docker Container Registry";
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
@ -141,7 +138,7 @@ in {
serviceConfig = { serviceConfig = {
User = "docker-registry"; User = "docker-registry";
WorkingDirectory = cfg.storagePath; WorkingDirectory = cfg.storagePath;
AmbientCapabilities = mkIf (cfg.port < 1024) "cap_net_bind_service"; AmbientCapabilities = lib.mkIf (cfg.port < 1024) "cap_net_bind_service";
}; };
}; };
@ -158,11 +155,11 @@ in {
/run/current-system/systemd/bin/systemctl restart docker-registry.service /run/current-system/systemd/bin/systemctl restart docker-registry.service
''; '';
startAt = optional cfg.enableGarbageCollect cfg.garbageCollectDates; startAt = lib.optional cfg.enableGarbageCollect cfg.garbageCollectDates;
}; };
users.users.docker-registry = users.users.docker-registry =
(optionalAttrs (cfg.storagePath != null) { (lib.optionalAttrs (cfg.storagePath != null) {
createHome = true; createHome = true;
home = cfg.storagePath; home = cfg.storagePath;
}) // { }) // {
@ -171,7 +168,7 @@ in {
}; };
users.groups.docker-registry = {}; users.groups.docker-registry = {};
networking.firewall = mkIf cfg.openFirewall { networking.firewall = lib.mkIf cfg.openFirewall {
allowedTCPPorts = [ cfg.port ]; allowedTCPPorts = [ cfg.port ];
}; };
}; };

View file

@ -1,7 +1,4 @@
{ lib, pkgs, config, ... }: { lib, pkgs, config, ... }:
with lib;
let let
cfg = config.services.domoticz; cfg = config.services.domoticz;
@ -12,16 +9,16 @@ in {
options = { options = {
services.domoticz = { services.domoticz = {
enable = mkEnableOption pkgDesc; enable = lib.mkEnableOption pkgDesc;
bind = mkOption { bind = lib.mkOption {
type = types.str; type = lib.types.str;
default = "0.0.0.0"; default = "0.0.0.0";
description = "IP address to bind to."; description = "IP address to bind to.";
}; };
port = mkOption { port = lib.mkOption {
type = types.port; type = lib.types.port;
default = 8080; default = 8080;
description = "Port to bind to for HTTP, set to 0 to disable HTTP."; description = "Port to bind to for HTTP, set to 0 to disable HTTP.";
}; };
@ -30,7 +27,7 @@ in {
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
systemd.services."domoticz" = { systemd.services."domoticz" = {
description = pkgDesc; description = pkgDesc;

View file

@ -1,16 +1,13 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.duckling; cfg = config.services.duckling;
in { in {
options = { options = {
services.duckling = { services.duckling = {
enable = mkEnableOption "duckling"; enable = lib.mkEnableOption "duckling";
port = mkOption { port = lib.mkOption {
type = types.port; type = lib.types.port;
default = 8080; default = 8080;
description = '' description = ''
Port on which duckling will run. Port on which duckling will run.
@ -19,7 +16,7 @@ in {
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
systemd.services.duckling = { systemd.services.duckling = {
description = "Duckling server service"; description = "Duckling server service";
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];

View file

@ -1,11 +1,8 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.dwm-status; cfg = config.services.dwm-status;
order = concatMapStringsSep "," (feature: ''"${feature}"'') cfg.order; order = lib.concatMapStringsSep "," (feature: ''"${feature}"'') cfg.order;
configFile = pkgs.writeText "dwm-status.toml" '' configFile = pkgs.writeText "dwm-status.toml" ''
order = [${order}] order = [${order}]
@ -22,21 +19,21 @@ in
services.dwm-status = { services.dwm-status = {
enable = mkEnableOption "dwm-status user service"; enable = lib.mkEnableOption "dwm-status user service";
package = mkPackageOption pkgs "dwm-status" { package = lib.mkPackageOption pkgs "dwm-status" {
example = "dwm-status.override { enableAlsaUtils = false; }"; example = "dwm-status.override { enableAlsaUtils = false; }";
}; };
order = mkOption { order = lib.mkOption {
type = types.listOf (types.enum [ "audio" "backlight" "battery" "cpu_load" "network" "time" ]); type = lib.types.listOf (lib.types.enum [ "audio" "backlight" "battery" "cpu_load" "network" "time" ]);
description = '' description = ''
List of enabled features in order. List of enabled features in order.
''; '';
}; };
extraConfig = mkOption { extraConfig = lib.mkOption {
type = types.lines; type = lib.types.lines;
default = ""; default = "";
description = '' description = ''
Extra config in TOML format. Extra config in TOML format.
@ -50,9 +47,9 @@ in
###### implementation ###### implementation
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
services.upower.enable = elem "battery" cfg.order; services.upower.enable = lib.elem "battery" cfg.order;
systemd.user.services.dwm-status = { systemd.user.services.dwm-status = {
description = "Highly performant and configurable DWM status service"; description = "Highly performant and configurable DWM status service";

View file

@ -1,16 +1,13 @@
{pkgs, lib, config, ...}: {pkgs, lib, config, ...}:
with lib;
let let
cfg = config.dysnomia; cfg = config.dysnomia;
printProperties = properties: printProperties = properties:
concatMapStrings (propertyName: lib.concatMapStrings (propertyName:
let let
property = properties.${propertyName}; property = properties.${propertyName};
in in
if isList property then "${propertyName}=(${lib.concatMapStrings (elem: "\"${toString elem}\" ") (properties.${propertyName})})\n" if lib.isList property then "${propertyName}=(${lib.concatMapStrings (elem: "\"${toString elem}\" ") (properties.${propertyName})})\n"
else "${propertyName}=\"${toString property}\"\n" else "${propertyName}=\"${toString property}\"\n"
) (builtins.attrNames properties); ) (builtins.attrNames properties);
@ -29,7 +26,7 @@ let
mkdir -p $out mkdir -p $out
cd $out cd $out
${concatMapStrings (containerName: ${lib.concatMapStrings (containerName:
let let
containerProperties = cfg.containers.${containerName}; containerProperties = cfg.containers.${containerName};
in in
@ -47,7 +44,7 @@ let
'' ''
mkdir ${containerName} mkdir ${containerName}
${concatMapStrings (componentName: ${lib.concatMapStrings (componentName:
let let
component = cfg.components.${containerName}.${componentName}; component = cfg.components.${containerName}.${componentName};
in in
@ -61,7 +58,7 @@ let
mkdir -p $out mkdir -p $out
cd $out cd $out
${concatMapStrings (containerName: ${lib.concatMapStrings (containerName:
linkMutableComponents { inherit containerName; } linkMutableComponents { inherit containerName; }
) (builtins.attrNames cfg.components)} ) (builtins.attrNames cfg.components)}
''; '';
@ -84,68 +81,68 @@ in
options = { options = {
dysnomia = { dysnomia = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = "Whether to enable Dysnomia"; description = "Whether to enable Dysnomia";
}; };
enableAuthentication = mkOption { enableAuthentication = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = "Whether to publish privacy-sensitive authentication credentials"; description = "Whether to publish privacy-sensitive authentication credentials";
}; };
package = mkOption { package = lib.mkOption {
type = types.path; type = lib.types.path;
description = "The Dysnomia package"; description = "The Dysnomia package";
}; };
properties = mkOption { properties = lib.mkOption {
description = "An attribute set in which each attribute represents a machine property. Optionally, these values can be shell substitutions."; description = "An attribute set in which each attribute represents a machine property. Optionally, these values can be shell substitutions.";
default = {}; default = {};
type = types.attrs; type = lib.types.attrs;
}; };
containers = mkOption { containers = lib.mkOption {
description = "An attribute set in which each key represents a container and each value an attribute set providing its configuration properties"; description = "An attribute set in which each key represents a container and each value an attribute set providing its configuration properties";
default = {}; default = {};
type = types.attrsOf types.attrs; type = lib.types.attrsOf lib.types.attrs;
}; };
components = mkOption { components = lib.mkOption {
description = "An attribute set in which each key represents a container and each value an attribute set in which each key represents a component and each value a derivation constructing its initial state"; description = "An attribute set in which each key represents a container and each value an attribute set in which each key represents a component and each value a derivation constructing its initial state";
default = {}; default = {};
type = types.attrsOf types.attrs; type = lib.types.attrsOf lib.types.attrs;
}; };
extraContainerProperties = mkOption { extraContainerProperties = lib.mkOption {
description = "An attribute set providing additional container settings in addition to the default properties"; description = "An attribute set providing additional container settings in addition to the default properties";
default = {}; default = {};
type = types.attrs; type = lib.types.attrs;
}; };
extraContainerPaths = mkOption { extraContainerPaths = lib.mkOption {
description = "A list of paths containing additional container configurations that are added to the search folders"; description = "A list of paths containing additional container configurations that are added to the search folders";
default = []; default = [];
type = types.listOf types.path; type = lib.types.listOf lib.types.path;
}; };
extraModulePaths = mkOption { extraModulePaths = lib.mkOption {
description = "A list of paths containing additional modules that are added to the search folders"; description = "A list of paths containing additional modules that are added to the search folders";
default = []; default = [];
type = types.listOf types.path; type = lib.types.listOf lib.types.path;
}; };
enableLegacyModules = mkOption { enableLegacyModules = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = true; default = true;
description = "Whether to enable Dysnomia legacy process and wrapper modules"; description = "Whether to enable Dysnomia legacy process and wrapper modules";
}; };
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
environment.etc = { environment.etc = {
"dysnomia/containers" = { "dysnomia/containers" = {
@ -199,16 +196,16 @@ in
"sysvinit-script" "sysvinit-script"
"nixos-configuration" "nixos-configuration"
] ]
++ optional (dysnomiaFlags.enableApacheWebApplication) "apache-webapplication" ++ lib.optional (dysnomiaFlags.enableApacheWebApplication) "apache-webapplication"
++ optional (dysnomiaFlags.enableAxis2WebService) "axis2-webservice" ++ lib.optional (dysnomiaFlags.enableAxis2WebService) "axis2-webservice"
++ optional (dysnomiaFlags.enableDockerContainer) "docker-container" ++ lib.optional (dysnomiaFlags.enableDockerContainer) "docker-container"
++ optional (dysnomiaFlags.enableEjabberdDump) "ejabberd-dump" ++ lib.optional (dysnomiaFlags.enableEjabberdDump) "ejabberd-dump"
++ optional (dysnomiaFlags.enableInfluxDatabase) "influx-database" ++ lib.optional (dysnomiaFlags.enableInfluxDatabase) "influx-database"
++ optional (dysnomiaFlags.enableMySQLDatabase) "mysql-database" ++ lib.optional (dysnomiaFlags.enableMySQLDatabase) "mysql-database"
++ optional (dysnomiaFlags.enablePostgreSQLDatabase) "postgresql-database" ++ lib.optional (dysnomiaFlags.enablePostgreSQLDatabase) "postgresql-database"
++ optional (dysnomiaFlags.enableTomcatWebApplication) "tomcat-webapplication" ++ lib.optional (dysnomiaFlags.enableTomcatWebApplication) "tomcat-webapplication"
++ optional (dysnomiaFlags.enableMongoDatabase) "mongo-database" ++ lib.optional (dysnomiaFlags.enableMongoDatabase) "mongo-database"
++ optional (dysnomiaFlags.enableSubversionRepository) "subversion-repository"; ++ lib.optional (dysnomiaFlags.enableSubversionRepository) "subversion-repository";
}; };
dysnomia.containers = lib.recursiveUpdate ({ dysnomia.containers = lib.recursiveUpdate ({

View file

@ -1,7 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.errbot; cfg = config.services.errbot;
pluginEnv = plugins: pkgs.buildEnv { pluginEnv = plugins: pkgs.buildEnv {
@ -17,7 +14,7 @@ let
BOT_LOG_LEVEL = logging.${instanceCfg.logLevel} BOT_LOG_LEVEL = logging.${instanceCfg.logLevel}
BOT_LOG_FILE = False BOT_LOG_FILE = False
BOT_ADMINS = (${concatMapStringsSep "," (name: "'${name}'") instanceCfg.admins}) BOT_ADMINS = (${lib.concatMapStringsSep "," (name: "'${name}'") instanceCfg.admins})
BOT_IDENTITY = ${builtins.toJSON instanceCfg.identity} BOT_IDENTITY = ${builtins.toJSON instanceCfg.identity}
@ -25,48 +22,48 @@ let
''; '';
in { in {
options = { options = {
services.errbot.instances = mkOption { services.errbot.instances = lib.mkOption {
default = {}; default = {};
description = "Errbot instance configs"; description = "Errbot instance configs";
type = types.attrsOf (types.submodule { type = lib.types.attrsOf (lib.types.submodule {
options = { options = {
dataDir = mkOption { dataDir = lib.mkOption {
type = types.nullOr types.path; type = lib.types.nullOr lib.types.path;
default = null; default = null;
description = "Data directory for errbot instance."; description = "Data directory for errbot instance.";
}; };
plugins = mkOption { plugins = lib.mkOption {
type = types.listOf types.package; type = lib.types.listOf lib.types.package;
default = []; default = [];
description = "List of errbot plugin derivations."; description = "List of errbot plugin derivations.";
}; };
logLevel = mkOption { logLevel = lib.mkOption {
type = types.str; type = lib.types.str;
default = "INFO"; default = "INFO";
description = "Errbot log level"; description = "Errbot log level";
}; };
admins = mkOption { admins = lib.mkOption {
type = types.listOf types.str; type = lib.types.listOf lib.types.str;
default = []; default = [];
description = "List of identifiers of errbot admins."; description = "List of identifiers of errbot admins.";
}; };
backend = mkOption { backend = lib.mkOption {
type = types.str; type = lib.types.str;
default = "XMPP"; default = "XMPP";
description = "Errbot backend name."; description = "Errbot backend name.";
}; };
identity = mkOption { identity = lib.mkOption {
type = types.attrs; type = lib.types.attrs;
description = "Errbot identity configuration"; description = "Errbot identity configuration";
}; };
extraConfig = mkOption { extraConfig = lib.mkOption {
type = types.lines; type = lib.types.lines;
default = ""; default = "";
description = "String to be appended to the config verbatim"; description = "String to be appended to the config verbatim";
}; };
@ -75,14 +72,14 @@ in {
}; };
}; };
config = mkIf (cfg.instances != {}) { config = lib.mkIf (cfg.instances != {}) {
users.users.errbot = { users.users.errbot = {
group = "errbot"; group = "errbot";
isSystemUser = true; isSystemUser = true;
}; };
users.groups.errbot = {}; users.groups.errbot = {};
systemd.services = mapAttrs' (name: instanceCfg: nameValuePair "errbot-${name}" ( systemd.services = lib.mapAttrs' (name: instanceCfg: lib.nameValuePair "errbot-${name}" (
let let
dataDir = if instanceCfg.dataDir != null then instanceCfg.dataDir else dataDir = if instanceCfg.dataDir != null then instanceCfg.dataDir else
"/var/lib/errbot/${name}"; "/var/lib/errbot/${name}";

View file

@ -1,7 +1,4 @@
{ config, pkgs, lib, ... }: { config, pkgs, lib, ... }:
with lib;
let let
cfg = config.services.etebase-server; cfg = config.services.etebase-server;
@ -13,24 +10,24 @@ let
in in
{ {
imports = [ imports = [
(mkRemovedOptionModule (lib.mkRemovedOptionModule
[ "services" "etebase-server" "customIni" ] [ "services" "etebase-server" "customIni" ]
"Set the option `services.etebase-server.settings' instead.") "Set the option `services.etebase-server.settings' instead.")
(mkRemovedOptionModule (lib.mkRemovedOptionModule
[ "services" "etebase-server" "database" ] [ "services" "etebase-server" "database" ]
"Set the option `services.etebase-server.settings.database' instead.") "Set the option `services.etebase-server.settings.database' instead.")
(mkRenamedOptionModule (lib.mkRenamedOptionModule
[ "services" "etebase-server" "secretFile" ] [ "services" "etebase-server" "secretFile" ]
[ "services" "etebase-server" "settings" "secret_file" ]) [ "services" "etebase-server" "settings" "secret_file" ])
(mkRenamedOptionModule (lib.mkRenamedOptionModule
[ "services" "etebase-server" "host" ] [ "services" "etebase-server" "host" ]
[ "services" "etebase-server" "settings" "allowed_hosts" "allowed_host1" ]) [ "services" "etebase-server" "settings" "allowed_hosts" "allowed_host1" ])
]; ];
options = { options = {
services.etebase-server = { services.etebase-server = {
enable = mkOption { enable = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
example = true; example = true;
description = '' description = ''
@ -43,77 +40,77 @@ in
''; '';
}; };
package = mkOption { package = lib.mkOption {
type = types.package; type = lib.types.package;
default = pkgs.etebase-server; default = pkgs.etebase-server;
defaultText = literalExpression "pkgs.python3.pkgs.etebase-server"; defaultText = lib.literalExpression "pkgs.python3.pkgs.etebase-server";
description = "etebase-server package to use."; description = "etebase-server package to use.";
}; };
dataDir = mkOption { dataDir = lib.mkOption {
type = types.str; type = lib.types.str;
default = "/var/lib/etebase-server"; default = "/var/lib/etebase-server";
description = "Directory to store the Etebase server data."; description = "Directory to store the Etebase server data.";
}; };
port = mkOption { port = lib.mkOption {
type = with types; nullOr port; type = with lib.types; nullOr port;
default = 8001; default = 8001;
description = "Port to listen on."; description = "Port to listen on.";
}; };
openFirewall = mkOption { openFirewall = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Whether to open ports in the firewall for the server. Whether to open ports in the firewall for the server.
''; '';
}; };
unixSocket = mkOption { unixSocket = lib.mkOption {
type = with types; nullOr str; type = with lib.types; nullOr str;
default = null; default = null;
description = "The path to the socket to bind to."; description = "The path to the socket to bind to.";
example = "/run/etebase-server/etebase-server.sock"; example = "/run/etebase-server/etebase-server.sock";
}; };
settings = mkOption { settings = lib.mkOption {
type = lib.types.submodule { type = lib.types.submodule {
freeformType = iniFmt.type; freeformType = iniFmt.type;
options = { options = {
global = { global = {
debug = mkOption { debug = lib.mkOption {
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Whether to set django's DEBUG flag. Whether to set django's DEBUG flag.
''; '';
}; };
secret_file = mkOption { secret_file = lib.mkOption {
type = with types; nullOr str; type = with lib.types; nullOr str;
default = null; default = null;
description = '' description = ''
The path to a file containing the secret The path to a file containing the secret
used as django's SECRET_KEY. used as django's SECRET_KEY.
''; '';
}; };
static_root = mkOption { static_root = lib.mkOption {
type = types.str; type = lib.types.str;
default = "${cfg.dataDir}/static"; default = "${cfg.dataDir}/static";
defaultText = literalExpression ''"''${config.services.etebase-server.dataDir}/static"''; defaultText = lib.literalExpression ''"''${config.services.etebase-server.dataDir}/static"'';
description = "The directory for static files."; description = "The directory for static files.";
}; };
media_root = mkOption { media_root = lib.mkOption {
type = types.str; type = lib.types.str;
default = "${cfg.dataDir}/media"; default = "${cfg.dataDir}/media";
defaultText = literalExpression ''"''${config.services.etebase-server.dataDir}/media"''; defaultText = lib.literalExpression ''"''${config.services.etebase-server.dataDir}/media"'';
description = "The media directory."; description = "The media directory.";
}; };
}; };
allowed_hosts = { allowed_hosts = {
allowed_host1 = mkOption { allowed_host1 = lib.mkOption {
type = types.str; type = lib.types.str;
default = "0.0.0.0"; default = "0.0.0.0";
example = "localhost"; example = "localhost";
description = '' description = ''
@ -122,15 +119,15 @@ in
}; };
}; };
database = { database = {
engine = mkOption { engine = lib.mkOption {
type = types.enum [ "django.db.backends.sqlite3" "django.db.backends.postgresql" ]; type = lib.types.enum [ "django.db.backends.sqlite3" "django.db.backends.postgresql" ];
default = "django.db.backends.sqlite3"; default = "django.db.backends.sqlite3";
description = "The database engine to use."; description = "The database engine to use.";
}; };
name = mkOption { name = lib.mkOption {
type = types.str; type = lib.types.str;
default = "${cfg.dataDir}/db.sqlite3"; default = "${cfg.dataDir}/db.sqlite3";
defaultText = literalExpression ''"''${config.services.etebase-server.dataDir}/db.sqlite3"''; defaultText = lib.literalExpression ''"''${config.services.etebase-server.dataDir}/db.sqlite3"'';
description = "The database name."; description = "The database name.";
}; };
}; };
@ -154,15 +151,15 @@ in
}; };
}; };
user = mkOption { user = lib.mkOption {
type = types.str; type = lib.types.str;
default = defaultUser; default = defaultUser;
description = "User under which Etebase server runs."; description = "User under which Etebase server runs.";
}; };
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
(runCommand "etebase-server" { (runCommand "etebase-server" {
@ -170,7 +167,7 @@ in
} '' } ''
makeWrapper ${cfg.package}/bin/etebase-server \ makeWrapper ${cfg.package}/bin/etebase-server \
$out/bin/etebase-server \ $out/bin/etebase-server \
--chdir ${escapeShellArg cfg.dataDir} \ --chdir ${lib.escapeShellArg cfg.dataDir} \
--prefix ETEBASE_EASY_CONFIG_PATH : "${configIni}" --prefix ETEBASE_EASY_CONFIG_PATH : "${configIni}"
'') '')
]; ];
@ -217,7 +214,7 @@ in
''; '';
}; };
users = optionalAttrs (cfg.user == defaultUser) { users = lib.optionalAttrs (cfg.user == defaultUser) {
users.${defaultUser} = { users.${defaultUser} = {
isSystemUser = true; isSystemUser = true;
group = defaultUser; group = defaultUser;
@ -227,7 +224,7 @@ in
groups.${defaultUser} = {}; groups.${defaultUser} = {};
}; };
networking.firewall = mkIf cfg.openFirewall { networking.firewall = lib.mkIf cfg.openFirewall {
allowedTCPPorts = [ cfg.port ]; allowedTCPPorts = [ cfg.port ];
}; };
}; };

View file

@ -1,40 +1,37 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.etesync-dav; cfg = config.services.etesync-dav;
in in
{ {
options.services.etesync-dav = { options.services.etesync-dav = {
enable = mkEnableOption "etesync-dav, end-to-end encrypted sync for contacts, calendars and tasks"; enable = lib.mkEnableOption "etesync-dav, end-to-end encrypted sync for contacts, calendars and tasks";
host = mkOption { host = lib.mkOption {
type = types.str; type = lib.types.str;
default = "localhost"; default = "localhost";
description = "The server host address."; description = "The server host address.";
}; };
port = mkOption { port = lib.mkOption {
type = types.port; type = lib.types.port;
default = 37358; default = 37358;
description = "The server host port."; description = "The server host port.";
}; };
apiUrl = mkOption { apiUrl = lib.mkOption {
type = types.str; type = lib.types.str;
default = "https://api.etesync.com/"; default = "https://api.etesync.com/";
description = "The url to the etesync API."; description = "The url to the etesync API.";
}; };
openFirewall = mkOption { openFirewall = lib.mkOption {
default = false; default = false;
type = types.bool; type = lib.types.bool;
description = "Whether to open the firewall for the specified port."; description = "Whether to open the firewall for the specified port.";
}; };
sslCertificate = mkOption { sslCertificate = lib.mkOption {
type = types.nullOr types.path; type = lib.types.nullOr lib.types.path;
default = null; default = null;
example = "/var/etesync.crt"; example = "/var/etesync.crt";
description = '' description = ''
@ -43,8 +40,8 @@ in
''; '';
}; };
sslCertificateKey = mkOption { sslCertificateKey = lib.mkOption {
type = types.nullOr types.path; type = lib.types.nullOr lib.types.path;
default = null; default = null;
example = "/var/etesync.key"; example = "/var/etesync.key";
description = '' description = ''
@ -54,8 +51,8 @@ in
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ]; networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [ cfg.port ];
systemd.services.etesync-dav = { systemd.services.etesync-dav = {
description = "etesync-dav - A CalDAV and CardDAV adapter for EteSync"; description = "etesync-dav - A CalDAV and CardDAV adapter for EteSync";
@ -75,12 +72,12 @@ in
DynamicUser = true; DynamicUser = true;
StateDirectory = "etesync-dav"; StateDirectory = "etesync-dav";
ExecStart = "${pkgs.etesync-dav}/bin/etesync-dav"; ExecStart = "${pkgs.etesync-dav}/bin/etesync-dav";
ExecStartPre = mkIf (cfg.sslCertificate != null || cfg.sslCertificateKey != null) ( ExecStartPre = lib.mkIf (cfg.sslCertificate != null || cfg.sslCertificateKey != null) (
pkgs.writers.writeBash "etesync-dav-copy-keys" '' pkgs.writers.writeBash "etesync-dav-copy-keys" ''
${optionalString (cfg.sslCertificate != null) '' ${lib.optionalString (cfg.sslCertificate != null) ''
cp ${toString cfg.sslCertificate} $STATE_DIRECTORY/etesync.crt cp ${toString cfg.sslCertificate} $STATE_DIRECTORY/etesync.crt
''} ''}
${optionalString (cfg.sslCertificateKey != null) '' ${lib.optionalString (cfg.sslCertificateKey != null) ''
cp ${toString cfg.sslCertificateKey} $STATE_DIRECTORY/etesync.key cp ${toString cfg.sslCertificateKey} $STATE_DIRECTORY/etesync.key
''} ''}
'' ''

View file

@ -1,6 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
format = pkgs.formats.yaml { }; format = pkgs.formats.yaml { };
cfg = config.services.evdevremapkeys; cfg = config.services.evdevremapkeys;
@ -8,9 +6,9 @@ let
in in
{ {
options.services.evdevremapkeys = { options.services.evdevremapkeys = {
enable = mkEnableOption ''evdevremapkeys, a daemon to remap events on linux input devices''; enable = lib.mkEnableOption ''evdevremapkeys, a daemon to remap events on linux input devices'';
settings = mkOption { settings = lib.mkOption {
type = format.type; type = format.type;
default = { }; default = { };
description = '' description = ''
@ -19,7 +17,7 @@ in
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
boot.kernelModules = [ "uinput" ]; boot.kernelModules = [ "uinput" ];
services.udev.extraRules = '' services.udev.extraRules = ''
KERNEL=="uinput", MODE="0660", GROUP="input" KERNEL=="uinput", MODE="0660", GROUP="input"

View file

@ -1,8 +1,5 @@
# Felix server # Felix server
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.services.felix; cfg = config.services.felix;
@ -17,23 +14,23 @@ in
services.felix = { services.felix = {
enable = mkEnableOption "the Apache Felix OSGi service"; enable = lib.mkEnableOption "the Apache Felix OSGi service";
bundles = mkOption { bundles = lib.mkOption {
type = types.listOf types.package; type = lib.types.listOf lib.types.package;
default = [ pkgs.felix_remoteshell ]; default = [ pkgs.felix_remoteshell ];
defaultText = literalExpression "[ pkgs.felix_remoteshell ]"; defaultText = lib.literalExpression "[ pkgs.felix_remoteshell ]";
description = "List of bundles that should be activated on startup"; description = "List of bundles that should be activated on startup";
}; };
user = mkOption { user = lib.mkOption {
type = types.str; type = lib.types.str;
default = "osgi"; default = "osgi";
description = "User account under which Apache Felix runs."; description = "User account under which Apache Felix runs.";
}; };
group = mkOption { group = lib.mkOption {
type = types.str; type = lib.types.str;
default = "osgi"; default = "osgi";
description = "Group account under which Apache Felix runs."; description = "Group account under which Apache Felix runs.";
}; };
@ -45,7 +42,7 @@ in
###### implementation ###### implementation
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
users.groups.osgi.gid = config.ids.gids.osgi; users.groups.osgi.gid = config.ids.gids.osgi;
users.users.osgi = users.users.osgi =

Some files were not shown because too many files have changed in this diff Show more