diff options
author | Frederik Rietdijk <fridh@fridh.nl> | 2019-08-28 08:26:42 +0200 |
---|---|---|
committer | Frederik Rietdijk <fridh@fridh.nl> | 2019-08-28 08:26:42 +0200 |
commit | 5061fe0c2c7743370e1d379d6fa60eed26ff1470 (patch) | |
tree | 4a4ee79a6e0694d3c7ad6fbeff33343d83458e6c /nixos/modules | |
parent | a2538606e3115e16db2e5075ecf37b886ad64ede (diff) | |
parent | 98640fd48212f8e6552517f667bba1901f5936d4 (diff) |
Merge staging-next into staging
Diffstat (limited to 'nixos/modules')
88 files changed, 2328 insertions, 1583 deletions
diff --git a/nixos/modules/config/fonts/fontconfig-penultimate.nix b/nixos/modules/config/fonts/fontconfig-penultimate.nix index 963cbb0f08c4b..9790bdde566d4 100644 --- a/nixos/modules/config/fonts/fontconfig-penultimate.nix +++ b/nixos/modules/config/fonts/fontconfig-penultimate.nix @@ -52,85 +52,11 @@ let </fontconfig> ''; + # local configuration file localConf = pkgs.writeText "fc-local.conf" cfg.localConf; - # The configuration to be included in /etc/font/ - penultimateConf = pkgs.runCommand "font-penultimate-conf" { - preferLocalBuild = true; - } '' - support_folder=$out/etc/fonts/conf.d - latest_folder=$out/etc/fonts/${latestVersion}/conf.d - - mkdir -p $support_folder - mkdir -p $latest_folder - - ln -s ${supportFontsConf} $support_folder/../fonts.conf - ln -s ${latestPkg.out}/etc/fonts/fonts.conf \ - $latest_folder/../fonts.conf - - # fontconfig-penultimate various configuration files - ln -s ${pkgs.fontconfig-penultimate}/etc/fonts/conf.d/*.conf \ - $support_folder - ln -s ${pkgs.fontconfig-penultimate}/etc/fonts/conf.d/*.conf \ - $latest_folder - - ln -s ${cacheConfSupport} $support_folder/00-nixos-cache.conf - ln -s ${cacheConfLatest} $latest_folder/00-nixos-cache.conf - - rm $support_folder/10-antialias.conf $latest_folder/10-antialias.conf - ln -s ${antialiasConf} $support_folder/10-antialias.conf - ln -s ${antialiasConf} $latest_folder/10-antialias.conf - - rm $support_folder/10-hinting.conf $latest_folder/10-hinting.conf - ln -s ${hintingConf} $support_folder/10-hinting.conf - ln -s ${hintingConf} $latest_folder/10-hinting.conf - - ${optionalString cfg.useEmbeddedBitmaps '' - rm $support_folder/10-no-embedded-bitmaps.conf - rm $latest_folder/10-no-embedded-bitmaps.conf - ''} - - rm $support_folder/10-subpixel.conf $latest_folder/10-subpixel.conf - ln -s ${subpixelConf} $support_folder/10-subpixel.conf - ln -s ${subpixelConf} $latest_folder/10-subpixel.conf - - ${optionalString (cfg.dpi != 0) '' - ln -s ${dpiConf} $support_folder/11-dpi.conf - ln -s ${dpiConf} $latest_folder/11-dpi.conf - ''} - - ${optionalString (!cfg.includeUserConf) '' - rm $support_folder/50-user.conf - rm $latest_folder/50-user.conf - ''} - - # 51-local.conf - rm $latest_folder/51-local.conf - substitute \ - ${pkgs.fontconfig-penultimate}/etc/fonts/conf.d/51-local.conf \ - $latest_folder/51-local.conf \ - --replace local.conf /etc/fonts/${latestVersion}/local.conf - - # local.conf (indirect priority 51) - ${optionalString (cfg.localConf != "") '' - ln -s ${localConf} $out/etc/fonts/local.conf - ln -s ${localConf} $out/etc/fonts/${latestVersion}/local.conf - ''} - - ln -s ${defaultFontsConf} $support_folder/52-default-fonts.conf - ln -s ${defaultFontsConf} $latest_folder/52-default-fonts.conf - - ${optionalString cfg.allowBitmaps '' - rm $support_folder/53-no-bitmaps.conf - rm $latest_folder/53-no-bitmaps.conf - ''} - - ${optionalString (!cfg.allowType1) '' - ln -s ${rejectType1} $support_folder/53-no-type1.conf - ln -s ${rejectType1} $latest_folder/53-no-type1.conf - ''} - ''; - + # rendering settings configuration files + # priority 10 hintingConf = pkgs.writeText "fc-10-hinting.conf" '' <?xml version='1.0'?> <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'> @@ -199,6 +125,8 @@ let </fontconfig> ''; + # default fonts configuration file + # priority 52 defaultFontsConf = let genDefault = fonts: name: optionalString (fonts != []) '' @@ -228,7 +156,9 @@ let </fontconfig> ''; - rejectType1 = pkgs.writeText "fc-53-no-type1.conf" '' + # reject Type 1 fonts + # priority 53 + rejectType1 = pkgs.writeText "fc-53-nixos-reject-type1.conf" '' <?xml version="1.0"?> <!DOCTYPE fontconfig SYSTEM "fonts.dtd"> <fontconfig> @@ -245,6 +175,88 @@ let </fontconfig> ''; + # The configuration to be included in /etc/font/ + penultimateConf = pkgs.runCommand "fontconfig-penultimate-conf" { + preferLocalBuild = true; + } '' + support_folder=$out/etc/fonts/conf.d + latest_folder=$out/etc/fonts/${latestVersion}/conf.d + + mkdir -p $support_folder + mkdir -p $latest_folder + + # fonts.conf + ln -s ${supportFontsConf} $support_folder/../fonts.conf + ln -s ${latestPkg.out}/etc/fonts/fonts.conf \ + $latest_folder/../fonts.conf + + # fontconfig-penultimate various configuration files + ln -s ${pkgs.fontconfig-penultimate}/etc/fonts/conf.d/*.conf \ + $support_folder + ln -s ${pkgs.fontconfig-penultimate}/etc/fonts/conf.d/*.conf \ + $latest_folder + + ln -s ${cacheConfSupport} $support_folder/00-nixos-cache.conf + ln -s ${cacheConfLatest} $latest_folder/00-nixos-cache.conf + + rm $support_folder/10-antialias.conf $latest_folder/10-antialias.conf + ln -s ${antialiasConf} $support_folder/10-antialias.conf + ln -s ${antialiasConf} $latest_folder/10-antialias.conf + + rm $support_folder/10-hinting.conf $latest_folder/10-hinting.conf + ln -s ${hintingConf} $support_folder/10-hinting.conf + ln -s ${hintingConf} $latest_folder/10-hinting.conf + + ${optionalString cfg.useEmbeddedBitmaps '' + rm $support_folder/10-no-embedded-bitmaps.conf + rm $latest_folder/10-no-embedded-bitmaps.conf + ''} + + rm $support_folder/10-subpixel.conf $latest_folder/10-subpixel.conf + ln -s ${subpixelConf} $support_folder/10-subpixel.conf + ln -s ${subpixelConf} $latest_folder/10-subpixel.conf + + ${optionalString (cfg.dpi != 0) '' + ln -s ${dpiConf} $support_folder/11-dpi.conf + ln -s ${dpiConf} $latest_folder/11-dpi.conf + ''} + + # 50-user.conf + ${optionalString (!cfg.includeUserConf) '' + rm $support_folder/50-user.conf + rm $latest_folder/50-user.conf + ''} + + # 51-local.conf + rm $latest_folder/51-local.conf + substitute \ + ${pkgs.fontconfig-penultimate}/etc/fonts/conf.d/51-local.conf \ + $latest_folder/51-local.conf \ + --replace local.conf /etc/fonts/${latestVersion}/local.conf + + # local.conf (indirect priority 51) + ${optionalString (cfg.localConf != "") '' + ln -s ${localConf} $support_folder/../local.conf + ln -s ${localConf} $latest_folder/../local.conf + ''} + + # 52-nixos-default-fonts.conf + ln -s ${defaultFontsConf} $support_folder/52-nixos-default-fonts.conf + ln -s ${defaultFontsConf} $latest_folder/52-nixos-default-fonts.conf + + # 53-no-bitmaps.conf + ${optionalString cfg.allowBitmaps '' + rm $support_folder/53-no-bitmaps.conf + rm $latest_folder/53-no-bitmaps.conf + ''} + + ${optionalString (!cfg.allowType1) '' + # 53-nixos-reject-type1.conf + ln -s ${rejectType1} $support_folder/53-nixos-reject-type1.conf + ln -s ${rejectType1} $latest_folder/53-nixos-reject-type1.conf + ''} + ''; + in { diff --git a/nixos/modules/config/fonts/fontconfig.nix b/nixos/modules/config/fonts/fontconfig.nix index 4112250b2f46b..fe0b88cf4c266 100644 --- a/nixos/modules/config/fonts/fontconfig.nix +++ b/nixos/modules/config/fonts/fontconfig.nix @@ -14,250 +14,252 @@ Low number means high priority. */ -{ config, lib, pkgs, ... }: +{ config, pkgs, lib, ... }: with lib; -let cfg = config.fonts.fontconfig; - - fcBool = x: "<bool>" + (boolToString x) + "</bool>"; - - # back-supported fontconfig version and package - # version is used for font cache generation - supportVersion = "210"; - supportPkg = pkgs."fontconfig_${supportVersion}"; - - # latest fontconfig version and package - # version is used for configuration folder name, /etc/fonts/VERSION/ - # note: format differs from supportVersion and can not be used with makeCacheConf - latestVersion = pkgs.fontconfig.configVersion; - latestPkg = pkgs.fontconfig; - - # supported version fonts.conf - supportFontsConf = pkgs.makeFontsConf { fontconfig = supportPkg; fontDirectories = config.fonts.fonts; }; - - # configuration file to read fontconfig cache - # version dependent - # priority 0 - cacheConfSupport = makeCacheConf { version = supportVersion; }; - cacheConfLatest = makeCacheConf {}; - - # generate the font cache setting file for a fontconfig version - # use latest when no version is passed - makeCacheConf = { version ? null }: - let - fcPackage = if version == null - then "fontconfig" - else "fontconfig_${version}"; - makeCache = fontconfig: pkgs.makeFontsCache { inherit fontconfig; fontDirectories = config.fonts.fonts; }; - cache = makeCache pkgs.${fcPackage}; - cache32 = makeCache pkgs.pkgsi686Linux.${fcPackage}; - in - pkgs.writeText "fc-00-nixos-cache.conf" '' - <?xml version='1.0'?> - <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'> - <fontconfig> - <!-- Font directories --> - ${concatStringsSep "\n" (map (font: "<dir>${font}</dir>") config.fonts.fonts)} - <!-- Pre-generated font caches --> - <cachedir>${cache}</cachedir> - ${optionalString (pkgs.stdenv.isx86_64 && cfg.cache32Bit) '' - <cachedir>${cache32}</cachedir> - ''} - </fontconfig> - ''; - - # rendering settings configuration file - # priority 10 - renderConf = pkgs.writeText "fc-10-nixos-rendering.conf" '' +let + cfg = config.fonts.fontconfig; + + fcBool = x: "<bool>" + (boolToString x) + "</bool>"; + + # back-supported fontconfig version and package + # version is used for font cache generation + supportVersion = "210"; + supportPkg = pkgs."fontconfig_${supportVersion}"; + + # latest fontconfig version and package + # version is used for configuration folder name, /etc/fonts/VERSION/ + # note: format differs from supportVersion and can not be used with makeCacheConf + latestVersion = pkgs.fontconfig.configVersion; + latestPkg = pkgs.fontconfig; + + # supported version fonts.conf + supportFontsConf = pkgs.makeFontsConf { fontconfig = supportPkg; fontDirectories = config.fonts.fonts; }; + + # configuration file to read fontconfig cache + # version dependent + # priority 0 + cacheConfSupport = makeCacheConf { version = supportVersion; }; + cacheConfLatest = makeCacheConf {}; + + # generate the font cache setting file for a fontconfig version + # use latest when no version is passed + makeCacheConf = { version ? null }: + let + fcPackage = if version == null + then "fontconfig" + else "fontconfig_${version}"; + makeCache = fontconfig: pkgs.makeFontsCache { inherit fontconfig; fontDirectories = config.fonts.fonts; }; + cache = makeCache pkgs."${fcPackage}"; + cache32 = makeCache pkgs.pkgsi686Linux."${fcPackage}"; + in + pkgs.writeText "fc-00-nixos-cache.conf" '' <?xml version='1.0'?> <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'> <fontconfig> - - <!-- Default rendering settings --> - <match target="pattern"> - <edit mode="append" name="hinting"> - ${fcBool cfg.hinting.enable} - </edit> - <edit mode="append" name="autohint"> - ${fcBool cfg.hinting.autohint} - </edit> - <edit mode="append" name="hintstyle"> - <const>hintslight</const> - </edit> - <edit mode="append" name="antialias"> - ${fcBool cfg.antialias} - </edit> - <edit mode="append" name="rgba"> - <const>${cfg.subpixel.rgba}</const> - </edit> - <edit mode="append" name="lcdfilter"> - <const>lcd${cfg.subpixel.lcdfilter}</const> - </edit> - </match> - - ${optionalString (cfg.dpi != 0) '' - <match target="pattern"> - <edit name="dpi" mode="assign"> - <double>${toString cfg.dpi}</double> - </edit> - </match> + <!-- Font directories --> + ${concatStringsSep "\n" (map (font: "<dir>${font}</dir>") config.fonts.fonts)} + <!-- Pre-generated font caches --> + <cachedir>${cache}</cachedir> + ${optionalString (pkgs.stdenv.isx86_64 && cfg.cache32Bit) '' + <cachedir>${cache32}</cachedir> ''} - - </fontconfig> - ''; - - # local configuration file - # priority 51 - localConf = pkgs.writeText "fc-local.conf" cfg.localConf; - - # default fonts configuration file - # priority 52 - defaultFontsConf = - let genDefault = fonts: name: - optionalString (fonts != []) '' - <alias> - <family>${name}</family> - <prefer> - ${concatStringsSep "" - (map (font: '' - <family>${font}</family> - '') fonts)} - </prefer> - </alias> - ''; - in - pkgs.writeText "fc-52-nixos-default-fonts.conf" '' - <?xml version='1.0'?> - <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'> - <fontconfig> - - <!-- Default fonts --> - ${genDefault cfg.defaultFonts.sansSerif "sans-serif"} - - ${genDefault cfg.defaultFonts.serif "serif"} - - ${genDefault cfg.defaultFonts.monospace "monospace"} - </fontconfig> ''; - # bitmap font options - # priority 53 - rejectBitmaps = pkgs.writeText "fc-53-nixos-bitmaps.conf" '' - <?xml version="1.0"?> - <!DOCTYPE fontconfig SYSTEM "fonts.dtd"> - <fontconfig> - - ${optionalString (!cfg.allowBitmaps) '' - <!-- Reject bitmap fonts --> - <selectfont> - <rejectfont> - <pattern> - <patelt name="scalable"><bool>false</bool></patelt> - </pattern> - </rejectfont> - </selectfont> - ''} - - <!-- Use embedded bitmaps in fonts like Calibri? --> - <match target="font"> - <edit name="embeddedbitmap" mode="assign"> - ${fcBool cfg.useEmbeddedBitmaps} + # rendering settings configuration file + # priority 10 + renderConf = pkgs.writeText "fc-10-nixos-rendering.conf" '' + <?xml version='1.0'?> + <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'> + <fontconfig> + + <!-- Default rendering settings --> + <match target="pattern"> + <edit mode="append" name="hinting"> + ${fcBool cfg.hinting.enable} + </edit> + <edit mode="append" name="autohint"> + ${fcBool cfg.hinting.autohint} + </edit> + <edit mode="append" name="hintstyle"> + <const>hintslight</const> + </edit> + <edit mode="append" name="antialias"> + ${fcBool cfg.antialias} + </edit> + <edit mode="append" name="rgba"> + <const>${cfg.subpixel.rgba}</const> + </edit> + <edit mode="append" name="lcdfilter"> + <const>lcd${cfg.subpixel.lcdfilter}</const> </edit> </match> - </fontconfig> - ''; - - # reject Type 1 fonts - # priority 53 - rejectType1 = pkgs.writeText "fc-53-nixos-reject-type1.conf" '' - <?xml version="1.0"?> - <!DOCTYPE fontconfig SYSTEM "fonts.dtd"> - <fontconfig> - - <!-- Reject Type 1 fonts --> - <selectfont> - <rejectfont> - <pattern> - <patelt name="fontformat"><string>Type 1</string></patelt> - </pattern> - </rejectfont> - </selectfont> - - </fontconfig> - ''; - - # fontconfig configuration package - confPkg = pkgs.runCommand "fontconfig-conf" { preferLocalBuild = true; } '' - support_folder=$out/etc/fonts - latest_folder=$out/etc/fonts/${latestVersion} - - mkdir -p $support_folder/conf.d - mkdir -p $latest_folder/conf.d - - # fonts.conf - ln -s ${supportFontsConf} $support_folder/fonts.conf - ln -s ${latestPkg.out}/etc/fonts/fonts.conf \ - $latest_folder/fonts.conf - - # fontconfig default config files - ln -s ${supportPkg.out}/etc/fonts/conf.d/*.conf \ - $support_folder/conf.d/ - ln -s ${latestPkg.out}/etc/fonts/conf.d/*.conf \ - $latest_folder/conf.d/ - - # update latest 51-local.conf path to look at the latest local.conf - rm $latest_folder/conf.d/51-local.conf - - substitute ${latestPkg.out}/etc/fonts/conf.d/51-local.conf \ - $latest_folder/conf.d/51-local.conf \ - --replace local.conf /etc/fonts/${latestVersion}/local.conf - - # 00-nixos-cache.conf - ln -s ${cacheConfSupport} \ - $support_folder/conf.d/00-nixos-cache.conf - ln -s ${cacheConfLatest} $latest_folder/conf.d/00-nixos-cache.conf - - # 10-nixos-rendering.conf - ln -s ${renderConf} $support_folder/conf.d/10-nixos-rendering.conf - ln -s ${renderConf} $latest_folder/conf.d/10-nixos-rendering.conf - - # 50-user.conf - ${optionalString (! cfg.includeUserConf) '' - rm $support_folder/conf.d/50-user.conf - rm $latest_folder/conf.d/50-user.conf - ''} - - # local.conf (indirect priority 51) - ${optionalString (cfg.localConf != "") '' - ln -s ${localConf} $support_folder/local.conf - ln -s ${localConf} $latest_folder/local.conf - ''} - - # 52-nixos-default-fonts.conf - ln -s ${defaultFontsConf} $support_folder/conf.d/52-nixos-default-fonts.conf - ln -s ${defaultFontsConf} $latest_folder/conf.d/52-nixos-default-fonts.conf - - # 53-nixos-bitmaps.conf - ln -s ${rejectBitmaps} $support_folder/conf.d/53-nixos-bitmaps.conf - ln -s ${rejectBitmaps} $latest_folder/conf.d/53-nixos-bitmaps.conf - - ${optionalString (! cfg.allowType1) '' - # 53-nixos-reject-type1.conf - ln -s ${rejectType1} $support_folder/conf.d/53-nixos-reject-type1.conf - ln -s ${rejectType1} $latest_folder/conf.d/53-nixos-reject-type1.conf + ${optionalString (cfg.dpi != 0) '' + <match target="pattern"> + <edit name="dpi" mode="assign"> + <double>${toString cfg.dpi}</double> + </edit> + </match> ''} - ''; - # Package with configuration files - # this merge all the packages in the fonts.fontconfig.confPackages list - fontconfigEtc = pkgs.buildEnv { - name = "fontconfig-etc"; - paths = cfg.confPackages; - ignoreCollisions = true; - }; + </fontconfig> + ''; + + # local configuration file + localConf = pkgs.writeText "fc-local.conf" cfg.localConf; + + # default fonts configuration file + # priority 52 + defaultFontsConf = + let genDefault = fonts: name: + optionalString (fonts != []) '' + <alias> + <family>${name}</family> + <prefer> + ${concatStringsSep "" + (map (font: '' + <family>${font}</family> + '') fonts)} + </prefer> + </alias> + ''; + in + pkgs.writeText "fc-52-nixos-default-fonts.conf" '' + <?xml version='1.0'?> + <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'> + <fontconfig> + + <!-- Default fonts --> + ${genDefault cfg.defaultFonts.sansSerif "sans-serif"} + + ${genDefault cfg.defaultFonts.serif "serif"} + + ${genDefault cfg.defaultFonts.monospace "monospace"} + + </fontconfig> + ''; + + # bitmap font options + # priority 53 + rejectBitmaps = pkgs.writeText "fc-53-no-bitmaps.conf" '' + <?xml version="1.0"?> + <!DOCTYPE fontconfig SYSTEM "fonts.dtd"> + <fontconfig> + + ${optionalString (!cfg.allowBitmaps) '' + <!-- Reject bitmap fonts --> + <selectfont> + <rejectfont> + <pattern> + <patelt name="scalable"><bool>false</bool></patelt> + </pattern> + </rejectfont> + </selectfont> + ''} + + <!-- Use embedded bitmaps in fonts like Calibri? --> + <match target="font"> + <edit name="embeddedbitmap" mode="assign"> + ${fcBool cfg.useEmbeddedBitmaps} + </edit> + </match> + + </fontconfig> + ''; + + # reject Type 1 fonts + # priority 53 + rejectType1 = pkgs.writeText "fc-53-nixos-reject-type1.conf" '' + <?xml version="1.0"?> + <!DOCTYPE fontconfig SYSTEM "fonts.dtd"> + <fontconfig> + + <!-- Reject Type 1 fonts --> + <selectfont> + <rejectfont> + <pattern> + <patelt name="fontformat"><string>Type 1</string></patelt> + </pattern> + </rejectfont> + </selectfont> + + </fontconfig> + ''; + + # fontconfig configuration package + confPkg = pkgs.runCommand "fontconfig-conf" { + preferLocalBuild = true; + } '' + support_folder=$out/etc/fonts/conf.d + latest_folder=$out/etc/fonts/${latestVersion}/conf.d + + mkdir -p $support_folder + mkdir -p $latest_folder + + # fonts.conf + ln -s ${supportFontsConf} $support_folder/../fonts.conf + ln -s ${latestPkg.out}/etc/fonts/fonts.conf \ + $latest_folder/../fonts.conf + + # fontconfig default config files + ln -s ${supportPkg.out}/etc/fonts/conf.d/*.conf \ + $support_folder/ + ln -s ${latestPkg.out}/etc/fonts/conf.d/*.conf \ + $latest_folder/ + + # update latest 51-local.conf path to look at the latest local.conf + rm $latest_folder/51-local.conf + + substitute ${latestPkg.out}/etc/fonts/conf.d/51-local.conf \ + $latest_folder/51-local.conf \ + --replace local.conf /etc/fonts/${latestVersion}/local.conf + + # 00-nixos-cache.conf + ln -s ${cacheConfSupport} \ + $support_folder/00-nixos-cache.conf + ln -s ${cacheConfLatest} $latest_folder/00-nixos-cache.conf + + # 10-nixos-rendering.conf + ln -s ${renderConf} $support_folder/10-nixos-rendering.conf + ln -s ${renderConf} $latest_folder/10-nixos-rendering.conf + + # 50-user.conf + ${optionalString (!cfg.includeUserConf) '' + rm $support_folder/50-user.conf + rm $latest_folder/50-user.conf + ''} + + # local.conf (indirect priority 51) + ${optionalString (cfg.localConf != "") '' + ln -s ${localConf} $support_folder/../local.conf + ln -s ${localConf} $latest_folder/../local.conf + ''} + + # 52-nixos-default-fonts.conf + ln -s ${defaultFontsConf} $support_folder/52-nixos-default-fonts.conf + ln -s ${defaultFontsConf} $latest_folder/52-nixos-default-fonts.conf + + # 53-no-bitmaps.conf + ln -s ${rejectBitmaps} $support_folder/53-no-bitmaps.conf + ln -s ${rejectBitmaps} $latest_folder/53-no-bitmaps.conf + + ${optionalString (!cfg.allowType1) '' + # 53-nixos-reject-type1.conf + ln -s ${rejectType1} $support_folder/53-nixos-reject-type1.conf + ln -s ${rejectType1} $latest_folder/53-nixos-reject-type1.conf + ''} + ''; + + # Package with configuration files + # this merge all the packages in the fonts.fontconfig.confPackages list + fontconfigEtc = pkgs.buildEnv { + name = "fontconfig-etc"; + paths = cfg.confPackages; + ignoreCollisions = true; + }; in { diff --git a/nixos/modules/config/qt5.nix b/nixos/modules/config/qt5.nix new file mode 100644 index 0000000000000..7de1c0f5d5574 --- /dev/null +++ b/nixos/modules/config/qt5.nix @@ -0,0 +1,102 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.qt5; + + isQGnome = cfg.platformTheme == "gnome" && cfg.style == "adwaita"; + isQtStyle = cfg.platformTheme == "gtk2" && cfg.style != "adwaita"; + + packages = if isQGnome then [ pkgs.qgnomeplatform pkgs.adwaita-qt ] + else if isQtStyle then [ pkgs.qtstyleplugins ] + else throw "`qt5.platformTheme` ${cfg.platformTheme} and `qt5.style` ${cfg.style} are not compatible."; + +in + +{ + + options = { + qt5 = { + + enable = mkEnableOption "Qt5 theming configuration"; + + platformTheme = mkOption { + type = types.enum [ + "gtk2" + "gnome" + ]; + example = "gnome"; + relatedPackages = [ + "qgnomeplatform" + ["libsForQt5" "qtstyleplugins"] + ]; + description = '' + Selects the platform theme to use for Qt5 applications.</para> + <para>The options are + <variablelist> + <varlistentry> + <term><literal>gtk</literal></term> + <listitem><para>Use GTK theme with + <link xlink:href="https://github.com/qt/qtstyleplugins">qtstyleplugins</link> + </para></listitem> + </varlistentry> + <varlistentry> + <term><literal>gnome</literal></term> + <listitem><para>Use GNOME theme with + <link xlink:href="https://github.com/FedoraQt/QGnomePlatform">qgnomeplatform</link> + </para></listitem> + </varlistentry> + </variablelist> + ''; + }; + + style = mkOption { + type = types.enum [ + "adwaita" + "cleanlooks" + "gtk2" + "motif" + "plastique" + ]; + example = "adwaita"; + relatedPackages = [ + "adwaita-qt" + ["libsForQt5" "qtstyleplugins"] + ]; + description = '' + Selects the style to use for Qt5 applications.</para> + <para>The options are + <variablelist> + <varlistentry> + <term><literal>adwaita</literal></term> + <listitem><para>Use Adwaita Qt style with + <link xlink:href="https://github.com/FedoraQt/adwaita-qt">adwaita</link> + </para></listitem> + </varlistentry> + <varlistentry> + <term><literal>cleanlooks</literal></term> + <term><literal>gtk2</literal></term> + <term><literal>motif</literal></term> + <term><literal>plastique</literal></term> + <listitem><para>Use styles from + <link xlink:href="https://github.com/qt/qtstyleplugins">qtstyleplugins</link> + </para></listitem> + </varlistentry> + </variablelist> + ''; + }; + }; + }; + + config = mkIf cfg.enable { + + environment.variables.QT_QPA_PLATFORMTHEME = cfg.platformTheme; + + environment.variables.QT_STYLE_OVERRIDE = cfg.style; + + environment.systemPackages = packages; + + }; +} diff --git a/nixos/modules/config/sysctl.nix b/nixos/modules/config/sysctl.nix index 0c6a7e2431aa6..fb2b58eed7203 100644 --- a/nixos/modules/config/sysctl.nix +++ b/nixos/modules/config/sysctl.nix @@ -42,22 +42,16 @@ in config = { - environment.etc."sysctl.d/nixos.conf".text = + environment.etc."sysctl.d/60-nixos.conf".text = concatStrings (mapAttrsToList (n: v: optionalString (v != null) "${n}=${if v == false then "0" else toString v}\n" ) config.boot.kernel.sysctl); systemd.services.systemd-sysctl = { wantedBy = [ "multi-user.target" ]; - restartTriggers = [ config.environment.etc."sysctl.d/nixos.conf".source ]; + restartTriggers = [ config.environment.etc."sysctl.d/60-nixos.conf".source ]; }; - # Enable hardlink and symlink restrictions. See - # https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=800179c9b8a1e796e441674776d11cd4c05d61d7 - # for details. - boot.kernel.sysctl."fs.protected_hardlinks" = true; - boot.kernel.sysctl."fs.protected_symlinks" = true; - # Hide kernel pointers (e.g. in /proc/modules) for unprivileged # users as these make it easier to exploit kernel vulnerabilities. boot.kernel.sysctl."kernel.kptr_restrict" = 1; diff --git a/nixos/modules/config/update-users-groups.pl b/nixos/modules/config/update-users-groups.pl index ef5e6346f02e7..59cea51c611b4 100644 --- a/nixos/modules/config/update-users-groups.pl +++ b/nixos/modules/config/update-users-groups.pl @@ -267,6 +267,7 @@ foreach my $line (-f "/etc/shadow" ? read_file("/etc/shadow") : ()) { next if !defined $u; $hashedPassword = "!" if !$spec->{mutableUsers}; $hashedPassword = $u->{hashedPassword} if defined $u->{hashedPassword} && !$spec->{mutableUsers}; # FIXME + chomp $hashedPassword; push @shadowNew, join(":", $name, $hashedPassword, @rest) . "\n"; $shadowSeen{$name} = 1; } diff --git a/nixos/modules/config/vte.nix b/nixos/modules/config/vte.nix new file mode 100644 index 0000000000000..d4a8c926fef2e --- /dev/null +++ b/nixos/modules/config/vte.nix @@ -0,0 +1,52 @@ +# VTE + +{ config, pkgs, lib, ... }: + +with lib; + +let + + vteInitSnippet = '' + # Show current working directory in VTE terminals window title. + # Supports both bash and zsh, requires interactive shell. + . ${pkgs.vte}/etc/profile.d/vte.sh + ''; + +in + +{ + + options = { + + programs.bash.vteIntegration = mkOption { + default = false; + type = types.bool; + description = '' + Whether to enable Bash integration for VTE terminals. + This allows it to preserve the current directory of the shell + across terminals. + ''; + }; + + programs.zsh.vteIntegration = mkOption { + default = false; + type = types.bool; + description = '' + Whether to enable Zsh integration for VTE terminals. + This allows it to preserve the current directory of the shell + across terminals. + ''; + }; + + }; + + config = mkMerge [ + (mkIf config.programs.bash.vteIntegration { + programs.bash.interactiveShellInit = mkBefore vteInitSnippet; + }) + + (mkIf config.programs.zsh.vteIntegration { + programs.zsh.interactiveShellInit = vteInitSnippet; + }) + ]; +} diff --git a/nixos/modules/installer/cd-dvd/sd-image.nix b/nixos/modules/installer/cd-dvd/sd-image.nix index 0c407b199367d..7f355a132496c 100644 --- a/nixos/modules/installer/cd-dvd/sd-image.nix +++ b/nixos/modules/installer/cd-dvd/sd-image.nix @@ -73,8 +73,8 @@ in firmwareSize = mkOption { type = types.int; - # As of 2019-05-31 the Raspberry pi firmware + u-bot takes ~13MiB - default = 20; + # As of 2019-08-18 the Raspberry pi firmware + u-boot takes ~18MiB + default = 30; description = '' Size of the /boot/firmware partition, in megabytes. ''; diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index 1047df95cdf57..efd8544d6a211 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -251,7 +251,7 @@ gale = 223; matrix-synapse = 224; rspamd = 225; - rmilter = 226; + # rmilter = 226; # unused, removed 2019-08-22 cfdyndns = 227; gammu-smsd = 228; pdnsd = 229; @@ -340,6 +340,7 @@ cockroachdb = 313; zoneminder = 314; paperless = 315; + mailman = 316; # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399! @@ -559,7 +560,7 @@ gale = 223; matrix-synapse = 224; rspamd = 225; - rmilter = 226; + # rmilter = 226; # unused, removed 2019-08-22 cfdyndns = 227; pdnsd = 229; octoprint = 230; @@ -640,6 +641,7 @@ cockroachdb = 313; zoneminder = 314; paperless = 315; + mailman = 316; # When adding a gid, make sure it doesn't match an existing # uid. Users and groups with the same name should have equal diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index a167336c156bb..6331e76c648fa 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -27,6 +27,7 @@ ./config/nsswitch.nix ./config/power-management.nix ./config/pulseaudio.nix + ./config/qt5.nix ./config/resolvconf.nix ./config/shells-environment.nix ./config/swap.nix @@ -37,6 +38,7 @@ ./config/unix-odbc-drivers.nix ./config/users-groups.nix ./config/vpnc.nix + ./config/vte.nix ./config/zram.nix ./hardware/acpilight.nix ./hardware/all-firmware.nix @@ -115,6 +117,7 @@ ./programs/fuse.nix ./programs/gnome-disks.nix ./programs/gnome-documents.nix + ./programs/gnome-terminal.nix ./programs/gpaste.nix ./programs/gnupg.nix ./programs/gphoto2.nix @@ -285,6 +288,7 @@ ./services/desktops/flatpak.nix ./services/desktops/geoclue2.nix ./services/desktops/gsignond.nix + ./services/desktops/gvfs.nix ./services/desktops/pipewire.nix ./services/desktops/gnome3/at-spi2-core.nix ./services/desktops/gnome3/chrome-gnome-shell.nix @@ -295,9 +299,7 @@ ./services/desktops/gnome3/gnome-remote-desktop.nix ./services/desktops/gnome3/gnome-online-miners.nix ./services/desktops/gnome3/gnome-settings-daemon.nix - ./services/desktops/gnome3/gnome-terminal-server.nix ./services/desktops/gnome3/gnome-user-share.nix - ./services/desktops/gnome3/gvfs.nix ./services/desktops/gnome3/rygel.nix ./services/desktops/gnome3/seahorse.nix ./services/desktops/gnome3/sushi.nix @@ -385,7 +387,6 @@ ./services/mail/spamassassin.nix ./services/mail/rspamd.nix ./services/mail/rss2email.nix - ./services/mail/rmilter.nix ./services/mail/roundcube.nix ./services/mail/nullmailer.nix ./services/misc/airsonic.nix @@ -436,13 +437,13 @@ ./services/misc/logkeys.nix ./services/misc/leaps.nix ./services/misc/lidarr.nix - ./services/misc/mantisbt.nix ./services/misc/mathics.nix ./services/misc/matrix-synapse.nix ./services/misc/mbpfan.nix ./services/misc/mediatomb.nix ./services/misc/mesos-master.nix ./services/misc/mesos-slave.nix + ./services/misc/metabase.nix ./services/misc/mwlib.nix ./services/misc/nix-daemon.nix ./services/misc/nix-gc.nix @@ -520,7 +521,6 @@ ./services/monitoring/scollector.nix ./services/monitoring/smartd.nix ./services/monitoring/sysstat.nix - ./services/monitoring/systemhealth.nix ./services/monitoring/teamviewer.nix ./services/monitoring/telegraf.nix ./services/monitoring/thanos.nix @@ -608,6 +608,7 @@ ./services/networking/iodine.nix ./services/networking/iperf3.nix ./services/networking/ircd-hybrid/default.nix + ./services/networking/jormungandr.nix ./services/networking/iwd.nix ./services/networking/keepalived/default.nix ./services/networking/keybase.nix @@ -647,6 +648,7 @@ ./services/networking/nullidentdmod.nix ./services/networking/nylon.nix ./services/networking/ocserv.nix + ./services/networking/ofono.nix ./services/networking/oidentd.nix ./services/networking/openfire.nix ./services/networking/openntpd.nix @@ -787,6 +789,7 @@ ./services/web-apps/mattermost.nix ./services/web-apps/mediawiki.nix ./services/web-apps/miniflux.nix + ./services/web-apps/moodle.nix ./services/web-apps/nextcloud.nix ./services/web-apps/nexus.nix ./services/web-apps/pgpkeyserver-lite.nix @@ -800,6 +803,7 @@ ./services/web-apps/zabbix.nix ./services/web-servers/apache-httpd/default.nix ./services/web-servers/caddy.nix + ./services/web-servers/darkhttpd.nix ./services/web-servers/fcgiwrap.nix ./services/web-servers/hitch/default.nix ./services/web-servers/hydron.nix @@ -862,7 +866,6 @@ ./system/activation/activation-script.nix ./system/activation/top-level.nix ./system/boot/binfmt.nix - ./system/boot/coredump.nix ./system/boot/emergency-mode.nix ./system/boot/grow-partition.nix ./system/boot/initrd-network.nix diff --git a/nixos/modules/profiles/hardened.nix b/nixos/modules/profiles/hardened.nix index 3ff9a2b4fde04..626d8b1d2bde5 100644 --- a/nixos/modules/profiles/hardened.nix +++ b/nixos/modules/profiles/hardened.nix @@ -14,8 +14,6 @@ with lib; nix.allowedUsers = mkDefault [ "@users" ]; - environment.memoryAllocator.provider = mkDefault "graphene-hardened"; - security.hideProcessInformation = mkDefault true; security.lockKernelModules = mkDefault true; @@ -95,23 +93,17 @@ with lib; # Disable ftrace debugging boot.kernel.sysctl."kernel.ftrace_enabled" = mkDefault false; - # Enable reverse path filtering (that is, do not attempt to route packets - # that "obviously" do not belong to the iface's network; dropped packets are - # logged as martians). + # Enable strict reverse path filtering (that is, do not attempt to route + # packets that "obviously" do not belong to the iface's network; dropped + # packets are logged as martians). boot.kernel.sysctl."net.ipv4.conf.all.log_martians" = mkDefault true; - boot.kernel.sysctl."net.ipv4.conf.all.rp_filter" = mkDefault true; + boot.kernel.sysctl."net.ipv4.conf.all.rp_filter" = mkDefault "1"; boot.kernel.sysctl."net.ipv4.conf.default.log_martians" = mkDefault true; - boot.kernel.sysctl."net.ipv4.conf.default.rp_filter" = mkDefault true; + boot.kernel.sysctl."net.ipv4.conf.default.rp_filter" = mkDefault "1"; # Ignore broadcast ICMP (mitigate SMURF) boot.kernel.sysctl."net.ipv4.icmp_echo_ignore_broadcasts" = mkDefault true; - # Ignore route information from sender - boot.kernel.sysctl."net.ipv4.conf.all.accept_source_route" = mkDefault false; - boot.kernel.sysctl."net.ipv4.conf.default.accept_source_route" = mkDefault false; - boot.kernel.sysctl."net.ipv6.conf.all.accept_source_route" = mkDefault false; - boot.kernel.sysctl."net.ipv6.conf.default.accept_source_route" = mkDefault false; - # Ignore incoming ICMP redirects (note: default is needed to ensure that the # setting is applied to interfaces added after the sysctls are set) boot.kernel.sysctl."net.ipv4.conf.all.accept_redirects" = mkDefault false; diff --git a/nixos/modules/programs/dconf.nix b/nixos/modules/programs/dconf.nix index b7bfb8504b6f1..eeebc3558bdf9 100644 --- a/nixos/modules/programs/dconf.nix +++ b/nixos/modules/programs/dconf.nix @@ -34,11 +34,11 @@ in services.dbus.packages = [ pkgs.gnome3.dconf ]; - environment.variables.GIO_EXTRA_MODULES = optional cfg.enable - "${pkgs.gnome3.dconf.lib}/lib/gio/modules"; - # https://github.com/NixOS/nixpkgs/pull/31891 - #environment.variables.XDG_DATA_DIRS = optional cfg.enable - # "$(echo ${pkgs.gsettings-desktop-schemas}/share/gsettings-schemas/gsettings-desktop-schemas-*)"; + # For dconf executable + environment.systemPackages = [ pkgs.gnome3.dconf ]; + + # Needed for unwrapped applications + environment.variables.GIO_EXTRA_MODULES = mkIf cfg.enable [ "${pkgs.gnome3.dconf.lib}/lib/gio/modules" ]; }; } diff --git a/nixos/modules/programs/environment.nix b/nixos/modules/programs/environment.nix index 4d762314298d0..66eb834826649 100644 --- a/nixos/modules/programs/environment.nix +++ b/nixos/modules/programs/environment.nix @@ -21,6 +21,7 @@ in PAGER = mkDefault "less -R"; EDITOR = mkDefault "nano"; XCURSOR_PATH = [ "$HOME/.icons" ]; + XDG_CONFIG_DIRS = [ "/etc/xdg" ]; # needs to be before profile-relative paths to allow changes through environment.etc }; environment.profiles = mkAfter diff --git a/nixos/modules/programs/gnome-terminal.nix b/nixos/modules/programs/gnome-terminal.nix new file mode 100644 index 0000000000000..0036677a15765 --- /dev/null +++ b/nixos/modules/programs/gnome-terminal.nix @@ -0,0 +1,36 @@ +# GNOME Terminal. + +{ config, pkgs, lib, ... }: + +with lib; + +let + + cfg = config.programs.gnome-terminal; + +in + +{ + + # Added 2019-08-19 + imports = [ + (mkRenamedOptionModule + [ "services" "gnome3" "gnome-terminal-server" "enable" ] + [ "programs" "gnome-terminal" "enable" ]) + ]; + + options = { + + programs.gnome-terminal.enable = mkEnableOption "GNOME Terminal"; + + }; + + config = mkIf cfg.enable { + environment.systemPackages = [ pkgs.gnome3.gnome-terminal ]; + services.dbus.packages = [ pkgs.gnome3.gnome-terminal ]; + systemd.packages = [ pkgs.gnome3.gnome-terminal ]; + + programs.bash.vteIntegration = true; + programs.zsh.vteIntegration = true; + }; +} diff --git a/nixos/modules/programs/gnupg.nix b/nixos/modules/programs/gnupg.nix index 9618d61a1f5bb..bcbc994efe9b3 100644 --- a/nixos/modules/programs/gnupg.nix +++ b/nixos/modules/programs/gnupg.nix @@ -83,7 +83,8 @@ in systemd.user.sockets.dirmngr = mkIf cfg.dirmngr.enable { wantedBy = [ "sockets.target" ]; }; - + + environment.systemPackages = with pkgs; [ cfg.package ]; systemd.packages = [ cfg.package ]; environment.interactiveShellInit = '' diff --git a/nixos/modules/programs/zsh/zsh.nix b/nixos/modules/programs/zsh/zsh.nix index 3f0c8262429aa..9816436cf954c 100644 --- a/nixos/modules/programs/zsh/zsh.nix +++ b/nixos/modules/programs/zsh/zsh.nix @@ -69,9 +69,7 @@ in promptInit = mkOption { default = '' - if [ "$TERM" != dumb ]; then - autoload -U promptinit && promptinit && prompt walters - fi + autoload -U promptinit && promptinit && prompt walters && setopt prompt_sp ''; description = '' Shell script code used to initialise the zsh prompt. @@ -213,6 +211,15 @@ in ${cfg.promptInit} + # Need to disable features to support TRAMP + if [ "$TERM" = dumb ]; then + unsetopt zle prompt_cr prompt_subst + unfunction precmd preexec + unset RPS1 RPROMPT + PS1='$ ' + PROMPT='$ ' + fi + # Read system-wide modifications. if test -f /etc/zshrc.local; then . /etc/zshrc.local diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix index 5c08a25c128ab..348ad094e5ad9 100644 --- a/nixos/modules/rename.nix +++ b/nixos/modules/rename.nix @@ -72,8 +72,8 @@ with lib; # PAM (mkRenamedOptionModule [ "security" "pam" "enableU2F" ] [ "security" "pam" "u2f" "enable" ]) - (mkRemovedOptionModule [ "services" "rmilter" "bindInetSockets" ] "Use services.rmilter.bindSocket.* instead") - (mkRemovedOptionModule [ "services" "rmilter" "bindUnixSockets" ] "Use services.rmilter.bindSocket.* instead") + # rmilter/rspamd + (mkRemovedOptionModule [ "services" "rmilter" ] "Use services.rspamd.* instead to set up milter service") # Xsession script (mkRenamedOptionModule [ "services" "xserver" "displayManager" "job" "logsXsession" ] [ "services" "xserver" "displayManager" "job" "logToFile" ]) @@ -178,6 +178,9 @@ with lib; The starting time can be configured via <literal>services.postgresqlBackup.startAt</literal>. '') + # phpfpm + (mkRemovedOptionModule [ "services" "phpfpm" "poolConfigs" ] "Use services.phpfpm.pools instead.") + # zabbixServer (mkRenamedOptionModule [ "services" "zabbixServer" "dbServer" ] [ "services" "zabbixServer" "database" "host" ]) @@ -226,6 +229,7 @@ with lib; (mkRemovedOptionModule [ "services" "mysql" "rootPassword" ] "Use socket authentication or set the password outside of the nix store.") (mkRemovedOptionModule [ "services" "zabbixServer" "dbPassword" ] "Use services.zabbixServer.database.passwordFile instead.") (mkRemovedOptionModule [ "systemd" "generator-packages" ] "Use systemd.packages instead.") + (mkRemovedOptionModule [ "systemd" "coredump" "enable" ] "Enabled by default. Set boot.kernel.sysctl.\"kernel.core_pattern\" = \"core\"; to disable.") # ZSH (mkRenamedOptionModule [ "programs" "zsh" "enableSyntaxHighlighting" ] [ "programs" "zsh" "syntaxHighlighting" "enable" ]) @@ -276,7 +280,7 @@ with lib; throw "services.redshift.longitude is set to null, you can remove this" else builtins.fromJSON value)) - ] ++ (flip map [ "blackboxExporter" "collectdExporter" "fritzboxExporter" + ] ++ (forEach [ "blackboxExporter" "collectdExporter" "fritzboxExporter" "jsonExporter" "minioExporter" "nginxExporter" "nodeExporter" "snmpExporter" "unifiExporter" "varnishExporter" ] (opt: mkRemovedOptionModule [ "services" "prometheus" "${opt}" ] '' diff --git a/nixos/modules/services/audio/roon-server.nix b/nixos/modules/services/audio/roon-server.nix index 9562ad1b164e4..d4b0b098b78e9 100644 --- a/nixos/modules/services/audio/roon-server.nix +++ b/nixos/modules/services/audio/roon-server.nix @@ -19,6 +19,20 @@ in { TCP: 9100 - 9200 ''; }; + user = mkOption { + type = types.str; + default = "roon-server"; + description = '' + User to run the Roon Server as. + ''; + }; + group = mkOption { + type = types.str; + default = "roon-server"; + description = '' + Group to run the Roon Server as. + ''; + }; }; }; @@ -33,8 +47,8 @@ in { serviceConfig = { ExecStart = "${pkgs.roon-server}/opt/start.sh"; LimitNOFILE = 8192; - DynamicUser = true; - SupplementaryGroups = "audio"; + User = cfg.user; + Group = cfg.group; StateDirectory = name; }; }; @@ -45,5 +59,15 @@ in { ]; allowedUDPPorts = [ 9003 ]; }; + + + users.groups."${cfg.group}" = {}; + users.users."${cfg.user}" = + if cfg.user == "roon-server" then { + isSystemUser = true; + description = "Roon Server user"; + groups = [ cfg.group "audio" ]; + } + else {}; }; } diff --git a/nixos/modules/services/databases/memcached.nix b/nixos/modules/services/databases/memcached.nix index f9e403dfc0c20..84d2c8674f4eb 100644 --- a/nixos/modules/services/databases/memcached.nix +++ b/nixos/modules/services/databases/memcached.nix @@ -103,7 +103,6 @@ in LockPersonality = true; RestrictRealtime = true; PrivateMounts = true; - PrivateUsers = true; MemoryDenyWriteExecute = true; }; }; diff --git a/nixos/modules/services/desktops/gnome3/gnome-online-accounts.nix b/nixos/modules/services/desktops/gnome3/gnome-online-accounts.nix index 4286251357f7e..748a025414a78 100644 --- a/nixos/modules/services/desktops/gnome3/gnome-online-accounts.nix +++ b/nixos/modules/services/desktops/gnome3/gnome-online-accounts.nix @@ -30,9 +30,9 @@ with lib; config = mkIf config.services.gnome3.gnome-online-accounts.enable { - environment.systemPackages = [ pkgs.gnome3.gnome-online-accounts ]; + environment.systemPackages = [ pkgs.gnome-online-accounts ]; - services.dbus.packages = [ pkgs.gnome3.gnome-online-accounts ]; + services.dbus.packages = [ pkgs.gnome-online-accounts ]; }; diff --git a/nixos/modules/services/desktops/gnome3/gnome-terminal-server.nix b/nixos/modules/services/desktops/gnome3/gnome-terminal-server.nix deleted file mode 100644 index fd14efee5f2ea..0000000000000 --- a/nixos/modules/services/desktops/gnome3/gnome-terminal-server.nix +++ /dev/null @@ -1,41 +0,0 @@ -# GNOME Documents daemon. - -{ config, pkgs, lib, ... }: - -with lib; - -{ - - ###### interface - - options = { - - services.gnome3.gnome-terminal-server = { - - enable = mkOption { - type = types.bool; - default = false; - description = '' - Whether to enable GNOME Terminal server service, - needed for gnome-terminal. - ''; - }; - - }; - - }; - - - ###### implementation - - config = mkIf config.services.gnome3.gnome-terminal-server.enable { - - environment.systemPackages = [ pkgs.gnome3.gnome-terminal ]; - - services.dbus.packages = [ pkgs.gnome3.gnome-terminal ]; - - systemd.packages = [ pkgs.gnome3.gnome-terminal ]; - - }; - -} diff --git a/nixos/modules/services/desktops/gnome3/gvfs.nix b/nixos/modules/services/desktops/gnome3/gvfs.nix deleted file mode 100644 index 4e99d191f18c7..0000000000000 --- a/nixos/modules/services/desktops/gnome3/gvfs.nix +++ /dev/null @@ -1,43 +0,0 @@ -# gvfs backends - -{ config, lib, pkgs, ... }: - -with lib; - -{ - - ###### interface - - options = { - - services.gnome3.gvfs = { - - enable = mkOption { - type = types.bool; - default = false; - description = '' - Whether to enable gvfs backends, userspace virtual filesystem used - by GNOME components via D-Bus. - ''; - }; - - }; - - }; - - - ###### implementation - - config = mkIf config.services.gnome3.gvfs.enable { - - environment.systemPackages = [ pkgs.gnome3.gvfs ]; - - services.dbus.packages = [ pkgs.gnome3.gvfs ]; - - systemd.packages = [ pkgs.gnome3.gvfs ]; - - services.udev.packages = [ pkgs.libmtp.bin ]; - - }; - -} diff --git a/nixos/modules/services/desktops/gnome3/tracker-miners.nix b/nixos/modules/services/desktops/gnome3/tracker-miners.nix index 20154fc2fed35..b390d8368c652 100644 --- a/nixos/modules/services/desktops/gnome3/tracker-miners.nix +++ b/nixos/modules/services/desktops/gnome3/tracker-miners.nix @@ -30,11 +30,11 @@ with lib; config = mkIf config.services.gnome3.tracker-miners.enable { - environment.systemPackages = [ pkgs.gnome3.tracker-miners ]; + environment.systemPackages = [ pkgs.tracker-miners ]; - services.dbus.packages = [ pkgs.gnome3.tracker-miners ]; + services.dbus.packages = [ pkgs.tracker-miners ]; - systemd.packages = [ pkgs.gnome3.tracker-miners ]; + systemd.packages = [ pkgs.tracker-miners ]; }; diff --git a/nixos/modules/services/desktops/gnome3/tracker.nix b/nixos/modules/services/desktops/gnome3/tracker.nix index c061f78904994..2e82927422644 100644 --- a/nixos/modules/services/desktops/gnome3/tracker.nix +++ b/nixos/modules/services/desktops/gnome3/tracker.nix @@ -30,11 +30,11 @@ with lib; config = mkIf config.services.gnome3.tracker.enable { - environment.systemPackages = [ pkgs.gnome3.tracker ]; + environment.systemPackages = [ pkgs.tracker ]; - services.dbus.packages = [ pkgs.gnome3.tracker ]; + services.dbus.packages = [ pkgs.tracker ]; - systemd.packages = [ pkgs.gnome3.tracker ]; + systemd.packages = [ pkgs.tracker ]; }; diff --git a/nixos/modules/services/desktops/gvfs.nix b/nixos/modules/services/desktops/gvfs.nix new file mode 100644 index 0000000000000..1d002eac41def --- /dev/null +++ b/nixos/modules/services/desktops/gvfs.nix @@ -0,0 +1,59 @@ +# GVfs + +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.gvfs; + +in + +{ + + # Added 2019-08-19 + imports = [ + (mkRenamedOptionModule + [ "services" "gnome3" "gvfs" "enable" ] + [ "services" "gvfs" "enable" ]) + ]; + + ###### interface + + options = { + + services.gvfs = { + + enable = mkEnableOption "GVfs, a userspace virtual filesystem"; + + # gvfs can be built with multiple configurations + package = mkOption { + type = types.package; + default = pkgs.gnome3.gvfs; + description = "Which GVfs package to use."; + }; + + }; + + }; + + + ###### implementation + + config = mkIf cfg.enable { + + environment.systemPackages = [ cfg.package ]; + + services.dbus.packages = [ cfg.package ]; + + systemd.packages = [ cfg.package ]; + + services.udev.packages = [ pkgs.libmtp.bin ]; + + # Needed for unwrapped applications + environment.variables.GIO_EXTRA_MODULES = [ "${cfg.package}/lib/gio/modules" ]; + + }; + +} diff --git a/nixos/modules/services/hardware/trezord.nix b/nixos/modules/services/hardware/trezord.nix index c06a0665d02ff..62824ed7350a7 100644 --- a/nixos/modules/services/hardware/trezord.nix +++ b/nixos/modules/services/hardware/trezord.nix @@ -4,6 +4,12 @@ with lib; let cfg = config.services.trezord; in { + + ### docs + + meta = { + doc = ./trezord.xml; + }; ### interface @@ -16,6 +22,22 @@ in { Enable Trezor bridge daemon, for use with Trezor hardware bitcoin wallets. ''; }; + + emulator.enable = mkOption { + type = types.bool; + default = false; + description = '' + Enable Trezor emulator support. + ''; + }; + + emulator.port = mkOption { + type = types.port; + default = 21324; + description = '' + Listening port for the Trezor emulator. + ''; + }; }; }; @@ -44,7 +66,7 @@ in { path = []; serviceConfig = { Type = "simple"; - ExecStart = "${pkgs.trezord}/bin/trezord-go"; + ExecStart = "${pkgs.trezord}/bin/trezord-go ${optionalString cfg.emulator.enable "-e ${builtins.toString cfg.emulator.port}"}"; User = "trezord"; }; }; diff --git a/nixos/modules/services/hardware/trezord.xml b/nixos/modules/services/hardware/trezord.xml new file mode 100644 index 0000000000000..972d409d9d0e0 --- /dev/null +++ b/nixos/modules/services/hardware/trezord.xml @@ -0,0 +1,26 @@ +<chapter xmlns="http://docbook.org/ns/docbook" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:xi="http://www.w3.org/2001/XInclude" + version="5.0" + xml:id="trezor"> + <title>Trezor</title> + <para> + Trezor is an open-source cryptocurrency hardware wallet and security token + allowing secure storage of private keys. + </para> + <para> + It offers advanced features such U2F two-factor authorization, SSH login + through + <link xlink:href="https://wiki.trezor.io/Apps:SSH_agent">Trezor SSH agent</link>, + <link xlink:href="https://wiki.trezor.io/GPG">GPG</link> and a + <link xlink:href="https://wiki.trezor.io/Trezor_Password_Manager">password manager</link>. + For more information, guides and documentation, see <link xlink:href="https://wiki.trezor.io"/>. + </para> + <para> + To enable Trezor support, add the following to your <filename>configuration.nix</filename>: +<programlisting> +<xref linkend="opt-services.trezord.enable"/> = true; +</programlisting> + This will add all necessary udev rules and start Trezor Bridge. + </para> +</chapter> diff --git a/nixos/modules/services/logging/awstats.nix b/nixos/modules/services/logging/awstats.nix index 612ae06d0a79c..54799d699a746 100644 --- a/nixos/modules/services/logging/awstats.nix +++ b/nixos/modules/services/logging/awstats.nix @@ -4,6 +4,7 @@ with lib; let cfg = config.services.awstats; + httpd = config.services.httpd; package = pkgs.awstats; in @@ -67,50 +68,43 @@ in environment.etc."awstats/awstats.conf".source = pkgs.runCommand "awstats.conf" { preferLocalBuild = true; } ( let - cfg-httpd = config.services.httpd; logFormat = - if cfg-httpd.logFormat == "combined" then "1" else - if cfg-httpd.logFormat == "common" then "4" else - throw "awstats service doesn't support Apache log format `${cfg-httpd.logFormat}`"; + if httpd.logFormat == "combined" then "1" else + if httpd.logFormat == "common" then "4" else + throw "awstats service doesn't support Apache log format `${httpd.logFormat}`"; in '' sed \ -e 's|^\(DirData\)=.*$|\1="${cfg.vardir}"|' \ -e 's|^\(DirIcons\)=.*$|\1="icons"|' \ -e 's|^\(CreateDirDataIfNotExists\)=.*$|\1=1|' \ - -e 's|^\(SiteDomain\)=.*$|\1="${cfg-httpd.hostName}"|' \ - -e 's|^\(LogFile\)=.*$|\1="${cfg-httpd.logDir}/access_log"|' \ + -e 's|^\(SiteDomain\)=.*$|\1="${httpd.hostName}"|' \ + -e 's|^\(LogFile\)=.*$|\1="${httpd.logDir}/access_log"|' \ -e 's|^\(LogFormat\)=.*$|\1=${logFormat}|' \ < '${package.out}/wwwroot/cgi-bin/awstats.model.conf' > "$out" echo '${cfg.extraConfig}' >> "$out" ''); + systemd.tmpfiles.rules = optionals cfg.service.enable [ + "d '${cfg.vardir}' - ${httpd.user} ${httpd.group} - -" + "Z '${cfg.vardir}' - ${httpd.user} ${httpd.group} - -" + ]; + # The httpd sub-service showing awstats. - services.httpd.enable = mkIf cfg.service.enable true; - services.httpd.extraSubservices = mkIf cfg.service.enable [ { function = { serverInfo, ... }: { - extraConfig = - '' - Alias ${cfg.service.urlPrefix}/classes "${package.out}/wwwroot/classes/" - Alias ${cfg.service.urlPrefix}/css "${package.out}/wwwroot/css/" - Alias ${cfg.service.urlPrefix}/icons "${package.out}/wwwroot/icon/" - ScriptAlias ${cfg.service.urlPrefix}/ "${package.out}/wwwroot/cgi-bin/" + services.httpd = optionalAttrs cfg.service.enable { + enable = true; + extraConfig = '' + Alias ${cfg.service.urlPrefix}/classes "${package.out}/wwwroot/classes/" + Alias ${cfg.service.urlPrefix}/css "${package.out}/wwwroot/css/" + Alias ${cfg.service.urlPrefix}/icons "${package.out}/wwwroot/icon/" + ScriptAlias ${cfg.service.urlPrefix}/ "${package.out}/wwwroot/cgi-bin/" - <Directory "${package.out}/wwwroot"> - Options None - AllowOverride None - Order allow,deny - Allow from all - </Directory> - ''; - startupScript = - let - inherit (serverInfo.serverConfig) user group; - in pkgs.writeScript "awstats_startup.sh" - '' - mkdir -p '${cfg.vardir}' - chown '${user}:${group}' '${cfg.vardir}' - ''; - };}]; + <Directory "${package.out}/wwwroot"> + Options None + Require all granted + </Directory> + ''; + }; systemd.services.awstats-update = mkIf (cfg.updateAt != null) { description = "awstats log collector"; diff --git a/nixos/modules/services/mail/rmilter.nix b/nixos/modules/services/mail/rmilter.nix deleted file mode 100644 index 466365b6b305b..0000000000000 --- a/nixos/modules/services/mail/rmilter.nix +++ /dev/null @@ -1,252 +0,0 @@ -{ config, lib, pkgs, ... }: - -with lib; - -let - - rspamdCfg = config.services.rspamd; - postfixCfg = config.services.postfix; - cfg = config.services.rmilter; - - inetSocket = addr: port: "inet:${addr}:${toString port}"; - unixSocket = sock: "unix:${sock}"; - - systemdSocket = if cfg.bindSocket.type == "unix" then cfg.bindSocket.path - else "${cfg.bindSocket.address}:${toString cfg.bindSocket.port}"; - rmilterSocket = if cfg.bindSocket.type == "unix" then unixSocket cfg.bindSocket.path - else inetSocket cfg.bindSocket.address cfg.bindSocket.port; - - rmilterConf = '' - pidfile = /run/rmilter/rmilter.pid; - bind_socket = ${if cfg.socketActivation then "fd:3" else rmilterSocket}; - tempdir = /tmp; - '' + (with cfg.rspamd; if enable then '' - spamd { - servers = ${concatStringsSep ", " servers}; - connect_timeout = 1s; - results_timeout = 20s; - error_time = 10; - dead_time = 300; - maxerrors = 10; - reject_message = "${rejectMessage}"; - ${optionalString (length whitelist != 0) "whitelist = ${concatStringsSep ", " whitelist};"} - - # rspamd_metric - metric for using with rspamd - # Default: "default" - rspamd_metric = "default"; - ${extraConfig} - }; - '' else "") + cfg.extraConfig; - - rmilterConfigFile = pkgs.writeText "rmilter.conf" rmilterConf; - -in - -{ - - ###### interface - - options = { - - services.rmilter = { - - enable = mkOption { - type = types.bool; - default = false; - description = "Whether to run the rmilter daemon."; - }; - - debug = mkOption { - type = types.bool; - default = false; - description = "Whether to run the rmilter daemon in debug mode."; - }; - - user = mkOption { - type = types.string; - default = "rmilter"; - description = '' - User to use when no root privileges are required. - ''; - }; - - group = mkOption { - type = types.string; - default = "rmilter"; - description = '' - Group to use when no root privileges are required. - ''; - }; - - bindSocket.type = mkOption { - type = types.enum [ "unix" "inet" ]; - default = "unix"; - description = '' - What kind of socket rmilter should listen on. Either "unix" - for an Unix domain socket or "inet" for a TCP socket. - ''; - }; - - bindSocket.path = mkOption { - type = types.str; - default = "/run/rmilter.sock"; - description = '' - Path to Unix domain socket to listen on. - ''; - }; - - bindSocket.address = mkOption { - type = types.str; - default = "[::1]"; - example = "0.0.0.0"; - description = '' - Inet address to listen on. - ''; - }; - - bindSocket.port = mkOption { - type = types.int; - default = 11990; - description = '' - Inet port to listen on. - ''; - }; - - socketActivation = mkOption { - type = types.bool; - default = true; - description = '' - Enable systemd socket activation for rmilter. - - Disabling socket activation is not recommended when a Unix - domain socket is used and could lead to incorrect - permissions. - ''; - }; - - rspamd = { - enable = mkOption { - type = types.bool; - default = rspamdCfg.enable; - description = "Whether to use rspamd to filter mails"; - }; - - servers = mkOption { - type = types.listOf types.str; - default = ["r:/run/rspamd/rspamd.sock"]; - description = '' - Spamd socket definitions. - Is server name is prefixed with r: it is rspamd server. - ''; - }; - - whitelist = mkOption { - type = types.listOf types.str; - default = [ ]; - description = "list of ips or nets that should be not checked with spamd"; - }; - - rejectMessage = mkOption { - type = types.str; - default = "Spam message rejected; If this is not spam contact abuse"; - description = "reject message for spam"; - }; - - extraConfig = mkOption { - type = types.lines; - default = ""; - description = "Custom snippet to append to end of `spamd' section"; - }; - }; - - extraConfig = mkOption { - type = types.lines; - default = ""; - description = "Custom snippet to append to rmilter config"; - }; - - postfix = { - enable = mkOption { - type = types.bool; - default = false; - description = "Add rmilter to postfix main.conf"; - }; - - configFragment = mkOption { - type = types.str; - description = "Addon to postfix configuration"; - default = '' - smtpd_milters = ${rmilterSocket} - milter_protocol = 6 - milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen} - ''; - }; - }; - - }; - - }; - - - ###### implementation - - config = mkMerge [ - - (mkIf cfg.enable { - warnings = [ - ''`config.services.rmilter' is deprecated, `rmilter' deprecated and unsupported by upstream, and will be removed from next releases. Use built-in rspamd milter instead.'' - ]; - - users.users = singleton { - name = cfg.user; - description = "rmilter daemon"; - uid = config.ids.uids.rmilter; - group = cfg.group; - }; - - users.groups = singleton { - name = cfg.group; - gid = config.ids.gids.rmilter; - }; - - systemd.services.rmilter = { - description = "Rmilter Service"; - - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - - serviceConfig = { - ExecStart = "${pkgs.rmilter}/bin/rmilter ${optionalString cfg.debug "-d"} -n -c ${rmilterConfigFile}"; - ExecReload = "${pkgs.coreutils}/bin/kill -USR1 $MAINPID"; - User = cfg.user; - Group = cfg.group; - PermissionsStartOnly = true; - Restart = "always"; - RuntimeDirectory = "rmilter"; - RuntimeDirectoryMode = "0750"; - }; - - }; - - systemd.sockets.rmilter = mkIf cfg.socketActivation { - description = "Rmilter service socket"; - wantedBy = [ "sockets.target" ]; - socketConfig = { - ListenStream = systemdSocket; - SocketUser = cfg.user; - SocketGroup = cfg.group; - SocketMode = "0660"; - }; - }; - }) - - (mkIf (cfg.enable && cfg.rspamd.enable && rspamdCfg.enable) { - users.users.${cfg.user}.extraGroups = [ rspamdCfg.group ]; - }) - - (mkIf (cfg.enable && cfg.postfix.enable) { - services.postfix.extraConfig = cfg.postfix.configFragment; - users.users.${postfixCfg.user}.extraGroups = [ cfg.group ]; - }) - ]; -} diff --git a/nixos/modules/services/mail/roundcube.nix b/nixos/modules/services/mail/roundcube.nix index e8b2e11bf726c..bdedfa1bb7017 100644 --- a/nixos/modules/services/mail/roundcube.nix +++ b/nixos/modules/services/mail/roundcube.nix @@ -4,6 +4,7 @@ with lib; let cfg = config.services.roundcube; + fpm = config.services.phpfpm.pools.roundcube; in { options.services.roundcube = { @@ -105,7 +106,7 @@ in extraConfig = '' location ~* \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; - fastcgi_pass unix:/run/phpfpm/roundcube; + fastcgi_pass unix:${fpm.socket}; include ${pkgs.nginx}/conf/fastcgi_params; include ${pkgs.nginx}/conf/fastcgi.conf; } @@ -119,24 +120,27 @@ in enable = true; }; - services.phpfpm.poolConfigs.roundcube = '' - listen = /run/phpfpm/roundcube - listen.owner = nginx - listen.group = nginx - listen.mode = 0660 - user = nginx - pm = dynamic - pm.max_children = 75 - pm.start_servers = 2 - pm.min_spare_servers = 1 - pm.max_spare_servers = 20 - pm.max_requests = 500 - php_admin_value[error_log] = 'stderr' - php_admin_flag[log_errors] = on - php_admin_value[post_max_size] = 25M - php_admin_value[upload_max_filesize] = 25M - catch_workers_output = yes - ''; + services.phpfpm.pools.roundcube = { + user = "nginx"; + phpOptions = '' + error_log = 'stderr' + log_errors = on + post_max_size = 25M + upload_max_filesize = 25M + ''; + settings = mapAttrs (name: mkDefault) { + "listen.owner" = "nginx"; + "listen.group" = "nginx"; + "listen.mode" = "0660"; + "pm" = "dynamic"; + "pm.max_children" = 75; + "pm.start_servers" = 2; + "pm.min_spare_servers" = 1; + "pm.max_spare_servers" = 20; + "pm.max_requests" = 500; + "catch_workers_output" = true; + }; + }; systemd.services.phpfpm-roundcube.after = [ "roundcube-setup.service" ]; systemd.services.roundcube-setup = let diff --git a/nixos/modules/services/misc/gitlab.nix b/nixos/modules/services/misc/gitlab.nix index 087630f217769..09c3a89d6a688 100644 --- a/nixos/modules/services/misc/gitlab.nix +++ b/nixos/modules/services/misc/gitlab.nix @@ -659,7 +659,7 @@ in { fi # We remove potentially broken links to old gitlab-shell versions - rm -f ${cfg.statePath}/repositories/**/*.git/hooks + rm -Rf ${cfg.statePath}/repositories/**/*.git/hooks ${pkgs.sudo}/bin/sudo -u ${cfg.user} -H ${pkgs.git}/bin/git config --global core.autocrlf "input" ''; diff --git a/nixos/modules/services/misc/mantisbt.nix b/nixos/modules/services/misc/mantisbt.nix deleted file mode 100644 index 7e3474feb672c..0000000000000 --- a/nixos/modules/services/misc/mantisbt.nix +++ /dev/null @@ -1,68 +0,0 @@ -{ config, lib, pkgs, ... }: - -with lib; -let - cfg = config.services.mantisbt; - - freshInstall = cfg.extraConfig == ""; - - # combined code+config directory - mantisbt = let - config_inc = pkgs.writeText "config_inc.php" ("<?php\n" + cfg.extraConfig); - src = pkgs.fetchurl { - url = "mirror://sourceforge/mantisbt/${name}.tar.gz"; - sha256 = "1pl6xn793p3mxc6ibpr2bhg85vkdlcf57yk7pfc399g47l8x4508"; - }; - name = "mantisbt-1.2.19"; - in - # We have to copy every time; otherwise config won't be found. - pkgs.runCommand name - { preferLocalBuild = true; allowSubstitutes = false; } - ('' - mkdir -p "$out" - cd "$out" - tar -xf '${src}' --strip-components=1 - ln -s '${config_inc}' config_inc.php - '' - + lib.optionalString (!freshInstall) "rm -r admin/" - ); -in -{ - options.services.mantisbt = { - enable = mkOption { - type = types.bool; - default = false; - description = '' - Enable the mantisbt web service. - This switches on httpd with PHP and database. - ''; - }; - urlPrefix = mkOption { - type = types.string; - default = "/mantisbt"; - description = "The URL prefix under which the mantisbt service appears."; - }; - extraConfig = mkOption { - type = types.lines; - default = ""; - description = '' - The contents of config_inc.php, without leading <?php. - If left empty, the admin directory will be accessible. - ''; - }; - }; - - - config = mkIf cfg.enable { - services.mysql.enable = true; - services.httpd.enable = true; - services.httpd.enablePHP = true; - # The httpd sub-service showing mantisbt. - services.httpd.extraSubservices = [ { function = { ... }: { - extraConfig = - '' - Alias ${cfg.urlPrefix} "${mantisbt}" - ''; - };}]; - }; -} diff --git a/nixos/modules/services/misc/matrix-synapse.nix b/nixos/modules/services/misc/matrix-synapse.nix index b8e650863baf6..018fac386163d 100644 --- a/nixos/modules/services/misc/matrix-synapse.nix +++ b/nixos/modules/services/misc/matrix-synapse.nix @@ -684,7 +684,7 @@ in { fi ''; serviceConfig = { - Type = "simple"; + Type = "notify"; User = "matrix-synapse"; Group = "matrix-synapse"; WorkingDirectory = cfg.dataDir; diff --git a/nixos/modules/services/misc/metabase.nix b/nixos/modules/services/misc/metabase.nix new file mode 100644 index 0000000000000..e78100a046a20 --- /dev/null +++ b/nixos/modules/services/misc/metabase.nix @@ -0,0 +1,103 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.services.metabase; + + inherit (lib) mkEnableOption mkIf mkOption; + inherit (lib) optional optionalAttrs types; + + dataDir = "/var/lib/metabase"; + +in { + + options = { + + services.metabase = { + enable = mkEnableOption "Metabase service"; + + listen = { + ip = mkOption { + type = types.str; + default = "0.0.0.0"; + description = '' + IP address that Metabase should listen on. + ''; + }; + + port = mkOption { + type = types.port; + default = 3000; + description = '' + Listen port for Metabase. + ''; + }; + }; + + ssl = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable SSL (https) support. + ''; + }; + + port = mkOption { + type = types.port; + default = 8443; + description = '' + Listen port over SSL (https) for Metabase. + ''; + }; + + keystore = mkOption { + type = types.nullOr types.path; + default = "${dataDir}/metabase.jks"; + example = "/etc/secrets/keystore.jks"; + description = '' + <link xlink:href="https://www.digitalocean.com/community/tutorials/java-keytool-essentials-working-with-java-keystores">Java KeyStore</link> file containing the certificates. + ''; + }; + + }; + + openFirewall = mkOption { + type = types.bool; + default = false; + description = '' + Open ports in the firewall for Metabase. + ''; + }; + }; + + }; + + config = mkIf cfg.enable { + + systemd.services.metabase = { + description = "Metabase server"; + wantedBy = [ "multi-user.target" ]; + after = [ "network-online.target" ]; + environment = { + MB_PLUGINS_DIR = "${dataDir}/plugins"; + MB_DB_FILE = "${dataDir}/metabase.db"; + MB_JETTY_HOST = cfg.listen.ip; + MB_JETTY_PORT = toString cfg.listen.port; + } // optionalAttrs (cfg.ssl.enable) { + MB_JETTY_SSL = true; + MB_JETTY_SSL_PORT = toString cfg.ssl.port; + MB_JETTY_SSL_KEYSTORE = cfg.ssl.keystore; + }; + serviceConfig = { + DynamicUser = true; + StateDirectory = baseNameOf dataDir; + ExecStart = "${pkgs.metabase}/bin/metabase"; + }; + }; + + networking.firewall = mkIf cfg.openFirewall { + allowedTCPPorts = [ cfg.listen.port ] ++ optional cfg.ssl.enable cfg.ssl.port; + }; + + }; +} diff --git a/nixos/modules/services/misc/zoneminder.nix b/nixos/modules/services/misc/zoneminder.nix index dc76ae6974245..6c45179a6d40a 100644 --- a/nixos/modules/services/misc/zoneminder.nix +++ b/nixos/modules/services/misc/zoneminder.nix @@ -2,6 +2,7 @@ let cfg = config.services.zoneminder; + fpm = config.services.phpfpm.pools.zoneminder; pkg = pkgs.zoneminder; dirName = pkg.dirName; @@ -19,8 +20,6 @@ let useCustomDir = cfg.storageDir != null; - socket = "/run/phpfpm/${dirName}.sock"; - zms = "/cgi-bin/zms"; dirs = dirList: [ dirName ] ++ map (e: "${dirName}/${e}") dirList; @@ -201,7 +200,10 @@ in { "zoneminder/80-nixos.conf".source = configFile; }; - networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [ cfg.port ]; + networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [ + cfg.port + 6802 # zmtrigger + ]; services = { fcgiwrap = lib.mkIf useNginx { @@ -274,7 +276,7 @@ in { fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_param HTTP_PROXY ""; - fastcgi_pass unix:${socket}; + fastcgi_pass unix:${fpm.socket}; } } ''; @@ -284,30 +286,27 @@ in { phpfpm = lib.mkIf useNginx { pools.zoneminder = { - listen = socket; + inherit user group; phpOptions = '' date.timezone = "${config.time.timeZone}" ${lib.concatStringsSep "\n" (map (e: "extension=${e.pkg}/lib/php/extensions/${e.name}.so") phpExtensions)} ''; - extraConfig = '' - user = ${user} - group = ${group} - - listen.owner = ${user} - listen.group = ${group} - listen.mode = 0660 - - pm = dynamic - pm.start_servers = 1 - pm.min_spare_servers = 1 - pm.max_spare_servers = 2 - pm.max_requests = 500 - pm.max_children = 5 - pm.status_path = /$pool-status - ping.path = /$pool-ping - ''; + settings = lib.mapAttrs (name: lib.mkDefault) { + "listen.owner" = user; + "listen.group" = group; + "listen.mode" = "0660"; + + "pm" = "dynamic"; + "pm.start_servers" = 1; + "pm.min_spare_servers" = 1; + "pm.max_spare_servers" = 2; + "pm.max_requests" = 500; + "pm.max_children" = 5; + "pm.status_path" = "/$pool-status"; + "ping.path" = "/$pool-ping"; + }; }; }; }; diff --git a/nixos/modules/services/monitoring/cadvisor.nix b/nixos/modules/services/monitoring/cadvisor.nix index 6ca420a05b234..695a8c42e85e0 100644 --- a/nixos/modules/services/monitoring/cadvisor.nix +++ b/nixos/modules/services/monitoring/cadvisor.nix @@ -84,6 +84,16 @@ in { type = types.bool; description = "Cadvisor storage driver, enable secure communication."; }; + + extraOptions = mkOption { + type = types.listOf types.str; + default = []; + description = '' + Additional cadvisor options. + + See <link xlink:href='https://github.com/google/cadvisor/blob/master/docs/runtime_options.md'/> for available options. + ''; + }; }; }; @@ -112,6 +122,7 @@ in { -logtostderr=true \ -listen_ip="${cfg.listenAddress}" \ -port="${toString cfg.port}" \ + ${escapeShellArgs cfg.extraOptions} \ ${optionalString (cfg.storageDriver != null) '' -storage_driver "${cfg.storageDriver}" \ -storage_driver_user "${cfg.storageDriverHost}" \ diff --git a/nixos/modules/services/monitoring/riemann-tools.nix b/nixos/modules/services/monitoring/riemann-tools.nix index 9c400a1e3e46b..2b647b6b1ade8 100644 --- a/nixos/modules/services/monitoring/riemann-tools.nix +++ b/nixos/modules/services/monitoring/riemann-tools.nix @@ -11,7 +11,7 @@ let healthLauncher = writeScriptBin "riemann-health" '' #!/bin/sh - exec ${pkgs.riemann-tools}/bin/riemann-health --host ${riemannHost} + exec ${pkgs.riemann-tools}/bin/riemann-health ${builtins.concatStringsSep " " cfg.extraArgs} --host ${riemannHost} ''; @@ -34,8 +34,16 @@ in { Address of the host riemann node. Defaults to localhost. ''; }; + extraArgs = mkOption { + type = types.listOf types.string; + default = []; + description = '' + A list of commandline-switches forwarded to a riemann-tool. + See for example `riemann-health --help` for available options. + ''; + example = ["-p 5555" "--timeout=30" "--attribute=myattribute=42"]; + }; }; - }; config = mkIf cfg.enableHealth { diff --git a/nixos/modules/services/monitoring/systemhealth.nix b/nixos/modules/services/monitoring/systemhealth.nix deleted file mode 100644 index 32d4314d5f777..0000000000000 --- a/nixos/modules/services/monitoring/systemhealth.nix +++ /dev/null @@ -1,133 +0,0 @@ -{ config, lib, pkgs, ... }: - -with lib; - -let - cfg = config.services.systemhealth; - - systemhealth = with pkgs; stdenv.mkDerivation { - name = "systemhealth-1.0"; - src = fetchurl { - url = "https://www.brianlane.com/downloads/systemhealth/systemhealth-1.0.tar.bz2"; - sha256 = "1q69lz7hmpbdpbz36zb06nzfkj651413n9icx0njmyr3xzq1j9qy"; - }; - buildInputs = [ python ]; - installPhase = '' - mkdir -p $out/bin - # Make it work for kernels 3.x, not so different than 2.6 - sed -i 's/2\.6/4.0/' system_health.py - cp system_health.py $out/bin - ''; - }; - - rrdDir = "/var/lib/health/rrd"; - htmlDir = "/var/lib/health/html"; - - configFile = rrdDir + "/.syshealthrc"; - # The program will try to read $HOME/.syshealthrc, so we set the proper home. - command = "HOME=${rrdDir} ${systemhealth}/bin/system_health.py"; - - cronJob = '' - */5 * * * * wwwrun ${command} --log - 5 * * * * wwwrun ${command} --graph - ''; - - nameEqualName = s: "${s} = ${s}"; - interfacesSection = concatStringsSep "\n" (map nameEqualName cfg.interfaces); - - driveLine = d: "${d.path} = ${d.name}"; - drivesSection = concatStringsSep "\n" (map driveLine cfg.drives); - -in -{ - options = { - services.systemhealth = { - enable = mkOption { - default = false; - description = '' - Enable the system health monitor and its generation of graphs. - ''; - }; - - urlPrefix = mkOption { - default = "/health"; - description = '' - The URL prefix under which the System Health web pages appear in httpd. - ''; - }; - - interfaces = mkOption { - default = [ "lo" ]; - example = [ "lo" "eth0" "eth1" ]; - description = '' - Interfaces to monitor (minimum one). - ''; - }; - - drives = mkOption { - default = [ ]; - example = [ { name = "root"; path = "/"; } ]; - description = '' - Drives to monitor. - ''; - }; - }; - }; - - config = mkIf cfg.enable { - services.cron.systemCronJobs = [ cronJob ]; - - system.activationScripts.systemhealth = stringAfter [ "var" ] - '' - mkdir -p ${rrdDir} ${htmlDir} - chown wwwrun:wwwrun ${rrdDir} ${htmlDir} - - cat >${configFile} << EOF - [paths] - rrdtool = ${pkgs.rrdtool}/bin/rrdtool - loadavg_rrd = loadavg - ps = /run/current-system/sw/bin/ps - df = /run/current-system/sw/bin/df - meminfo_rrd = meminfo - uptime_rrd = uptime - rrd_path = ${rrdDir} - png_path = ${htmlDir} - - [processes] - - [interfaces] - ${interfacesSection} - - [drives] - ${drivesSection} - - [graphs] - width = 400 - time = ['-3hours', '-32hours', '-8days', '-5weeks', '-13months'] - height = 100 - - [external] - - EOF - - chown wwwrun:wwwrun ${configFile} - - ${pkgs.su}/bin/su -s "/bin/sh" -c "${command} --check" wwwrun - ${pkgs.su}/bin/su -s "/bin/sh" -c "${command} --html" wwwrun - ''; - - services.httpd.extraSubservices = [ - { function = f: { - extraConfig = '' - Alias ${cfg.urlPrefix} ${htmlDir} - - <Directory ${htmlDir}> - Order allow,deny - Allow from all - </Directory> - ''; - }; - } - ]; - }; -} diff --git a/nixos/modules/services/monitoring/ups.nix b/nixos/modules/services/monitoring/ups.nix index bc755612fd9bb..429b40227d47f 100644 --- a/nixos/modules/services/monitoring/ups.nix +++ b/nixos/modules/services/monitoring/ups.nix @@ -225,7 +225,7 @@ in '' maxstartdelay = ${toString cfg.maxStartDelay} - ${flip concatStringsSep (flip map (attrValues cfg.ups) (ups: ups.summary)) " + ${flip concatStringsSep (forEach (attrValues cfg.ups) (ups: ups.summary)) " "} ''; diff --git a/nixos/modules/services/network-filesystems/u9fs.nix b/nixos/modules/services/network-filesystems/u9fs.nix index 4f37fc2a9e5cf..77961b78cadb8 100644 --- a/nixos/modules/services/network-filesystems/u9fs.nix +++ b/nixos/modules/services/network-filesystems/u9fs.nix @@ -55,6 +55,7 @@ in sockets.u9fs = { description = "U9fs Listening Socket"; wantedBy = [ "sockets.target" ]; + after = [ "network.target" ]; inherit (cfg) listenStreams; socketConfig.Accept = "yes"; }; diff --git a/nixos/modules/services/networking/cjdns.nix b/nixos/modules/services/networking/cjdns.nix index c40962f4aa827..3fb85b16cbe20 100644 --- a/nixos/modules/services/networking/cjdns.nix +++ b/nixos/modules/services/networking/cjdns.nix @@ -44,9 +44,7 @@ let parseModules = x: x // { connectTo = mapAttrs (name: value: { inherit (value) password publicKey; }) x.connectTo; }; - # would be nice to merge 'cfg' with a //, - # but the json nesting is wacky. - cjdrouteConf = builtins.toJSON ( { + cjdrouteConf = builtins.toJSON ( recursiveUpdate { admin = { bind = cfg.admin.bind; password = "@CJDNS_ADMIN_PASSWORD@"; @@ -71,7 +69,7 @@ let security = [ { exemptAngel = 1; setuser = "nobody"; } ]; - }); + } cfg.extraConfig); in @@ -91,6 +89,16 @@ in ''; }; + extraConfig = mkOption { + type = types.attrs; + default = {}; + example = { router.interface.tunDevice = "tun10"; }; + description = '' + Extra configuration, given as attrs, that will be merged recursively + with the rest of the JSON generated by this module, at the root node. + ''; + }; + confFile = mkOption { type = types.nullOr types.path; default = null; @@ -246,7 +254,10 @@ in if cfg.confFile != null then "${pkg}/bin/cjdroute < ${cfg.confFile}" else '' source /etc/cjdns.keys - echo '${cjdrouteConf}' | sed \ + (cat <<'EOF' + ${cjdrouteConf} + EOF + ) | sed \ -e "s/@CJDNS_ADMIN_PASSWORD@/$CJDNS_ADMIN_PASSWORD/g" \ -e "s/@CJDNS_PRIVATE_KEY@/$CJDNS_PRIVATE_KEY/g" \ | ${pkg}/bin/cjdroute diff --git a/nixos/modules/services/networking/consul.nix b/nixos/modules/services/networking/consul.nix index 0e1195da8c0a7..689cbc8a986d9 100644 --- a/nixos/modules/services/networking/consul.nix +++ b/nixos/modules/services/networking/consul.nix @@ -15,7 +15,7 @@ let ++ cfg.extraConfigFiles; devices = attrValues (filterAttrs (_: i: i != null) cfg.interface); - systemdDevices = flip map devices + systemdDevices = forEach devices (i: "sys-subsystem-net-devices-${utils.escapeSystemdPath i}.device"); in { diff --git a/nixos/modules/services/networking/dnschain.nix b/nixos/modules/services/networking/dnschain.nix index 0c2add424bac5..5b58ea9b0c910 100644 --- a/nixos/modules/services/networking/dnschain.nix +++ b/nixos/modules/services/networking/dnschain.nix @@ -136,10 +136,16 @@ in "/.dns/127.0.0.1#${toString cfg.dns.port}" ]; - services.pdns-recursor.forwardZones = mkIf cfgs.pdns-recursor.resolveDNSChainQueries - { bit = "127.0.0.1:${toString cfg.dns.port}"; - dns = "127.0.0.1:${toString cfg.dns.port}"; - }; + services.pdns-recursor = mkIf cfgs.pdns-recursor.resolveDNSChainQueries { + forwardZones = + { bit = "127.0.0.1:${toString cfg.dns.port}"; + dns = "127.0.0.1:${toString cfg.dns.port}"; + }; + luaConfig ='' + addNTA("bit", "namecoin doesn't support DNSSEC") + addNTA("dns", "namecoin doesn't support DNSSEC") + ''; + }; users.users = singleton { name = username; diff --git a/nixos/modules/services/networking/hylafax/systemd.nix b/nixos/modules/services/networking/hylafax/systemd.nix index ec5b7692f9745..b9b9b9dca4f0a 100644 --- a/nixos/modules/services/networking/hylafax/systemd.nix +++ b/nixos/modules/services/networking/hylafax/systemd.nix @@ -7,7 +7,7 @@ let inherit (lib) concatStringsSep optionalString; cfg = config.services.hylafax; - mapModems = lib.flip map (lib.attrValues cfg.modems); + mapModems = lib.forEach (lib.attrValues cfg.modems); mkConfigFile = name: conf: # creates hylafax config file, diff --git a/nixos/modules/services/networking/jormungandr.nix b/nixos/modules/services/networking/jormungandr.nix new file mode 100644 index 0000000000000..0c66b85fe8a5f --- /dev/null +++ b/nixos/modules/services/networking/jormungandr.nix @@ -0,0 +1,97 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.services.jormungandr; + + inherit (lib) mkEnableOption mkIf mkOption; + inherit (lib) optionalString types; + + dataDir = "/var/lib/jormungandr"; + + # Default settings so far, as the service matures we will + # move these out as separate settings + configSettings = { + storage = dataDir; + p2p = { + public_address = "/ip4/127.0.0.1/tcp/8299"; + messages = "high"; + blocks = "high"; + }; + rest = { + listen = "127.0.0.1:8607"; + }; + }; + + configFile = if cfg.configFile == null then + pkgs.writeText "jormungandr.yaml" (builtins.toJSON configSettings) + else cfg.configFile; + +in { + + options = { + + services.jormungandr = { + enable = mkEnableOption "jormungandr service"; + + configFile = mkOption { + type = types.nullOr types.path; + default = null; + example = "/var/lib/jormungandr/node.yaml"; + description = '' + The path of the jormungandr blockchain configuration file in YAML format. + If no file is specified, a file is generated using the other options. + ''; + }; + + secretFile = mkOption { + type = types.nullOr types.path; + default = null; + example = "/etc/secret/jormungandr.yaml"; + description = '' + The path of the jormungandr blockchain secret node configuration file in + YAML format. Do not store this in nix store! + ''; + }; + + genesisBlockHash = mkOption { + type = types.nullOr types.string; + default = null; + example = "d70495af81ae8600aca3e642b2427327cb6001ec4d7a0037e96a00dabed163f9"; + description = '' + Set the genesis block hash (the hash of the block0) so we can retrieve + the genesis block (and the blockchain configuration) from the existing + storage or from the network. + ''; + }; + + genesisBlockFile = mkOption { + type = types.nullOr types.path; + default = null; + example = "/var/lib/jormungandr/block-0.bin"; + description = '' + The path of the genesis block file if we are hosting it locally. + ''; + }; + + }; + }; + + config = mkIf cfg.enable { + + systemd.services.jormungandr = { + description = "jormungandr server"; + wantedBy = [ "multi-user.target" ]; + after = [ "network-online.target" ]; + serviceConfig = { + DynamicUser = true; + StateDirectory = baseNameOf dataDir; + ExecStart = '' + ${pkgs.jormungandr}/bin/jormungandr --config ${configFile} \ + ${optionalString (cfg.secretFile != null) " --secret ${cfg.secretFile}"} \ + ${optionalString (cfg.genesisBlockHash != null) " --genesis-block-hash ${cfg.genesisBlockHash}"} \ + ${optionalString (cfg.genesisBlockFile != null) " --genesis-block ${cfg.genesisBlockFile}"} + ''; + }; + }; + }; +} diff --git a/nixos/modules/services/networking/ofono.nix b/nixos/modules/services/networking/ofono.nix new file mode 100644 index 0000000000000..40ef9433de0fb --- /dev/null +++ b/nixos/modules/services/networking/ofono.nix @@ -0,0 +1,44 @@ +# Ofono daemon. +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.ofono; + + plugin_path = + lib.concatMapStringsSep ":" + (plugin: "${plugin}/lib/ofono/plugins") + cfg.plugins + ; + +in + +{ + ###### interface + options = { + services.ofono = { + enable = mkEnableOption "Ofono"; + + plugins = mkOption { + type = types.listOf types.package; + default = []; + example = literalExample "[ pkgs.modem-manager-gui ]"; + description = '' + The list of plugins to install. + ''; + }; + }; + }; + + ###### implementation + config = mkIf cfg.enable { + services.dbus.packages = [ pkgs.ofono ]; + + systemd.packages = [ pkgs.ofono ]; + + systemd.services.ofono.environment.OFONO_PLUGIN_PATH = mkIf (cfg.plugins != []) plugin_path; + + }; +} diff --git a/nixos/modules/services/networking/pdns-recursor.nix b/nixos/modules/services/networking/pdns-recursor.nix index 5292e9b046820..ec69cc838da9d 100644 --- a/nixos/modules/services/networking/pdns-recursor.nix +++ b/nixos/modules/services/networking/pdns-recursor.nix @@ -6,25 +6,27 @@ let dataDir = "/var/lib/pdns-recursor"; username = "pdns-recursor"; - cfg = config.services.pdns-recursor; - zones = mapAttrsToList (zone: uri: "${zone}.=${uri}") cfg.forwardZones; + cfg = config.services.pdns-recursor; - configFile = pkgs.writeText "recursor.conf" '' - local-address=${cfg.dns.address} - local-port=${toString cfg.dns.port} - allow-from=${concatStringsSep "," cfg.dns.allowFrom} + oneOrMore = type: with types; either type (listOf type); + valueType = with types; oneOf [ int str bool path ]; + configType = with types; attrsOf (nullOr (oneOrMore valueType)); - webserver-address=${cfg.api.address} - webserver-port=${toString cfg.api.port} - webserver-allow-from=${concatStringsSep "," cfg.api.allowFrom} + toBool = val: if val then "yes" else "no"; + serialize = val: with types; + if str.check val then val + else if int.check val then toString val + else if path.check val then toString val + else if bool.check val then toBool val + else if builtins.isList val then (concatMapStringsSep "," serialize val) + else ""; - forward-zones=${concatStringsSep "," zones} - export-etc-hosts=${if cfg.exportHosts then "yes" else "no"} - dnssec=${cfg.dnssecValidation} - serve-rfc1918=${if cfg.serveRFC1918 then "yes" else "no"} + configFile = pkgs.writeText "recursor.conf" + (concatStringsSep "\n" + (flip mapAttrsToList cfg.settings + (name: val: "${name}=${serialize val}"))); - ${cfg.extraConfig} - ''; + mkDefaultAttrs = mapAttrs (n: v: mkDefault v); in { options.services.pdns-recursor = { @@ -117,18 +119,56 @@ in { ''; }; - extraConfig = mkOption { + settings = mkOption { + type = configType; + default = { }; + example = literalExample '' + { + loglevel = 8; + log-common-errors = true; + } + ''; + description = '' + PowerDNS Recursor settings. Use this option to configure Recursor + settings not exposed in a NixOS option or to bypass one. + See the full documentation at + <link xlink:href="https://doc.powerdns.com/recursor/settings.html"/> + for the available options. + ''; + }; + + luaConfig = mkOption { type = types.lines; default = ""; description = '' - Extra options to be appended to the configuration file. + The content Lua configuration file for PowerDNS Recursor. See + <link xlink:href="https://doc.powerdns.com/recursor/lua-config/index.html"/>. ''; }; }; config = mkIf cfg.enable { - users.users.${username} = { + services.pdns-recursor.settings = mkDefaultAttrs { + local-address = cfg.dns.address; + local-port = cfg.dns.port; + allow-from = cfg.dns.allowFrom; + + webserver-address = cfg.api.address; + webserver-port = cfg.api.port; + webserver-allow-from = cfg.api.allowFrom; + + forward-zones = mapAttrsToList (zone: uri: "${zone}.=${uri}") cfg.forwardZones; + export-etc-hosts = cfg.exportHosts; + dnssec = cfg.dnssecValidation; + serve-rfc1918 = cfg.serveRFC1918; + lua-config-file = pkgs.writeText "recursor.lua" cfg.luaConfig; + + log-timestamp = false; + disable-syslog = true; + }; + + users.users."${username}" = { home = dataDir; createHome = true; uid = config.ids.uids.pdns-recursor; @@ -150,8 +190,7 @@ in { AmbientCapabilities = "cap_net_bind_service"; ExecStart = ''${pkgs.pdns-recursor}/bin/pdns_recursor \ --config-dir=${dataDir} \ - --socket-dir=${dataDir} \ - --disable-syslog + --socket-dir=${dataDir} ''; }; @@ -165,4 +204,10 @@ in { ''; }; }; + + imports = [ + (mkRemovedOptionModule [ "services" "pdns-recursor" "extraConfig" ] + "To change extra Recursor settings use services.pdns-recursor.settings instead.") + ]; + } diff --git a/nixos/modules/services/networking/shadowsocks.nix b/nixos/modules/services/networking/shadowsocks.nix index fe6d65a5f963a..af12db590f000 100644 --- a/nixos/modules/services/networking/shadowsocks.nix +++ b/nixos/modules/services/networking/shadowsocks.nix @@ -35,10 +35,10 @@ in }; localAddress = mkOption { - type = types.str; - default = "0.0.0.0"; + type = types.coercedTo types.str singleton (types.listOf types.str); + default = [ "[::0]" "0.0.0.0" ]; description = '' - Local address to which the server binds. + Local addresses to which the server binds. ''; }; diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix index 0f9d2420903bd..91fc7d72bc6d2 100644 --- a/nixos/modules/services/networking/ssh/sshd.nix +++ b/nixos/modules/services/networking/ssh/sshd.nix @@ -502,7 +502,7 @@ in assertions = [{ assertion = if cfg.forwardX11 then cfgc.setXAuthLocation else true; message = "cannot enable X11 forwarding without setting xauth location";}] - ++ flip map cfg.listenAddresses ({ addr, ... }: { + ++ forEach cfg.listenAddresses ({ addr, ... }: { assertion = addr != null; message = "addr must be specified in each listenAddresses entry"; }); diff --git a/nixos/modules/services/networking/stubby.nix b/nixos/modules/services/networking/stubby.nix index 3fbf6eb60e9d7..b38bcd4cec058 100644 --- a/nixos/modules/services/networking/stubby.nix +++ b/nixos/modules/services/networking/stubby.nix @@ -168,7 +168,7 @@ in default = defaultUpstream; type = types.lines; description = '' - Add additional upstreams. See <citerefentry><refentrytitle>stubby + Replace default upstreams. See <citerefentry><refentrytitle>stubby </refentrytitle><manvolnum>1</manvolnum></citerefentry> for an example of the entry formatting. In Strict mode, at least one of the following settings must be supplied for each nameserver: diff --git a/nixos/modules/services/networking/unifi.nix b/nixos/modules/services/networking/unifi.nix index 6239c88b7e41c..c922ba15960fd 100644 --- a/nixos/modules/services/networking/unifi.nix +++ b/nixos/modules/services/networking/unifi.nix @@ -176,6 +176,7 @@ in Type = "simple"; ExecStart = "${(removeSuffix "\n" cmd)} start"; ExecStop = "${(removeSuffix "\n" cmd)} stop"; + Restart = "on-failure"; User = "unifi"; UMask = "0077"; WorkingDirectory = "${stateDir}"; diff --git a/nixos/modules/services/search/elasticsearch.nix b/nixos/modules/services/search/elasticsearch.nix index 6b688c640d59b..91d8f544e16b0 100644 --- a/nixos/modules/services/search/elasticsearch.nix +++ b/nixos/modules/services/search/elasticsearch.nix @@ -131,6 +131,7 @@ in { description = "Extra elasticsearch plugins"; default = []; type = types.listOf types.package; + example = lib.literalExample "[ pkgs.elasticsearchPlugins.discovery-ec2 ]"; }; }; diff --git a/nixos/modules/services/security/sshguard.nix b/nixos/modules/services/security/sshguard.nix index 25cec5b5b1051..4a174564dd2ca 100644 --- a/nixos/modules/services/security/sshguard.nix +++ b/nixos/modules/services/security/sshguard.nix @@ -106,14 +106,24 @@ in { path = with pkgs; [ iptables ipset iproute systemd ]; - postStart = '' + # The sshguard ipsets must exist before we invoke + # iptables. sshguard creates the ipsets after startup if + # necessary, but if we let sshguard do it, we can't reliably add + # the iptables rules because postStart races with the creation + # of the ipsets. So instead, we create both the ipsets and + # firewall rules before sshguard starts. + preStart = '' + ${pkgs.ipset}/bin/ipset -quiet create -exist sshguard4 hash:net family inet + ${pkgs.ipset}/bin/ipset -quiet create -exist sshguard6 hash:net family inet6 ${pkgs.iptables}/bin/iptables -I INPUT -m set --match-set sshguard4 src -j DROP ${pkgs.iptables}/bin/ip6tables -I INPUT -m set --match-set sshguard6 src -j DROP ''; - preStop = '' + postStop = '' ${pkgs.iptables}/bin/iptables -D INPUT -m set --match-set sshguard4 src -j DROP ${pkgs.iptables}/bin/ip6tables -D INPUT -m set --match-set sshguard6 src -j DROP + ${pkgs.ipset}/bin/ipset -quiet destroy sshguard4 + ${pkgs.ipset}/bin/ipset -quiet destroy sshguard6 ''; unitConfig.Documentation = "man:sshguard(8)"; diff --git a/nixos/modules/services/security/usbguard.nix b/nixos/modules/services/security/usbguard.nix index 88d2f69db5729..20d5e3b28eb9e 100644 --- a/nixos/modules/services/security/usbguard.nix +++ b/nixos/modules/services/security/usbguard.nix @@ -39,6 +39,16 @@ in { services.usbguard = { enable = mkEnableOption "USBGuard daemon"; + package = mkOption { + type = types.package; + default = pkgs.usbguard; + defaultText = "pkgs.usbguard"; + description = '' + The usbguard package to use. If you do not need the Qt GUI, use + <literal>pkgs.usbguard-nox</literal> to save disk space. + ''; + }; + ruleFile = mkOption { type = types.path; default = "/var/lib/usbguard/rules.conf"; @@ -179,7 +189,7 @@ in { config = mkIf cfg.enable { - environment.systemPackages = [ pkgs.usbguard ]; + environment.systemPackages = [ cfg.package ]; systemd.services.usbguard = { description = "USBGuard daemon"; @@ -195,7 +205,7 @@ in { serviceConfig = { Type = "simple"; - ExecStart = ''${pkgs.usbguard}/bin/usbguard-daemon -P -k -c ${daemonConfFile}''; + ExecStart = ''${cfg.package}/bin/usbguard-daemon -P -k -c ${daemonConfFile}''; Restart = "on-failure"; }; }; diff --git a/nixos/modules/services/torrent/transmission.nix b/nixos/modules/services/torrent/transmission.nix index f544928fb6b1d..a94a471361ef8 100644 --- a/nixos/modules/services/torrent/transmission.nix +++ b/nixos/modules/services/torrent/transmission.nix @@ -84,6 +84,18 @@ in The directory where transmission will create files. ''; }; + + user = mkOption { + type = types.str; + default = "transmission"; + description = "User account under which Transmission runs."; + }; + + group = mkOption { + type = types.str; + default = "transmission"; + description = "Group account under which Transmission runs."; + }; }; }; @@ -99,7 +111,8 @@ in serviceConfig.ExecStartPre = preStart; serviceConfig.ExecStart = "${pkgs.transmission}/bin/transmission-daemon -f --port ${toString config.services.transmission.port}"; serviceConfig.ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; - serviceConfig.User = "transmission"; + serviceConfig.User = cfg.user; + serviceConfig.Group = cfg.group; # NOTE: transmission has an internal umask that also must be set (in settings.json) serviceConfig.UMask = "0002"; }; @@ -107,14 +120,19 @@ in # It's useful to have transmission in path, e.g. for remote control environment.systemPackages = [ pkgs.transmission ]; - users.groups.transmission.gid = config.ids.gids.transmission; - users.users.transmission = { - group = "transmission"; - uid = config.ids.uids.transmission; - description = "Transmission BitTorrent user"; - home = homeDir; - createHome = true; - }; + users.users = optionalAttrs (cfg.user == "transmission") (singleton + { name = "transmission"; + group = cfg.group; + uid = config.ids.uids.transmission; + description = "Transmission BitTorrent user"; + home = homeDir; + createHome = true; + }); + + users.groups = optionalAttrs (cfg.group == "transmission") (singleton + { name = "transmission"; + gid = config.ids.gids.transmission; + }); # AppArmor profile security.apparmor.profiles = mkIf apparmor [ diff --git a/nixos/modules/services/web-apps/icingaweb2/icingaweb2.nix b/nixos/modules/services/web-apps/icingaweb2/icingaweb2.nix index 6e5e5470c17fa..195ee76ff4e3b 100644 --- a/nixos/modules/services/web-apps/icingaweb2/icingaweb2.nix +++ b/nixos/modules/services/web-apps/icingaweb2/icingaweb2.nix @@ -1,14 +1,16 @@ { config, lib, pkgs, ... }: with lib; let cfg = config.services.icingaweb2; + fpm = config.services.phpfpm.pools.${poolName}; poolName = "icingaweb2"; - phpfpmSocketName = "/var/run/phpfpm/${poolName}.sock"; defaultConfig = { global = { - module_path = "${pkgs.icingaweb2}/modules${optionalString (builtins.length config.modulePath > 0) ":${concatStringsSep ":" config.modulePath}"}"; + module_path = "${pkgs.icingaweb2}/modules"; }; }; in { + meta.maintainers = with maintainers; [ das_j ]; + options.services.icingaweb2 = with types; { enable = mkEnableOption "the icingaweb2 web interface"; @@ -162,27 +164,26 @@ in { }; config = mkIf cfg.enable { - services.phpfpm.poolConfigs = mkIf (cfg.pool == "${poolName}") { - ${poolName} = '' - listen = "${phpfpmSocketName}" - listen.owner = nginx - listen.group = nginx - listen.mode = 0600 - user = icingaweb2 - pm = dynamic - pm.max_children = 75 - pm.start_servers = 2 - pm.min_spare_servers = 2 - pm.max_spare_servers = 10 - ''; + services.phpfpm.pools = mkIf (cfg.pool == "${poolName}") { + "${poolName}" = { + user = "icingaweb2"; + phpOptions = '' + extension = ${pkgs.phpPackages.imagick}/lib/php/extensions/imagick.so + date.timezone = "${cfg.timezone}" + ''; + settings = mapAttrs (name: mkDefault) { + "listen.owner" = "nginx"; + "listen.group" = "nginx"; + "listen.mode" = "0600"; + "pm" = "dynamic"; + "pm.max_children" = 75; + "pm.start_servers" = 2; + "pm.min_spare_servers" = 2; + "pm.max_spare_servers" = 10; + }; + }; }; - services.phpfpm.phpOptions = mkIf (cfg.pool == "${poolName}") - '' - extension = ${pkgs.phpPackages.imagick}/lib/php/extensions/imagick.so - date.timezone = "${cfg.timezone}" - ''; - systemd.services."phpfpm-${poolName}".serviceConfig.ReadWritePaths = [ "/etc/icingaweb2" ]; services.nginx = { @@ -206,7 +207,7 @@ in { include ${config.services.nginx.package}/conf/fastcgi.conf; try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; - fastcgi_pass unix:${phpfpmSocketName}; + fastcgi_pass unix:${fpm.socket}; fastcgi_param SCRIPT_FILENAME ${pkgs.icingaweb2}/public/index.php; ''; }; diff --git a/nixos/modules/services/web-apps/limesurvey.nix b/nixos/modules/services/web-apps/limesurvey.nix index c110c607e6c11..68b57a9b90ddf 100644 --- a/nixos/modules/services/web-apps/limesurvey.nix +++ b/nixos/modules/services/web-apps/limesurvey.nix @@ -120,15 +120,15 @@ in }; poolConfig = mkOption { - type = types.lines; - default = '' - pm = dynamic - pm.max_children = 32 - pm.start_servers = 2 - pm.min_spare_servers = 2 - pm.max_spare_servers = 4 - pm.max_requests = 500 - ''; + type = with types; attrsOf (oneOf [ str int bool ]); + default = { + "pm" = "dynamic"; + "pm.max_children" = 32; + "pm.start_servers" = 2; + "pm.min_spare_servers" = 2; + "pm.max_spare_servers" = 4; + "pm.max_requests" = 500; + }; description = '' Options for the LimeSurvey PHP pool. See the documentation on <literal>php-fpm.conf</literal> for details on configuration directives. @@ -203,17 +203,12 @@ in }; services.phpfpm.pools.limesurvey = { - listen = "/run/phpfpm/limesurvey.sock"; - extraConfig = '' - listen.owner = ${config.services.httpd.user}; - listen.group = ${config.services.httpd.group}; - user = ${user}; - group = ${group}; - - env[LIMESURVEY_CONFIG] = ${limesurveyConfig} - - ${cfg.poolConfig} - ''; + inherit user group; + phpEnv.LIMESURVEY_CONFIG = "${limesurveyConfig}"; + settings = { + "listen.owner" = config.services.httpd.user; + "listen.group" = config.services.httpd.group; + } // cfg.poolConfig; }; services.httpd = { @@ -241,7 +236,7 @@ in <Directory "${pkg}/share/limesurvey"> <FilesMatch "\.php$"> <If "-f %{REQUEST_FILENAME}"> - SetHandler "proxy:unix:${fpm.listen}|fcgi://localhost/" + SetHandler "proxy:unix:${fpm.socket}|fcgi://localhost/" </If> </FilesMatch> diff --git a/nixos/modules/services/web-apps/matomo.nix b/nixos/modules/services/web-apps/matomo.nix index 14aca45a342ba..d9f840408cc82 100644 --- a/nixos/modules/services/web-apps/matomo.nix +++ b/nixos/modules/services/web-apps/matomo.nix @@ -176,7 +176,7 @@ in { # Use User-Private Group scheme to protect Matomo data, but allow administration / backup via 'matomo' group # Copy config folder chmod g+s "${dataDir}" - cp -r "${cfg.package}/config" "${dataDir}/" + cp -r "${cfg.package}/share/config" "${dataDir}/" chmod -R u+rwX,g+rwX,o-rwx "${dataDir}" # check whether user setup has already been done @@ -225,22 +225,24 @@ in { serviceConfig.UMask = "0007"; }; - services.phpfpm.poolConfigs = let + services.phpfpm.pools = let # workaround for when both are null and need to generate a string, # which is illegal, but as assertions apparently are being triggered *after* config generation, # we have to avoid already throwing errors at this previous stage. socketOwner = if (cfg.nginx != null) then config.services.nginx.user else if (cfg.webServerUser != null) then cfg.webServerUser else ""; in { - ${pool} = '' - listen = "${phpSocket}" - listen.owner = ${socketOwner} - listen.group = root - listen.mode = 0600 - user = ${user} - env[PIWIK_USER_PATH] = ${dataDir} - ${cfg.phpfpmProcessManagerConfig} - ''; + ${pool} = { + listen = phpSocket; + extraConfig = '' + listen.owner = ${socketOwner} + listen.group = root + listen.mode = 0600 + user = ${user} + env[PIWIK_USER_PATH] = ${dataDir} + ${cfg.phpfpmProcessManagerConfig} + ''; + }; }; diff --git a/nixos/modules/services/web-apps/mediawiki.nix b/nixos/modules/services/web-apps/mediawiki.nix index 5bd5977e592b5..ec2568bf952d3 100644 --- a/nixos/modules/services/web-apps/mediawiki.nix +++ b/nixos/modules/services/web-apps/mediawiki.nix @@ -312,17 +312,17 @@ in }; poolConfig = mkOption { - type = types.lines; - default = '' - pm = dynamic - pm.max_children = 32 - pm.start_servers = 2 - pm.min_spare_servers = 2 - pm.max_spare_servers = 4 - pm.max_requests = 500 - ''; + type = with types; attrsOf (oneOf [ str int bool ]); + default = { + "pm" = "dynamic"; + "pm.max_children" = 32; + "pm.start_servers" = 2; + "pm.min_spare_servers" = 2; + "pm.max_spare_servers" = 4; + "pm.max_requests" = 500; + }; description = '' - Options for MediaWiki's PHP pool. See the documentation on <literal>php-fpm.conf</literal> + Options for the MediaWiki PHP pool. See the documentation on <literal>php-fpm.conf</literal> for details on configuration directives. ''; }; @@ -379,17 +379,12 @@ in }; services.phpfpm.pools.mediawiki = { - listen = "/run/phpfpm/mediawiki.sock"; - extraConfig = '' - listen.owner = ${config.services.httpd.user} - listen.group = ${config.services.httpd.group} - user = ${user} - group = ${group} - - env[MEDIAWIKI_CONFIG] = ${mediawikiConfig} - - ${cfg.poolConfig} - ''; + inherit user group; + phpEnv.MEDIAWIKI_CONFIG = "${mediawikiConfig}"; + settings = { + "listen.owner" = config.services.httpd.user; + "listen.group" = config.services.httpd.group; + } // cfg.poolConfig; }; services.httpd = { @@ -403,7 +398,7 @@ in <Directory "${pkg}/share/mediawiki"> <FilesMatch "\.php$"> <If "-f %{REQUEST_FILENAME}"> - SetHandler "proxy:unix:${fpm.listen}|fcgi://localhost/" + SetHandler "proxy:unix:${fpm.socket}|fcgi://localhost/" </If> </FilesMatch> diff --git a/nixos/modules/services/web-apps/moodle.nix b/nixos/modules/services/web-apps/moodle.nix new file mode 100644 index 0000000000000..f2516c67c6b31 --- /dev/null +++ b/nixos/modules/services/web-apps/moodle.nix @@ -0,0 +1,300 @@ +{ config, lib, pkgs, ... }: + +let + inherit (lib) mkDefault mkEnableOption mkForce mkIf mkMerge mkOption types; + inherit (lib) concatStringsSep literalExample mapAttrsToList optional optionalString; + + cfg = config.services.moodle; + fpm = config.services.phpfpm.pools.moodle; + + user = "moodle"; + group = config.services.httpd.group; + stateDir = "/var/lib/moodle"; + + moodleConfig = pkgs.writeText "config.php" '' + <?php // Moodle configuration file + + unset($CFG); + global $CFG; + $CFG = new stdClass(); + + $CFG->dbtype = '${ { "mysql" = "mariadb"; "pgsql" = "pgsql"; }.${cfg.database.type} }'; + $CFG->dblibrary = 'native'; + $CFG->dbhost = '${cfg.database.host}'; + $CFG->dbname = '${cfg.database.name}'; + $CFG->dbuser = '${cfg.database.user}'; + ${optionalString (cfg.database.passwordFile != null) "$CFG->dbpass = file_get_contents('${cfg.database.passwordFile}');"} + $CFG->prefix = 'mdl_'; + $CFG->dboptions = array ( + 'dbpersist' => 0, + 'dbport' => '${toString cfg.database.port}', + ${optionalString (cfg.database.socket != null) "'dbsocket' => '${cfg.database.socket}',"} + 'dbcollation' => 'utf8mb4_unicode_ci', + ); + + $CFG->wwwroot = '${if cfg.virtualHost.enableSSL then "https" else "http"}://${cfg.virtualHost.hostName}'; + $CFG->dataroot = '${stateDir}'; + $CFG->admin = 'admin'; + + $CFG->directorypermissions = 02777; + $CFG->disableupdateautodeploy = true; + + $CFG->pathtogs = '${pkgs.ghostscript}/bin/gs'; + $CFG->pathtophp = '${pkgs.php}/bin/php'; + $CFG->pathtodu = '${pkgs.coreutils}/bin/du'; + $CFG->aspellpath = '${pkgs.aspell}/bin/aspell'; + $CFG->pathtodot = '${pkgs.graphviz}/bin/dot'; + + require_once('${cfg.package}/share/moodle/lib/setup.php'); + + // There is no php closing tag in this file, + // it is intentional because it prevents trailing whitespace problems! + ''; + + mysqlLocal = cfg.database.createLocally && cfg.database.type == "mysql"; + pgsqlLocal = cfg.database.createLocally && cfg.database.type == "pgsql"; +in +{ + # interface + options.services.moodle = { + enable = mkEnableOption "Moodle web application"; + + package = mkOption { + type = types.package; + default = pkgs.moodle; + defaultText = "pkgs.moodle"; + description = "The Moodle package to use."; + }; + + initialPassword = mkOption { + type = types.str; + example = "correcthorsebatterystaple"; + description = '' + Specifies the initial password for the admin, i.e. the password assigned if the user does not already exist. + The password specified here is world-readable in the Nix store, so it should be changed promptly. + ''; + }; + + database = { + type = mkOption { + type = types.enum [ "mysql" "pgsql" ]; + default = "mysql"; + description = ''Database engine to use.''; + }; + + host = mkOption { + type = types.str; + default = "localhost"; + description = "Database host address."; + }; + + port = mkOption { + type = types.int; + description = "Database host port."; + default = { + "mysql" = 3306; + "pgsql" = 5432; + }.${cfg.database.type}; + defaultText = "3306"; + }; + + name = mkOption { + type = types.str; + default = "moodle"; + description = "Database name."; + }; + + user = mkOption { + type = types.str; + default = "moodle"; + description = "Database user."; + }; + + passwordFile = mkOption { + type = types.nullOr types.path; + default = null; + example = "/run/keys/moodle-dbpassword"; + description = '' + A file containing the password corresponding to + <option>database.user</option>. + ''; + }; + + socket = mkOption { + type = types.nullOr types.path; + default = + if mysqlLocal then "/run/mysqld/mysqld.sock" + else if pgsqlLocal then "/run/postgresql" + else null; + defaultText = "/run/mysqld/mysqld.sock"; + description = "Path to the unix socket file to use for authentication."; + }; + + createLocally = mkOption { + type = types.bool; + default = true; + description = "Create the database and database user locally."; + }; + }; + + virtualHost = mkOption { + type = types.submodule ({ + options = import ../web-servers/apache-httpd/per-server-options.nix { + inherit lib; + forMainServer = false; + }; + }); + example = { + hostName = "moodle.example.org"; + enableSSL = true; + adminAddr = "webmaster@example.org"; + sslServerCert = "/var/lib/acme/moodle.example.org/full.pem"; + sslServerKey = "/var/lib/acme/moodle.example.org/key.pem"; + }; + description = '' + Apache configuration can be done by adapting <option>services.httpd.virtualHosts</option>. + See <xref linkend="opt-services.httpd.virtualHosts"/> for further information. + ''; + }; + + poolConfig = mkOption { + type = with types; attrsOf (oneOf [ str int bool ]); + default = { + "pm" = "dynamic"; + "pm.max_children" = 32; + "pm.start_servers" = 2; + "pm.min_spare_servers" = 2; + "pm.max_spare_servers" = 4; + "pm.max_requests" = 500; + }; + description = '' + Options for the Moodle PHP pool. See the documentation on <literal>php-fpm.conf</literal> + for details on configuration directives. + ''; + }; + }; + + # implementation + config = mkIf cfg.enable { + + assertions = [ + { assertion = cfg.database.createLocally -> cfg.database.user == user; + message = "services.moodle.database.user must be set to ${user} if services.moodle.database.createLocally is set true"; + } + { assertion = cfg.database.createLocally -> cfg.database.passwordFile == null; + message = "a password cannot be specified if services.moodle.database.createLocally is set to true"; + } + ]; + + services.mysql = mkIf mysqlLocal { + enable = true; + package = mkDefault pkgs.mariadb; + ensureDatabases = [ cfg.database.name ]; + ensureUsers = [ + { name = cfg.database.user; + ensurePermissions = { + "${cfg.database.name}.*" = "SELECT, INSERT, UPDATE, DELETE, CREATE, CREATE TEMPORARY TABLES, DROP, INDEX, ALTER"; + }; + } + ]; + }; + + services.postgresql = mkIf pgsqlLocal { + enable = true; + ensureDatabases = [ cfg.database.name ]; + ensureUsers = [ + { name = cfg.database.user; + ensurePermissions = { "DATABASE ${cfg.database.name}" = "ALL PRIVILEGES"; }; + } + ]; + }; + + services.phpfpm.pools.moodle = { + inherit user group; + phpEnv.MOODLE_CONFIG = "${moodleConfig}"; + phpOptions = '' + zend_extension = opcache.so + opcache.enable = 1 + ''; + settings = { + "listen.owner" = config.services.httpd.user; + "listen.group" = config.services.httpd.group; + } // cfg.poolConfig; + }; + + services.httpd = { + enable = true; + adminAddr = mkDefault cfg.virtualHost.adminAddr; + extraModules = [ "proxy_fcgi" ]; + virtualHosts = [ (mkMerge [ + cfg.virtualHost { + documentRoot = mkForce "${cfg.package}/share/moodle"; + extraConfig = '' + <Directory "${cfg.package}/share/moodle"> + <FilesMatch "\.php$"> + <If "-f %{REQUEST_FILENAME}"> + SetHandler "proxy:unix:${fpm.socket}|fcgi://localhost/" + </If> + </FilesMatch> + Options -Indexes + DirectoryIndex index.php + </Directory> + ''; + } + ]) ]; + }; + + systemd.tmpfiles.rules = [ + "d '${stateDir}' 0750 ${user} ${group} - -" + ]; + + systemd.services.moodle-init = { + wantedBy = [ "multi-user.target" ]; + before = [ "phpfpm-moodle.service" ]; + after = optional mysqlLocal "mysql.service" ++ optional pgsqlLocal "postgresql.service"; + environment.MOODLE_CONFIG = moodleConfig; + script = '' + ${pkgs.php}/bin/php ${cfg.package}/share/moodle/admin/cli/check_database_schema.php && rc=$? || rc=$? + + [ "$rc" == 1 ] && ${pkgs.php}/bin/php ${cfg.package}/share/moodle/admin/cli/upgrade.php \ + --non-interactive \ + --allow-unstable + + [ "$rc" == 2 ] && ${pkgs.php}/bin/php ${cfg.package}/share/moodle/admin/cli/install_database.php \ + --agree-license \ + --adminpass=${cfg.initialPassword} + + true + ''; + serviceConfig = { + User = user; + Group = group; + Type = "oneshot"; + }; + }; + + systemd.services.moodle-cron = { + description = "Moodle cron service"; + after = [ "moodle-init.service" ]; + environment.MOODLE_CONFIG = moodleConfig; + serviceConfig = { + User = user; + Group = group; + ExecStart = "${pkgs.php}/bin/php ${cfg.package}/share/moodle/admin/cli/cron.php"; + }; + }; + + systemd.timers.moodle-cron = { + description = "Moodle cron timer"; + wantedBy = [ "timers.target" ]; + timerConfig = { + OnCalendar = "minutely"; + }; + }; + + systemd.services.httpd.after = optional mysqlLocal "mysql.service" ++ optional pgsqlLocal "postgresql.service"; + + users.users."${user}".group = group; + + }; +} diff --git a/nixos/modules/services/web-apps/nextcloud.nix b/nixos/modules/services/web-apps/nextcloud.nix index e67ff611d9ddc..5f5469e485077 100644 --- a/nixos/modules/services/web-apps/nextcloud.nix +++ b/nixos/modules/services/web-apps/nextcloud.nix @@ -4,6 +4,7 @@ with lib; let cfg = config.services.nextcloud; + fpm = config.services.phpfpm.pools.nextcloud; phpPackage = pkgs.php73; phpPackages = pkgs.php73Packages; @@ -410,25 +411,20 @@ in { }; services.phpfpm = { - pools.nextcloud = let - phpAdminValues = (toKeyValue - (foldr (a: b: a // b) {} - (mapAttrsToList (k: v: { "php_admin_value[${k}]" = v; }) - phpOptions))); - in { - phpOptions = phpOptionsExtensions; + pools.nextcloud = { + user = "nextcloud"; + group = "nginx"; + phpOptions = phpOptionsExtensions + phpOptionsStr; phpPackage = phpPackage; - listen = "/run/phpfpm/nextcloud"; - extraConfig = '' - listen.owner = nginx - listen.group = nginx - user = nextcloud - group = nginx - ${cfg.poolConfig} - env[NEXTCLOUD_CONFIG_DIR] = ${cfg.home}/config - env[PATH] = /run/wrappers/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin:/usr/bin:/bin - ${phpAdminValues} - ''; + phpEnv = { + NEXTCLOUD_CONFIG_DIR = "${cfg.home}/config"; + PATH = "/run/wrappers/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin:/usr/bin:/bin"; + }; + settings = mapAttrs (name: mkDefault) { + "listen.owner" = "nginx"; + "listen.group" = "nginx"; + }; + extraConfig = cfg.poolConfig; }; }; @@ -489,7 +485,7 @@ in { fastcgi_param HTTPS ${if cfg.https then "on" else "off"}; fastcgi_param modHeadersAvailable true; fastcgi_param front_controller_active true; - fastcgi_pass unix:/run/phpfpm/nextcloud; + fastcgi_pass unix:${fpm.socket}; fastcgi_intercept_errors on; fastcgi_request_buffering off; fastcgi_read_timeout 120s; diff --git a/nixos/modules/services/web-apps/restya-board.nix b/nixos/modules/services/web-apps/restya-board.nix index 70dbae4e8d22d..11272ed591b85 100644 --- a/nixos/modules/services/web-apps/restya-board.nix +++ b/nixos/modules/services/web-apps/restya-board.nix @@ -9,11 +9,11 @@ with lib; let cfg = config.services.restya-board; + fpm = config.services.phpfpm.pools.${poolName}; runDir = "/run/restya-board"; poolName = "restya-board"; - phpfpmSocketName = "/run/phpfpm/${poolName}.sock"; in @@ -179,8 +179,9 @@ in config = mkIf cfg.enable { services.phpfpm.pools = { - ${poolName} = { - listen = phpfpmSocketName; + "${poolName}" = { + inherit (cfg) user group; + phpOptions = '' date.timezone = "CET" @@ -191,20 +192,18 @@ in auth_password = ${cfg.email.password} ''} ''; - extraConfig = '' - listen.owner = nginx - listen.group = nginx - listen.mode = 0600 - user = ${cfg.user} - group = ${cfg.group} - pm = dynamic - pm.max_children = 75 - pm.start_servers = 10 - pm.min_spare_servers = 5 - pm.max_spare_servers = 20 - pm.max_requests = 500 - catch_workers_output = 1 - ''; + settings = mapAttrs (name: mkDefault) { + "listen.owner" = "nginx"; + "listen.group" = "nginx"; + "listen.mode" = "0600"; + "pm" = "dynamic"; + "pm.max_children" = 75; + "pm.start_servers" = 10; + "pm.min_spare_servers" = 5; + "pm.max_spare_servers" = 20; + "pm.max_requests" = 500; + "catch_workers_output" = 1; + }; }; }; @@ -241,7 +240,7 @@ in tryFiles = "$uri =404"; extraConfig = '' include ${pkgs.nginx}/conf/fastcgi_params; - fastcgi_pass unix:${phpfpmSocketName}; + fastcgi_pass unix:${fpm.socket}; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PHP_VALUE "upload_max_filesize=9G \n post_max_size=9G \n max_execution_time=200 \n max_input_time=200 \n memory_limit=256M"; diff --git a/nixos/modules/services/web-apps/selfoss.nix b/nixos/modules/services/web-apps/selfoss.nix index 30d7fb1c8d221..d693c401565ff 100644 --- a/nixos/modules/services/web-apps/selfoss.nix +++ b/nixos/modules/services/web-apps/selfoss.nix @@ -4,7 +4,6 @@ let cfg = config.services.selfoss; poolName = "selfoss_pool"; - phpfpmSocketName = "/run/phpfpm/${poolName}.sock"; dataDir = "/var/lib/selfoss"; @@ -115,22 +114,22 @@ in }; config = mkIf cfg.enable { - - services.phpfpm.poolConfigs = mkIf (cfg.pool == "${poolName}") { - ${poolName} = '' - listen = "${phpfpmSocketName}"; - listen.owner = nginx - listen.group = nginx - listen.mode = 0600 - user = nginx - pm = dynamic - pm.max_children = 75 - pm.start_servers = 10 - pm.min_spare_servers = 5 - pm.max_spare_servers = 20 - pm.max_requests = 500 - catch_workers_output = 1 - ''; + services.phpfpm.pools = mkIf (cfg.pool == "${poolName}") { + "${poolName}" = { + user = "nginx"; + settings = mapAttrs (name: mkDefault) { + "listen.owner" = "nginx"; + "listen.group" = "nginx"; + "listen.mode" = "0600"; + "pm" = "dynamic"; + "pm.max_children" = 75; + "pm.start_servers" = 10; + "pm.min_spare_servers" = 5; + "pm.max_spare_servers" = 20; + "pm.max_requests" = 500; + "catch_workers_output" = 1; + }; + }; }; systemd.services.selfoss-config = { diff --git a/nixos/modules/services/web-apps/tt-rss.nix b/nixos/modules/services/web-apps/tt-rss.nix index 0dbe6d8175871..4daf3ff9f991c 100644 --- a/nixos/modules/services/web-apps/tt-rss.nix +++ b/nixos/modules/services/web-apps/tt-rss.nix @@ -520,21 +520,20 @@ let ]; services.phpfpm.pools = mkIf (cfg.pool == "${poolName}") { - ${poolName} = { - listen = "/var/run/phpfpm/${poolName}.sock"; - extraConfig = '' - listen.owner = nginx - listen.group = nginx - listen.mode = 0600 - user = ${cfg.user} - pm = dynamic - pm.max_children = 75 - pm.start_servers = 10 - pm.min_spare_servers = 5 - pm.max_spare_servers = 20 - pm.max_requests = 500 - catch_workers_output = 1 - ''; + "${poolName}" = { + inherit (cfg) user; + settings = mapAttrs (name: mkDefault) { + "listen.owner" = "nginx"; + "listen.group" = "nginx"; + "listen.mode" = "0600"; + "pm" = "dynamic"; + "pm.max_children" = 75; + "pm.start_servers" = 10; + "pm.min_spare_servers" = 5; + "pm.max_spare_servers" = 20; + "pm.max_requests" = 500; + "catch_workers_output" = 1; + }; }; }; @@ -552,7 +551,7 @@ let locations."~ \.php$" = { extraConfig = '' fastcgi_split_path_info ^(.+\.php)(/.+)$; - fastcgi_pass unix:${config.services.phpfpm.pools.${cfg.pool}.listen}; + fastcgi_pass unix:${config.services.phpfpm.pools.${cfg.pool}.socket}; fastcgi_index index.php; ''; }; diff --git a/nixos/modules/services/web-apps/wordpress.nix b/nixos/modules/services/web-apps/wordpress.nix index 624b0089a0376..98dc84588189c 100644 --- a/nixos/modules/services/web-apps/wordpress.nix +++ b/nixos/modules/services/web-apps/wordpress.nix @@ -216,15 +216,15 @@ let }; poolConfig = mkOption { - type = types.lines; - default = '' - pm = dynamic - pm.max_children = 32 - pm.start_servers = 2 - pm.min_spare_servers = 2 - pm.max_spare_servers = 4 - pm.max_requests = 500 - ''; + type = with types; attrsOf (oneOf [ str int bool ]); + default = { + "pm" = "dynamic"; + "pm.max_children" = 32; + "pm.start_servers" = 2; + "pm.min_spare_servers" = 2; + "pm.max_spare_servers" = 4; + "pm.max_requests" = 500; + }; description = '' Options for the WordPress PHP pool. See the documentation on <literal>php-fpm.conf</literal> for details on configuration directives. @@ -280,15 +280,11 @@ in services.phpfpm.pools = mapAttrs' (hostName: cfg: ( nameValuePair "wordpress-${hostName}" { - listen = "/run/phpfpm/wordpress-${hostName}.sock"; - extraConfig = '' - listen.owner = ${config.services.httpd.user} - listen.group = ${config.services.httpd.group} - user = ${user} - group = ${group} - - ${cfg.poolConfig} - ''; + inherit user group; + settings = { + "listen.owner" = config.services.httpd.user; + "listen.group" = config.services.httpd.group; + } // cfg.poolConfig; } )) eachSite; @@ -303,7 +299,7 @@ in <Directory "${pkg hostName cfg}/share/wordpress"> <FilesMatch "\.php$"> <If "-f %{REQUEST_FILENAME}"> - SetHandler "proxy:unix:/run/phpfpm/wordpress-${hostName}.sock|fcgi://localhost/" + SetHandler "proxy:unix:${config.services.phpfpm.pools."wordpress-${hostName}".socket}|fcgi://localhost/" </If> </FilesMatch> diff --git a/nixos/modules/services/web-apps/zabbix.nix b/nixos/modules/services/web-apps/zabbix.nix index 5517cda64c71f..dac243b20e97a 100644 --- a/nixos/modules/services/web-apps/zabbix.nix +++ b/nixos/modules/services/web-apps/zabbix.nix @@ -133,15 +133,15 @@ in }; poolConfig = mkOption { - type = types.lines; - default = '' - pm = dynamic - pm.max_children = 32 - pm.start_servers = 2 - pm.min_spare_servers = 2 - pm.max_spare_servers = 4 - pm.max_requests = 500 - ''; + type = with types; attrsOf (oneOf [ str int bool ]); + default = { + "pm" = "dynamic"; + "pm.max_children" = 32; + "pm.start_servers" = 2; + "pm.min_spare_servers" = 2; + "pm.max_spare_servers" = 4; + "pm.max_requests" = 500; + }; description = '' Options for the Zabbix PHP pool. See the documentation on <literal>php-fpm.conf</literal> for details on configuration directives. ''; @@ -160,6 +160,8 @@ in ]; services.phpfpm.pools.zabbix = { + inherit user; + group = config.services.httpd.group; phpOptions = '' # https://www.zabbix.com/documentation/current/manual/installation/install memory_limit = 128M @@ -177,15 +179,11 @@ in '' + optionalString (cfg.database.type == "oracle") '' extension=${pkgs.phpPackages.oci8}/lib/php/extensions/oci8.so ''; - listen = "/run/phpfpm/zabbix.sock"; - extraConfig = '' - listen.owner = ${config.services.httpd.user}; - listen.group = ${config.services.httpd.group}; - user = ${user}; - group = ${config.services.httpd.group}; - env[ZABBIX_CONFIG] = ${zabbixConfig} - ${cfg.poolConfig} - ''; + phpEnv.ZABBIX_CONFIG = zabbixConfig; + settings = { + "listen.owner" = config.services.httpd.user; + "listen.group" = config.services.httpd.group; + } // cfg.poolConfig; }; services.httpd = { diff --git a/nixos/modules/services/web-servers/caddy.nix b/nixos/modules/services/web-servers/caddy.nix index d0b936cb019fd..6a1db6087840a 100644 --- a/nixos/modules/services/web-servers/caddy.nix +++ b/nixos/modules/services/web-servers/caddy.nix @@ -70,7 +70,7 @@ in { { CADDYPATH = cfg.dataDir; }; serviceConfig = { ExecStart = '' - ${cfg.package.bin}/bin/caddy -root=/var/tmp -conf=${configFile} \ + ${cfg.package}/bin/caddy -root=/var/tmp -conf=${configFile} \ -ca=${cfg.ca} -email=${cfg.email} ${optionalString cfg.agree "-agree"} ''; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; diff --git a/nixos/modules/services/web-servers/darkhttpd.nix b/nixos/modules/services/web-servers/darkhttpd.nix new file mode 100644 index 0000000000000..80870118c334b --- /dev/null +++ b/nixos/modules/services/web-servers/darkhttpd.nix @@ -0,0 +1,77 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.darkhttpd; + + args = concatStringsSep " " ([ + cfg.rootDir + "--port ${toString cfg.port}" + "--addr ${cfg.address}" + ] ++ cfg.extraArgs + ++ optional cfg.hideServerId "--no-server-id" + ++ optional config.networking.enableIPv6 "--ipv6"); + +in { + options.services.darkhttpd = with types; { + enable = mkEnableOption "DarkHTTPd web server"; + + port = mkOption { + default = 80; + type = ints.u16; + description = '' + Port to listen on. + Pass 0 to let the system choose any free port for you. + ''; + }; + + address = mkOption { + default = "127.0.0.1"; + type = str; + description = '' + Address to listen on. + Pass `all` to listen on all interfaces. + ''; + }; + + rootDir = mkOption { + type = path; + description = '' + Path from which to serve files. + ''; + }; + + hideServerId = mkOption { + type = bool; + default = true; + description = '' + Don't identify the server type in headers or directory listings. + ''; + }; + + extraArgs = mkOption { + type = listOf str; + default = []; + description = '' + Additional configuration passed to the executable. + ''; + }; + }; + + config = mkIf cfg.enable { + systemd.services.darkhttpd = { + description = "Dark HTTPd"; + wants = [ "network.target" ]; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + DynamicUser = true; + ExecStart = "${cfg.package}/bin/darkhttpd ${args}"; + AmbientCapabilities = lib.mkIf (cfg.port < 1024) [ "CAP_NET_BIND_SERVICE" ]; + Restart = "on-failure"; + RestartSec = "2s"; + }; + }; + }; +} diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix index 2b7fcb3140417..c1a51fbf8b425 100644 --- a/nixos/modules/services/web-servers/nginx/default.nix +++ b/nixos/modules/services/web-servers/nginx/default.nix @@ -162,6 +162,10 @@ let ${cfg.appendConfig} ''; + configPath = if cfg.enableReload + then "/etc/nginx/nginx.conf" + else configFile; + vhosts = concatStringsSep "\n" (mapAttrsToList (vhostName: vhost: let onlySSL = vhost.onlySSL || vhost.enableSSL; @@ -431,6 +435,16 @@ in "; }; + enableReload = mkOption { + default = false; + type = types.bool; + description = '' + Reload nginx when configuration file changes (instead of restart). + The configuration file is exposed at <filename>/etc/nginx/nginx.conf</filename>. + See also <literal>systemd.services.*.restartIfChanged</literal>. + ''; + }; + stateDir = mkOption { default = "/var/spool/nginx"; description = " @@ -638,10 +652,10 @@ in preStart = '' ${cfg.preStart} - ${cfg.package}/bin/nginx -c ${configFile} -p ${cfg.stateDir} -t + ${cfg.package}/bin/nginx -c ${configPath} -p ${cfg.stateDir} -t ''; serviceConfig = { - ExecStart = "${cfg.package}/bin/nginx -c ${configFile} -p ${cfg.stateDir}"; + ExecStart = "${cfg.package}/bin/nginx -c ${configPath} -p ${cfg.stateDir}"; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; Restart = "always"; RestartSec = "10s"; @@ -649,6 +663,21 @@ in }; }; + environment.etc."nginx/nginx.conf" = mkIf cfg.enableReload { + source = configFile; + }; + + systemd.services.nginx-config-reload = mkIf cfg.enableReload { + wantedBy = [ "nginx.service" ]; + restartTriggers = [ configFile ]; + script = '' + if ${pkgs.systemd}/bin/systemctl -q is-active nginx.service ; then + ${pkgs.systemd}/bin/systemctl reload nginx.service + fi + ''; + serviceConfig.RemainAfterExit = true; + }; + security.acme.certs = filterAttrs (n: v: v != {}) ( let vhostsConfigs = mapAttrsToList (vhostName: vhostConfig: vhostConfig) virtualHosts; diff --git a/nixos/modules/services/web-servers/phpfpm/default.nix b/nixos/modules/services/web-servers/phpfpm/default.nix index ffafbc5e92f21..e95e71e0d997e 100644 --- a/nixos/modules/services/web-servers/phpfpm/default.nix +++ b/nixos/modules/services/web-servers/phpfpm/default.nix @@ -4,41 +4,27 @@ with lib; let cfg = config.services.phpfpm; - enabled = cfg.poolConfigs != {} || cfg.pools != {}; - stateDir = "/run/phpfpm"; + runtimeDir = "/run/phpfpm"; - poolConfigs = - (mapAttrs mapPoolConfig cfg.poolConfigs) // - (mapAttrs mapPool cfg.pools); + toStr = value: + if true == value then "yes" + else if false == value then "no" + else toString value; - mapPoolConfig = n: p: { - phpPackage = cfg.phpPackage; - phpOptions = cfg.phpOptions; - config = p; - }; - - mapPool = n: p: { - phpPackage = p.phpPackage; - phpOptions = p.phpOptions; - config = '' - listen = ${p.listen} - ${p.extraConfig} - ''; - }; - - fpmCfgFile = pool: conf: pkgs.writeText "phpfpm-${pool}.conf" '' + fpmCfgFile = pool: poolOpts: pkgs.writeText "phpfpm-${pool}.conf" '' [global] - error_log = syslog - daemonize = no - ${cfg.extraConfig} + ${concatStringsSep "\n" (mapAttrsToList (n: v: "${n} = ${toStr v}") cfg.settings)} + ${optionalString (cfg.extraConfig != null) cfg.extraConfig} [${pool}] - ${conf} + ${concatStringsSep "\n" (mapAttrsToList (n: v: "${n} = ${toStr v}") poolOpts.settings)} + ${concatStringsSep "\n" (mapAttrsToList (n: v: "env[${n}] = ${toStr v}") poolOpts.phpEnv)} + ${optionalString (poolOpts.extraConfig != null) poolOpts.extraConfig} ''; - phpIni = pool: pkgs.runCommand "php.ini" { - inherit (pool) phpPackage phpOptions; + phpIni = poolOpts: pkgs.runCommand "php.ini" { + inherit (poolOpts) phpPackage phpOptions; preferLocalBuild = true; nixDefaults = '' sendmail_path = "/run/wrappers/bin/sendmail -t -i" @@ -48,13 +34,138 @@ let cat $phpPackage/etc/php.ini $nixDefaultsPath $phpOptionsPath > $out ''; + poolOpts = { name, ... }: + let + poolOpts = cfg.pools."${name}"; + in + { + options = { + socket = mkOption { + type = types.str; + readOnly = true; + description = '' + Path to the unix socket file on which to accept FastCGI requests. + <note><para>This option is read-only and managed by NixOS.</para></note> + ''; + }; + + listen = mkOption { + type = types.str; + default = ""; + example = "/path/to/unix/socket"; + description = '' + The address on which to accept FastCGI requests. + ''; + }; + + phpPackage = mkOption { + type = types.package; + default = cfg.phpPackage; + defaultText = "config.services.phpfpm.phpPackage"; + description = '' + The PHP package to use for running this PHP-FPM pool. + ''; + }; + + phpOptions = mkOption { + type = types.lines; + default = cfg.phpOptions; + defaultText = "config.services.phpfpm.phpOptions"; + description = '' + "Options appended to the PHP configuration file <filename>php.ini</filename> used for this PHP-FPM pool." + ''; + }; + + phpEnv = lib.mkOption { + type = with types; attrsOf str; + default = {}; + description = '' + Environment variables used for this PHP-FPM pool. + ''; + example = literalExample '' + { + HOSTNAME = "$HOSTNAME"; + TMP = "/tmp"; + TMPDIR = "/tmp"; + TEMP = "/tmp"; + } + ''; + }; + + user = mkOption { + type = types.str; + description = "User account under which this pool runs."; + }; + + group = mkOption { + type = types.str; + description = "Group account under which this pool runs."; + }; + + settings = mkOption { + type = with types; attrsOf (oneOf [ str int bool ]); + default = {}; + description = '' + PHP-FPM pool directives. Refer to the "List of pool directives" section of + <link xlink:href="https://www.php.net/manual/en/install.fpm.configuration.php"/> + for details. Note that settings names must be enclosed in quotes (e.g. + <literal>"pm.max_children"</literal> instead of <literal>pm.max_children</literal>). + ''; + example = literalExample '' + { + "pm" = "dynamic"; + "pm.max_children" = 75; + "pm.start_servers" = 10; + "pm.min_spare_servers" = 5; + "pm.max_spare_servers" = 20; + "pm.max_requests" = 500; + } + ''; + }; + + extraConfig = mkOption { + type = with types; nullOr lines; + default = null; + description = '' + Extra lines that go into the pool configuration. + See the documentation on <literal>php-fpm.conf</literal> for + details on configuration directives. + ''; + }; + }; + + config = { + socket = if poolOpts.listen == "" then "${runtimeDir}/${name}.sock" else poolOpts.listen; + group = mkDefault poolOpts.user; + + settings = mapAttrs (name: mkDefault){ + listen = poolOpts.socket; + user = poolOpts.user; + group = poolOpts.group; + }; + }; + }; + in { options = { services.phpfpm = { + settings = mkOption { + type = with types; attrsOf (oneOf [ str int bool ]); + default = {}; + description = '' + PHP-FPM global directives. Refer to the "List of global php-fpm.conf directives" section of + <link xlink:href="https://www.php.net/manual/en/install.fpm.configuration.php"/> + for details. Note that settings names must be enclosed in quotes (e.g. + <literal>"pm.max_children"</literal> instead of <literal>pm.max_children</literal>). + You need not specify the options <literal>error_log</literal> or + <literal>daemonize</literal> here, since they are generated by NixOS. + ''; + }; + extraConfig = mkOption { - type = types.lines; - default = ""; + type = with types; nullOr lines; + default = null; description = '' Extra configuration that should be put in the global section of the PHP-FPM configuration file. Do not specify the options @@ -80,64 +191,56 @@ in { '' date.timezone = "CET" ''; - description = - "Options appended to the PHP configuration file <filename>php.ini</filename>."; - }; - - poolConfigs = mkOption { - default = {}; - type = types.attrsOf types.lines; - example = literalExample '' - { mypool = ''' - listen = /run/phpfpm/mypool - user = nobody - pm = dynamic - pm.max_children = 75 - pm.start_servers = 10 - pm.min_spare_servers = 5 - pm.max_spare_servers = 20 - pm.max_requests = 500 - '''; - } - ''; description = '' - A mapping between PHP-FPM pool names and their configurations. - See the documentation on <literal>php-fpm.conf</literal> for - details on configuration directives. If no pools are defined, - the phpfpm service is disabled. + Options appended to the PHP configuration file <filename>php.ini</filename>. ''; }; pools = mkOption { - type = types.attrsOf (types.submodule (import ./pool-options.nix { - inherit lib config; - })); + type = types.attrsOf (types.submodule poolOpts); default = {}; example = literalExample '' { mypool = { - listen = "/path/to/unix/socket"; + user = "php"; + group = "php"; phpPackage = pkgs.php; - extraConfig = ''' - user = nobody - pm = dynamic - pm.max_children = 75 - pm.start_servers = 10 - pm.min_spare_servers = 5 - pm.max_spare_servers = 20 - pm.max_requests = 500 + settings = ''' + "pm" = "dynamic"; + "pm.max_children" = 75; + "pm.start_servers" = 10; + "pm.min_spare_servers" = 5; + "pm.max_spare_servers" = 20; + "pm.max_requests" = 500; '''; } }''; description = '' - PHP-FPM pools. If no pools or poolConfigs are defined, the PHP-FPM + PHP-FPM pools. If no pools are defined, the PHP-FPM service is disabled. ''; }; }; }; - config = mkIf enabled { + config = mkIf (cfg.pools != {}) { + + warnings = + mapAttrsToList (pool: poolOpts: '' + Using config.services.phpfpm.pools.${pool}.listen is deprecated and will become unsupported in a future release. Please reference the read-only option config.services.phpfpm.pools.${pool}.socket to access the path of your socket. + '') (filterAttrs (pool: poolOpts: poolOpts.listen != "") cfg.pools) ++ + mapAttrsToList (pool: poolOpts: '' + Using config.services.phpfpm.pools.${pool}.extraConfig is deprecated and will become unsupported in a future release. Please migrate your configuration to config.services.phpfpm.pools.${pool}.settings. + '') (filterAttrs (pool: poolOpts: poolOpts.extraConfig != null) cfg.pools) ++ + optional (cfg.extraConfig != null) '' + Using config.services.phpfpm.extraConfig is deprecated and will become unsupported in a future release. Please migrate your configuration to config.services.phpfpm.settings. + '' + ; + + services.phpfpm.settings = { + error_log = "syslog"; + daemonize = false; + }; systemd.slices.phpfpm = { description = "PHP FastCGI Process manager pools slice"; @@ -148,18 +251,15 @@ in { wantedBy = [ "multi-user.target" ]; }; - systemd.services = flip mapAttrs' poolConfigs (pool: poolConfig: + systemd.services = mapAttrs' (pool: poolOpts: nameValuePair "phpfpm-${pool}" { description = "PHP FastCGI Process Manager service for pool ${pool}"; after = [ "network.target" ]; wantedBy = [ "phpfpm.target" ]; partOf = [ "phpfpm.target" ]; - preStart = '' - mkdir -p ${stateDir} - ''; serviceConfig = let - cfgFile = fpmCfgFile pool poolConfig.config; - iniFile = phpIni poolConfig; + cfgFile = fpmCfgFile pool poolOpts; + iniFile = phpIni poolOpts; in { Slice = "phpfpm.slice"; PrivateDevices = true; @@ -168,10 +268,12 @@ in { # XXX: We need AF_NETLINK to make the sendmail SUID binary from postfix work RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_NETLINK"; Type = "notify"; - ExecStart = "${poolConfig.phpPackage}/bin/php-fpm -y ${cfgFile} -c ${iniFile}"; + ExecStart = "${poolOpts.phpPackage}/bin/php-fpm -y ${cfgFile} -c ${iniFile}"; ExecReload = "${pkgs.coreutils}/bin/kill -USR2 $MAINPID"; + RuntimeDirectory = "phpfpm"; + RuntimeDirectoryPreserve = true; # Relevant when multiple processes are running }; } - ); + ) cfg.pools; }; } diff --git a/nixos/modules/services/web-servers/phpfpm/pool-options.nix b/nixos/modules/services/web-servers/phpfpm/pool-options.nix deleted file mode 100644 index d9ad7eff71f2c..0000000000000 --- a/nixos/modules/services/web-servers/phpfpm/pool-options.nix +++ /dev/null @@ -1,57 +0,0 @@ -{ lib, config }: - -let - fpmCfg = config.services.phpfpm; -in - -with lib; { - - options = { - - listen = mkOption { - type = types.str; - example = "/path/to/unix/socket"; - description = '' - The address on which to accept FastCGI requests. - ''; - }; - - phpPackage = mkOption { - type = types.package; - default = fpmCfg.phpPackage; - defaultText = "config.services.phpfpm.phpPackage"; - description = '' - The PHP package to use for running this PHP-FPM pool. - ''; - }; - - phpOptions = mkOption { - type = types.lines; - default = fpmCfg.phpOptions; - defaultText = "config.services.phpfpm.phpOptions"; - description = '' - "Options appended to the PHP configuration file <filename>php.ini</filename> used for this PHP-FPM pool." - ''; - }; - - extraConfig = mkOption { - type = types.lines; - example = '' - user = nobody - pm = dynamic - pm.max_children = 75 - pm.start_servers = 10 - pm.min_spare_servers = 5 - pm.max_spare_servers = 20 - pm.max_requests = 500 - ''; - - description = '' - Extra lines that go into the pool configuration. - See the documentation on <literal>php-fpm.conf</literal> for - details on configuration directives. - ''; - }; - }; -} - diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix index c5c2e0bffc127..0caa93ad217fd 100644 --- a/nixos/modules/services/x11/desktop-managers/gnome3.nix +++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix @@ -3,7 +3,9 @@ with lib; let + cfg = config.services.xserver.desktopManager.gnome3; + serviceCfg = config.services.gnome3; # Prioritize nautilus by default when opening directories mimeAppsList = pkgs.writeTextFile { @@ -29,10 +31,10 @@ let chmod -R a+w $out/share/gsettings-schemas/nixos-gsettings-overrides cat - > $out/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas/nixos-defaults.gschema.override <<- EOF [org.gnome.desktop.background] - picture-uri='${pkgs.nixos-artwork.wallpapers.simple-dark-gray}/share/artwork/gnome/nix-wallpaper-simple-dark-gray.png' + picture-uri='file://${pkgs.nixos-artwork.wallpapers.simple-dark-gray}/share/artwork/gnome/nix-wallpaper-simple-dark-gray.png' [org.gnome.desktop.screensaver] - picture-uri='${pkgs.nixos-artwork.wallpapers.simple-dark-gray-bottom}/share/artwork/gnome/nix-wallpaper-simple-dark-gray_bottom.png' + picture-uri='file://${pkgs.nixos-artwork.wallpapers.simple-dark-gray-bottom}/share/artwork/gnome/nix-wallpaper-simple-dark-gray_bottom.png' [org.gnome.shell] favorite-apps=[ 'org.gnome.Epiphany.desktop', 'evolution.desktop', 'org.gnome.Music.desktop', 'org.gnome.Photos.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop' ] @@ -45,10 +47,19 @@ let flashbackEnabled = cfg.flashback.enableMetacity || length cfg.flashback.customSessions > 0; -in { +in + +{ options = { + services.gnome3 = { + core-os-services.enable = mkEnableOption "essential services for GNOME3"; + core-shell.enable = mkEnableOption "GNOME Shell services"; + core-utilities.enable = mkEnableOption "GNOME core utilities"; + games.enable = mkEnableOption "GNOME games"; + }; + services.xserver.desktopManager.gnome3 = { enable = mkOption { default = false; @@ -121,139 +132,194 @@ in { }; - config = mkIf cfg.enable { - - # Enable helpful DBus services. - security.polkit.enable = true; - services.udisks2.enable = true; - services.accounts-daemon.enable = true; - services.dleyna-renderer.enable = mkDefault true; - services.dleyna-server.enable = mkDefault true; - services.gnome3.at-spi2-core.enable = true; - services.gnome3.evolution-data-server.enable = true; - services.gnome3.glib-networking.enable = true; - services.gnome3.gnome-keyring.enable = true; - services.gnome3.gnome-online-accounts.enable = mkDefault true; - services.gnome3.gnome-remote-desktop.enable = mkDefault true; - services.gnome3.gnome-settings-daemon.enable = true; - services.gnome3.gnome-terminal-server.enable = mkDefault true; - services.gnome3.gnome-user-share.enable = mkDefault true; - services.gnome3.gvfs.enable = true; - services.gnome3.rygel.enable = mkDefault true; - services.gnome3.seahorse.enable = mkDefault true; - services.gnome3.sushi.enable = mkDefault true; - services.gnome3.tracker.enable = mkDefault true; - services.gnome3.tracker-miners.enable = mkDefault true; - hardware.pulseaudio.enable = mkDefault true; - services.telepathy.enable = mkDefault true; - networking.networkmanager.enable = mkDefault true; - services.upower.enable = config.powerManagement.enable; - services.dbus.packages = - optional config.services.printing.enable pkgs.system-config-printer ++ - optional flashbackEnabled pkgs.gnome3.gnome-screensaver; - services.colord.enable = mkDefault true; - services.packagekit.enable = mkDefault true; - hardware.bluetooth.enable = mkDefault true; - services.hardware.bolt.enable = mkDefault true; - services.xserver.libinput.enable = mkDefault true; # for controlling touchpad settings via gnome control center - systemd.packages = [ pkgs.gnome3.vino ]; - xdg.portal.enable = true; - xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-gtk ]; - - # Enable default programs - programs.evince.enable = mkDefault true; - programs.file-roller.enable = mkDefault true; - programs.gnome-disks.enable = mkDefault true; - programs.gnome-documents.enable = mkDefault true; - - # If gnome3 is installed, build vim for gtk3 too. - nixpkgs.config.vim.gui = "gtk3"; - - fonts.fonts = [ - pkgs.dejavu_fonts pkgs.cantarell-fonts - pkgs.source-sans-pro - pkgs.source-code-pro # Default monospace font in 3.32 - ]; - - services.xserver.displayManager.extraSessionFilePackages = [ pkgs.gnome3.gnome-session ] - ++ map - (wm: pkgs.gnome3.gnome-flashback.mkSessionForWm { - inherit (wm) wmName wmLabel wmCommand; - }) (optional cfg.flashback.enableMetacity { - wmName = "metacity"; - wmLabel = "Metacity"; - wmCommand = "${pkgs.gnome3.metacity}/bin/metacity"; - } ++ cfg.flashback.customSessions); - - environment.extraInit = '' - ${concatMapStrings (p: '' - if [ -d "${p}/share/gsettings-schemas/${p.name}" ]; then - export XDG_DATA_DIRS=$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}${p}/share/gsettings-schemas/${p.name} - fi - - if [ -d "${p}/lib/girepository-1.0" ]; then - export GI_TYPELIB_PATH=$GI_TYPELIB_PATH''${GI_TYPELIB_PATH:+:}${p}/lib/girepository-1.0 - export LD_LIBRARY_PATH=$LD_LIBRARY_PATH''${LD_LIBRARY_PATH:+:}${p}/lib - fi - '') cfg.sessionPath} - ''; + config = mkMerge [ + (mkIf (cfg.enable || flashbackEnabled) { + services.gnome3.core-os-services.enable = true; + services.gnome3.core-shell.enable = true; + services.gnome3.core-utilities.enable = mkDefault true; + services.xserver.displayManager.extraSessionFilePackages = [ pkgs.gnome3.gnome-session ]; - services.geoclue2.enable = mkDefault true; - # GNOME should have its own geoclue agent - services.geoclue2.enableDemoAgent = false; + environment.extraInit = '' + ${concatMapStrings (p: '' + if [ -d "${p}/share/gsettings-schemas/${p.name}" ]; then + export XDG_DATA_DIRS=$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}${p}/share/gsettings-schemas/${p.name} + fi - services.geoclue2.appConfig.gnome-datetime-panel = { - isAllowed = true; - isSystem = true; - }; - services.geoclue2.appConfig.gnome-color-panel = { - isAllowed = true; - isSystem = true; - }; - services.geoclue2.appConfig."org.gnome.Shell" = { - isAllowed = true; - isSystem = true; - }; + if [ -d "${p}/lib/girepository-1.0" ]; then + export GI_TYPELIB_PATH=$GI_TYPELIB_PATH''${GI_TYPELIB_PATH:+:}${p}/lib/girepository-1.0 + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH''${LD_LIBRARY_PATH:+:}${p}/lib + fi + '') cfg.sessionPath} + ''; - environment.variables.GNOME_SESSION_DEBUG = optionalString cfg.debug "1"; + environment.systemPackages = cfg.sessionPath; - # Override default mimeapps - environment.variables.XDG_DATA_DIRS = [ "${mimeAppsList}/share" ]; + environment.variables.GNOME_SESSION_DEBUG = mkIf cfg.debug "1"; - # Override GSettings schemas - environment.variables.NIX_GSETTINGS_OVERRIDES_DIR = "${nixos-gsettings-desktop-schemas}/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas"; + # Override GSettings schemas + environment.variables.NIX_GSETTINGS_OVERRIDES_DIR = "${nixos-gsettings-desktop-schemas}/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas"; - # Let nautilus find extensions - # TODO: Create nautilus-with-extensions package - environment.variables.NAUTILUS_EXTENSION_DIR = "${config.system.path}/lib/nautilus/extensions-3.0"; + # If gnome3 is installed, build vim for gtk3 too. + nixpkgs.config.vim.gui = "gtk3"; + }) - services.xserver.updateDbusEnvironment = true; + (mkIf flashbackEnabled { + services.xserver.displayManager.extraSessionFilePackages = map + (wm: pkgs.gnome3.gnome-flashback.mkSessionForWm { + inherit (wm) wmName wmLabel wmCommand; + }) (optional cfg.flashback.enableMetacity { + wmName = "metacity"; + wmLabel = "Metacity"; + wmCommand = "${pkgs.gnome3.metacity}/bin/metacity"; + } ++ cfg.flashback.customSessions); - environment.variables.GIO_EXTRA_MODULES = [ "${lib.getLib pkgs.gnome3.dconf}/lib/gio/modules" - "${pkgs.gnome3.gvfs}/lib/gio/modules" ]; - environment.systemPackages = pkgs.gnome3.corePackages ++ cfg.sessionPath - ++ (pkgs.gnome3.removePackagesByName pkgs.gnome3.optionalPackages config.environment.gnome3.excludePackages) ++ [ - pkgs.xdg-user-dirs # Update user dirs as described in http://freedesktop.org/wiki/Software/xdg-user-dirs/ - ]; + security.pam.services.gnome-screensaver = { + enableGnomeKeyring = true; + }; - # Use the correct gnome3 packageSet - networking.networkmanager.basePackages = - { inherit (pkgs) networkmanager modemmanager wpa_supplicant crda; + services.dbus.packages = [ + pkgs.gnome3.gnome-screensaver + ]; + }) + + (mkIf serviceCfg.core-os-services.enable { + hardware.bluetooth.enable = mkDefault true; + hardware.pulseaudio.enable = mkDefault true; + programs.dconf.enable = true; + security.polkit.enable = true; + services.accounts-daemon.enable = true; + services.dleyna-renderer.enable = mkDefault true; + services.dleyna-server.enable = mkDefault true; + services.gnome3.at-spi2-core.enable = true; + services.gnome3.evolution-data-server.enable = true; + services.gnome3.gnome-keyring.enable = true; + services.gnome3.gnome-online-accounts.enable = mkDefault true; + services.gnome3.gnome-online-miners.enable = true; + services.gnome3.tracker-miners.enable = mkDefault true; + services.gnome3.tracker.enable = mkDefault true; + services.hardware.bolt.enable = mkDefault true; + services.packagekit.enable = mkDefault true; + services.udisks2.enable = true; + services.upower.enable = config.powerManagement.enable; + services.xserver.libinput.enable = mkDefault true; # for controlling touchpad settings via gnome control center + + xdg.portal.enable = true; + xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-gtk ]; + + networking.networkmanager.enable = mkDefault true; + + # Use the correct gnome3 packageSet + networking.networkmanager.basePackages = { + inherit (pkgs) networkmanager modemmanager wpa_supplicant crda; inherit (pkgs.gnome3) networkmanager-openvpn networkmanager-vpnc - networkmanager-openconnect networkmanager-fortisslvpn - networkmanager-iodine networkmanager-l2tp; }; - - # Needed for themes and backgrounds - environment.pathsToLink = [ - "/share" - "/share/nautilus-python/extensions" - ]; + networkmanager-openconnect networkmanager-fortisslvpn + networkmanager-iodine networkmanager-l2tp; + }; - security.pam.services.gnome-screensaver = mkIf flashbackEnabled { - enableGnomeKeyring = true; - }; - }; + services.xserver.updateDbusEnvironment = true; + + # Needed for themes and backgrounds + environment.pathsToLink = [ + "/share" # TODO: https://github.com/NixOS/nixpkgs/issues/47173 + ]; + }) + + (mkIf serviceCfg.core-shell.enable { + services.colord.enable = mkDefault true; + services.gnome3.glib-networking.enable = true; + services.gnome3.gnome-remote-desktop.enable = mkDefault true; + services.gnome3.gnome-settings-daemon.enable = true; + services.gnome3.gnome-user-share.enable = mkDefault true; + services.gnome3.rygel.enable = mkDefault true; + services.gvfs.enable = true; + services.telepathy.enable = mkDefault true; + systemd.packages = [ pkgs.gnome3.vino ]; + services.dbus.packages = + optional config.services.printing.enable pkgs.system-config-printer; + + services.geoclue2.enable = mkDefault true; + services.geoclue2.enableDemoAgent = false; # GNOME has its own geoclue agent + + services.geoclue2.appConfig."gnome-datetime-panel" = { + isAllowed = true; + isSystem = true; + }; + services.geoclue2.appConfig."gnome-color-panel" = { + isAllowed = true; + isSystem = true; + }; + services.geoclue2.appConfig."org.gnome.Shell" = { + isAllowed = true; + isSystem = true; + }; + fonts.fonts = with pkgs; [ + cantarell-fonts + dejavu_fonts + source-code-pro # Default monospace font in 3.32 + source-sans-pro + ]; + + environment.systemPackages = with pkgs.gnome3; [ + adwaita-icon-theme + gnome-backgrounds + gnome-bluetooth + gnome-control-center + gnome-getting-started-docs + gnome-shell + gnome-shell-extensions + gnome-themes-extra + gnome-user-docs + pkgs.glib # for gsettings + pkgs.gnome-menus + pkgs.gtk3.out # for gtk-launch + pkgs.hicolor-icon-theme + pkgs.shared-mime-info # for update-mime-database + pkgs.xdg-user-dirs # Update user dirs as described in http://freedesktop.org/wiki/Software/xdg-user-dirs/ + vino + ]; + }) + + (mkIf serviceCfg.core-utilities.enable { + environment.systemPackages = (with pkgs.gnome3; removePackagesByName [ + baobab eog epiphany evince gucharmap nautilus totem yelp gnome-calculator + gnome-contacts gnome-font-viewer gnome-screenshot gnome-system-monitor simple-scan + gnome-terminal evolution file-roller gedit gnome-clocks gnome-music gnome-tweaks + pkgs.gnome-photos nautilus-sendto dconf-editor vinagre gnome-weather gnome-logs + gnome-maps gnome-characters gnome-calendar accerciser gnome-nettool gnome-packagekit + gnome-software gnome-power-manager gnome-todo pkgs.gnome-usage + ] config.environment.gnome3.excludePackages); + + # Enable default programs + programs.evince.enable = mkDefault true; + programs.file-roller.enable = mkDefault true; + programs.gnome-disks.enable = mkDefault true; + programs.gnome-documents.enable = mkDefault true; + programs.gnome-terminal.enable = mkDefault true; + services.gnome3.seahorse.enable = mkDefault true; + services.gnome3.sushi.enable = mkDefault true; + + # Let nautilus find extensions + # TODO: Create nautilus-with-extensions package + environment.variables.NAUTILUS_EXTENSION_DIR = "${config.system.path}/lib/nautilus/extensions-3.0"; + + # Override default mimeapps for nautilus + environment.variables.XDG_DATA_DIRS = [ "${mimeAppsList}/share" ]; + + environment.pathsToLink = [ + "/share/nautilus-python/extensions" + ]; + }) + + (mkIf serviceCfg.games.enable { + environment.systemPackages = (with pkgs.gnome3; removePackagesByName [ + aisleriot atomix five-or-more four-in-a-row gnome-chess gnome-klotski + gnome-mahjongg gnome-mines gnome-nibbles gnome-robots gnome-sudoku + gnome-taquin gnome-tetravex hitori iagno lightsoff quadrapassel + swell-foop tali + ] config.environment.gnome3.excludePackages); + }) + ]; } diff --git a/nixos/modules/services/x11/desktop-managers/lxqt.nix b/nixos/modules/services/x11/desktop-managers/lxqt.nix index 4368adedb34b3..bf53082b267d1 100644 --- a/nixos/modules/services/x11/desktop-managers/lxqt.nix +++ b/nixos/modules/services/x11/desktop-managers/lxqt.nix @@ -58,7 +58,8 @@ in # Link some extra directories in /run/current-system/software/share environment.pathsToLink = [ "/share" ]; - environment.variables.GIO_EXTRA_MODULES = [ "${pkgs.gvfs}/lib/gio/modules" ]; + services.gvfs.enable = true; + services.gvfs.package = pkgs.gvfs; services.upower.enable = config.powerManagement.enable; }; diff --git a/nixos/modules/services/x11/desktop-managers/mate.nix b/nixos/modules/services/x11/desktop-managers/mate.nix index eb06cb6bba233..6a2aa650c0b2e 100644 --- a/nixos/modules/services/x11/desktop-managers/mate.nix +++ b/nixos/modules/services/x11/desktop-managers/mate.nix @@ -94,17 +94,19 @@ in ]; programs.dconf.enable = true; + # Shell integration for VTE terminals + programs.bash.vteIntegration = mkDefault true; + programs.zsh.vteIntegration = mkDefault true; + services.gnome3.at-spi2-core.enable = true; services.gnome3.gnome-keyring.enable = true; services.gnome3.gnome-settings-daemon.enable = true; services.gnome3.gnome-settings-daemon.package = pkgs.mate.mate-settings-daemon; - services.gnome3.gvfs.enable = true; + services.gvfs.enable = true; services.upower.enable = config.powerManagement.enable; security.pam.services.mate-screensaver.unixAuth = true; - environment.variables.GIO_EXTRA_MODULES = [ "${pkgs.gnome3.gvfs}/lib/gio/modules" ]; - environment.pathsToLink = [ "/share" ]; }; diff --git a/nixos/modules/services/x11/desktop-managers/pantheon.nix b/nixos/modules/services/x11/desktop-managers/pantheon.nix index f0cafc377585d..ae23015d2005d 100644 --- a/nixos/modules/services/x11/desktop-managers/pantheon.nix +++ b/nixos/modules/services/x11/desktop-managers/pantheon.nix @@ -99,10 +99,6 @@ in fi '') cfg.sessionPath} - # Makes qt applications look less alien - export QT_QPA_PLATFORMTHEME=gtk3 - export QT_STYLE_OVERRIDE=adwaita - # Settings from elementary-default-settings export GTK_CSD=1 export GTK_MODULES=$GTK_MODULES:pantheon-filechooser-module @@ -129,7 +125,7 @@ in services.gnome3.gnome-keyring.enable = true; services.gnome3.gnome-settings-daemon.enable = true; services.gnome3.gnome-settings-daemon.package = pkgs.pantheon.elementary-settings-daemon; - services.gnome3.gvfs.enable = true; + services.gvfs.enable = true; services.gnome3.rygel.enable = mkDefault true; services.gsignond.enable = mkDefault true; services.gsignond.plugins = with pkgs.gsignondPlugins; [ lastfm mail oauth ]; @@ -146,9 +142,19 @@ in isSystem = true; }; + programs.dconf.enable = true; programs.evince.enable = mkDefault true; programs.file-roller.enable = mkDefault true; + # Shell integration for VTE terminals + programs.bash.vteIntegration = mkDefault true; + programs.zsh.vteIntegration = mkDefault true; + + # Harmonize Qt5 applications under Pantheon + qt5.enable = true; + qt5.platformTheme = "gnome"; + qt5.style = "adwaita"; + networking.networkmanager.enable = mkDefault true; networking.networkmanager.basePackages = { inherit (pkgs) networkmanager modemmanager wpa_supplicant crda; @@ -161,11 +167,6 @@ in environment.variables.GNOME_SESSION_DEBUG = optionalString cfg.debug "1"; - environment.variables.GIO_EXTRA_MODULES = [ - "${lib.getLib pkgs.gnome3.dconf}/lib/gio/modules" - "${pkgs.gnome3.gvfs}/lib/gio/modules" - ]; - environment.pathsToLink = [ # FIXME: modules should link subdirs of `/share` rather than relying on this "/share" @@ -187,7 +188,6 @@ in glib-networking gnome-menus gnome3.adwaita-icon-theme - gnome3.dconf gtk3.out hicolor-icon-theme lightlocker diff --git a/nixos/modules/services/x11/desktop-managers/xfce.nix b/nixos/modules/services/x11/desktop-managers/xfce.nix index 6852154378d7c..1102f73d1ac36 100644 --- a/nixos/modules/services/x11/desktop-managers/xfce.nix +++ b/nixos/modules/services/x11/desktop-managers/xfce.nix @@ -66,7 +66,6 @@ in exo garcon gtk-xfce-engine - gvfs libxfce4ui tumbler xfconf @@ -100,10 +99,6 @@ in "/share/gtksourceview-2.0" ]; - environment.variables = { - GIO_EXTRA_MODULES = [ "${pkgs.xfce.gvfs}/lib/gio/modules" ]; - }; - services.xserver.gdk-pixbuf.modulePackages = [ pkgs.librsvg ]; services.xserver.desktopManager.session = [{ @@ -128,5 +123,7 @@ in # Enable helpful DBus services. services.udisks2.enable = true; services.upower.enable = config.powerManagement.enable; + services.gvfs.enable = true; + services.gvfs.package = pkgs.xfce.gvfs; }; } diff --git a/nixos/modules/services/x11/xautolock.nix b/nixos/modules/services/x11/xautolock.nix index 1611d584d50eb..3e03131ca1145 100644 --- a/nixos/modules/services/x11/xautolock.nix +++ b/nixos/modules/services/x11/xautolock.nix @@ -129,7 +129,7 @@ in assertion = cfg.killer != null -> cfg.killtime >= 10; message = "killtime has to be at least 10 minutes according to `man xautolock`"; } - ] ++ (lib.flip map [ "locker" "notifier" "nowlocker" "killer" ] + ] ++ (lib.forEach [ "locker" "notifier" "nowlocker" "killer" ] (option: { assertion = cfg.${option} != null -> builtins.substring 0 1 cfg.${option} == "/"; diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix index 7ffe1c1256100..c94a064383156 100644 --- a/nixos/modules/services/x11/xserver.nix +++ b/nixos/modules/services/x11/xserver.nix @@ -78,7 +78,7 @@ let in imap1 mkHead cfg.xrandrHeads; xrandrDeviceSection = let - monitors = flip map xrandrHeads (h: '' + monitors = forEach xrandrHeads (h: '' Option "monitor-${h.config.output}" "${h.name}" ''); # First option is indented through the space in the config but any diff --git a/nixos/modules/system/boot/coredump.nix b/nixos/modules/system/boot/coredump.nix deleted file mode 100644 index 30f367da76663..0000000000000 --- a/nixos/modules/system/boot/coredump.nix +++ /dev/null @@ -1,66 +0,0 @@ -{ config, lib, pkgs, ... }: - -with lib; - -{ - - options = { - - systemd.coredump = { - - enable = mkOption { - default = false; - type = types.bool; - description = '' - Enables storing core dumps in systemd. - Note that this alone is not enough to enable core dumps. The maximum - file size for core dumps must be specified in limits.conf as well. See - <option>security.pam.loginLimits</option> and the limits.conf(5) - man page (these specify the core dump limits for user login sessions) - and <option>systemd.extraConfig</option> (where e.g. - <literal>DefaultLimitCORE=1000000</literal> can be specified to set - the core dump limit for systemd system-level services). - ''; - }; - - extraConfig = mkOption { - default = ""; - type = types.lines; - example = "Storage=journal"; - description = '' - Extra config options for systemd-coredump. See coredump.conf(5) man page - for available options. - ''; - }; - }; - - }; - - config = mkMerge [ - (mkIf config.systemd.coredump.enable { - - systemd.additionalUpstreamSystemUnits = [ "systemd-coredump.socket" "systemd-coredump@.service" ]; - - environment.etc."systemd/coredump.conf".text = - '' - [Coredump] - ${config.systemd.coredump.extraConfig} - ''; - - # Have the kernel pass core dumps to systemd's coredump helper binary. - # From systemd's 50-coredump.conf file. See: - # <https://github.com/systemd/systemd/blob/v218/sysctl.d/50-coredump.conf.in> - boot.kernel.sysctl."kernel.core_pattern" = "|${pkgs.systemd}/lib/systemd/systemd-coredump %P %u %g %s %t %c %e"; - }) - - (mkIf (!config.systemd.coredump.enable) { - boot.kernel.sysctl."kernel.core_pattern" = mkDefault "core"; - - systemd.extraConfig = - '' - DefaultLimitCORE=0:infinity - ''; - }) - ]; - -} diff --git a/nixos/modules/system/boot/kernel.nix b/nixos/modules/system/boot/kernel.nix index dd2e0f38fff5b..50dbf2f83651b 100644 --- a/nixos/modules/system/boot/kernel.nix +++ b/nixos/modules/system/boot/kernel.nix @@ -36,6 +36,7 @@ in boot.kernelPackages = mkOption { default = pkgs.linuxPackages; + type = types.unspecified // { merge = mergeEqualOption; }; apply = kernelPackages: kernelPackages.extend (self: super: { kernel = super.kernel.override { inherit randstructSeed; diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix index 4c85bd5db4a8b..4a68ae901dada 100644 --- a/nixos/modules/system/boot/loader/grub/grub.nix +++ b/nixos/modules/system/boot/loader/grub/grub.nix @@ -684,7 +684,7 @@ in assertion = if args.efiSysMountPoint == null then true else hasPrefix "/" args.efiSysMountPoint; message = "EFI paths must be absolute, not ${args.efiSysMountPoint}"; } - ] ++ flip map args.devices (device: { + ] ++ forEach args.devices (device: { assertion = device == "nodev" || hasPrefix "/" device; message = "GRUB devices must be absolute paths, not ${device} in ${args.path}"; })); diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix index d6b446e9ac227..f2060e21509c9 100644 --- a/nixos/modules/system/boot/networkd.nix +++ b/nixos/modules/system/boot/networkd.nix @@ -55,6 +55,27 @@ let (assertMacAddress "MACAddress") ]; + # NOTE The PrivateKey directive is missing on purpose here, please + # do not add it to this list. The nix store is world-readable let's + # refrain ourselves from providing a footgun. + checkWireGuard = checkUnitConfig "WireGuard" [ + (assertOnlyFields [ + "PrivateKeyFile" "ListenPort" "FwMark" + ]) + (assertRange "FwMark" 1 4294967295) + ]; + + # NOTE The PresharedKey directive is missing on purpose here, please + # do not add it to this list. The nix store is world-readable,let's + # refrain ourselves from providing a footgun. + checkWireGuardPeer = checkUnitConfig "WireGuardPeer" [ + (assertOnlyFields [ + "PublicKey" "PresharedKeyFile" "AllowedIPs" + "Endpoint" "PersistentKeepalive" + ]) + (assertRange "PersistentKeepalive" 1 65535) + ]; + checkVlan = checkUnitConfig "VLAN" [ (assertOnlyFields ["Id" "GVRP" "MVRP" "LooseBinding" "ReorderHeader"]) (assertRange "Id" 0 4094) @@ -320,6 +341,46 @@ let ''; }; + wireguardConfig = mkOption { + default = {}; + example = { + PrivateKeyFile = "/etc/wireguard/secret.key"; + ListenPort = 51820; + FwMark = 42; + }; + type = types.addCheck (types.attrsOf unitOption) checkWireGuard; + description = '' + Each attribute in this set specifies an option in the + <literal>[WireGuard]</literal> section of the unit. See + <citerefentry><refentrytitle>systemd.netdev</refentrytitle> + <manvolnum>5</manvolnum></citerefentry> for details. + Use <literal>PrivateKeyFile</literal> instead of + <literal>PrivateKey</literal>: the nix store is + world-readable. + ''; + }; + + wireguardPeers = mkOption { + default = []; + example = [ { wireguardPeerConfig={ + Endpoint = "192.168.1.1:51820"; + PublicKey = "27s0OvaBBdHoJYkH9osZpjpgSOVNw+RaKfboT/Sfq0g="; + PresharedKeyFile = "/etc/wireguard/psk.key"; + AllowedIPs = [ "10.0.0.1/32" ]; + PersistentKeepalive = 15; + };}]; + type = with types; listOf (submodule wireguardPeerOptions); + description = '' + Each item in this array specifies an option in the + <literal>[WireGuardPeer]</literal> section of the unit. See + <citerefentry><refentrytitle>systemd.netdev</refentrytitle> + <manvolnum>5</manvolnum></citerefentry> for details. + Use <literal>PresharedKeyFile</literal> instead of + <literal>PresharedKey</literal>: the nix store is + world-readable. + ''; + }; + vlanConfig = mkOption { default = {}; example = { Id = "4"; }; @@ -450,6 +511,23 @@ let }; }; + wireguardPeerOptions = { + options = { + wireguardPeerConfig = mkOption { + default = {}; + example = { }; + type = types.addCheck (types.attrsOf unitOption) checkWireGuardPeer; + description = '' + Each attribute in this set specifies an option in the + <literal>[WireGuardPeer]</literal> section of the unit. See + <citerefentry><refentrytitle>systemd.network</refentrytitle> + <manvolnum>5</manvolnum></citerefentry> for details. + ''; + }; + }; + }; + + networkOptions = commonNetworkOptions // { networkConfig = mkOption { @@ -732,6 +810,16 @@ let ${attrsToSection def.bondConfig} ''} + ${optionalString (def.wireguardConfig != { }) '' + [WireGuard] + ${attrsToSection def.wireguardConfig} + + ''} + ${flip concatMapStrings def.wireguardPeers (x: '' + [WireGuardPeer] + ${attrsToSection x.wireguardPeerConfig} + + '')} ${def.extraConfig} ''; }; diff --git a/nixos/modules/system/boot/stage-1-init.sh b/nixos/modules/system/boot/stage-1-init.sh index 67cbe720ddc3f..b817a45deba35 100644 --- a/nixos/modules/system/boot/stage-1-init.sh +++ b/nixos/modules/system/boot/stage-1-init.sh @@ -44,13 +44,13 @@ EOF *) to ignore the error and continue EOF - read reply + read -n 1 reply if [ -n "$allowShell" -a "$reply" = f ]; then exec setsid @shell@ -c "exec @shell@ < /dev/$console >/dev/$console 2>/dev/$console" elif [ -n "$allowShell" -a "$reply" = i ]; then echo "Starting interactive shell..." - setsid @shell@ -c "@shell@ < /dev/$console >/dev/$console 2>/dev/$console" || fail + setsid @shell@ -c "exec @shell@ < /dev/$console >/dev/$console 2>/dev/$console" || fail elif [ "$reply" = r ]; then echo "Rebooting..." reboot -f diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix index 413e32de7b57b..f9f86b5c87bad 100644 --- a/nixos/modules/system/boot/systemd.nix +++ b/nixos/modules/system/boot/systemd.nix @@ -76,6 +76,10 @@ let "systemd-journald-dev-log.socket" "syslog.socket" + # Coredumps. + "systemd-coredump.socket" + "systemd-coredump@.service" + # SysV init compatibility. "systemd-initctl.socket" "systemd-initctl.service" @@ -533,13 +537,23 @@ in }; systemd.enableCgroupAccounting = mkOption { - default = false; + default = true; type = types.bool; description = '' Whether to enable cgroup accounting. ''; }; + systemd.coredump.extraConfig = mkOption { + default = ""; + type = types.lines; + example = "Storage=journal"; + description = '' + Extra config options for systemd-coredump. See coredump.conf(5) man page + for available options. + ''; + }; + systemd.extraConfig = mkOption { default = ""; type = types.lines; @@ -790,11 +804,12 @@ in [Manager] ${optionalString config.systemd.enableCgroupAccounting '' DefaultCPUAccounting=yes + DefaultBlockIOAccounting=yes DefaultIOAccounting=yes DefaultBlockIOAccounting=yes - DefaultMemoryAccounting=yes - DefaultTasksAccounting=yes + DefaultIPAccounting=yes ''} + DefaultLimitCORE=infinity ${config.systemd.extraConfig} ''; @@ -818,6 +833,12 @@ in ${config.services.journald.extraConfig} ''; + "systemd/coredump.conf".text = + '' + [Coredump] + ${config.systemd.coredump.extraConfig} + ''; + "systemd/logind.conf".text = '' [Login] KillUserProcesses=${if config.services.logind.killUserProcesses then "yes" else "no"} @@ -831,6 +852,10 @@ in [Sleep] ''; + # install provided sysctl snippets + "sysctl.d/50-coredump.conf".source = "${systemd}/example/sysctl.d/50-coredump.conf"; + "sysctl.d/50-default.conf".source = "${systemd}/example/sysctl.d/50-default.conf"; + "tmpfiles.d/systemd.conf".source = "${systemd}/example/tmpfiles.d/systemd.conf"; "tmpfiles.d/x11.conf".source = "${systemd}/example/tmpfiles.d/x11.conf"; diff --git a/nixos/modules/tasks/network-interfaces-systemd.nix b/nixos/modules/tasks/network-interfaces-systemd.nix index b40ea26554ad9..f5a593211efca 100644 --- a/nixos/modules/tasks/network-interfaces-systemd.nix +++ b/nixos/modules/tasks/network-interfaces-systemd.nix @@ -74,7 +74,7 @@ in enable = true; networks."99-main" = genericNetwork mkDefault; } - (mkMerge (flip map interfaces (i: { + (mkMerge (forEach interfaces (i: { netdevs = mkIf i.virtual ({ "40-${i.name}" = { netdevConfig = { @@ -90,7 +90,7 @@ in name = mkDefault i.name; DHCP = mkForce (dhcpStr (if i.useDHCP != null then i.useDHCP else cfg.useDHCP && interfaceIps i == [ ])); - address = flip map (interfaceIps i) + address = forEach (interfaceIps i) (ip: "${ip.address}/${toString ip.prefixLength}"); networkConfig.IPv6PrivacyExtensions = "kernel"; } ]; @@ -102,7 +102,7 @@ in Kind = "bridge"; }; }; - networks = listToAttrs (flip map bridge.interfaces (bi: + networks = listToAttrs (forEach bridge.interfaces (bi: nameValuePair "40-${bi}" (mkMerge [ (genericNetwork (mkOverride 999)) { DHCP = mkOverride 0 (dhcpStr false); networkConfig.Bridge = name; @@ -173,7 +173,7 @@ in }; - networks = listToAttrs (flip map bond.interfaces (bi: + networks = listToAttrs (forEach bond.interfaces (bi: nameValuePair "40-${bi}" (mkMerge [ (genericNetwork (mkOverride 999)) { DHCP = mkOverride 0 (dhcpStr false); networkConfig.Bond = name; diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix index d330ee123037b..046c61c8b5652 100644 --- a/nixos/modules/tasks/network-interfaces.nix +++ b/nixos/modules/tasks/network-interfaces.nix @@ -926,7 +926,7 @@ in warnings = concatMap (i: i.warnings) interfaces; assertions = - (flip map interfaces (i: { + (forEach interfaces (i: { # With the linux kernel, interface name length is limited by IFNAMSIZ # to 16 bytes, including the trailing null byte. # See include/linux/if.h in the kernel sources @@ -934,12 +934,12 @@ in message = '' The name of networking.interfaces."${i.name}" is too long, it needs to be less than 16 characters. ''; - })) ++ (flip map slaveIfs (i: { + })) ++ (forEach slaveIfs (i: { assertion = i.ipv4.addresses == [ ] && i.ipv6.addresses == [ ]; message = '' The networking.interfaces."${i.name}" must not have any defined ips when it is a slave. ''; - })) ++ (flip map interfaces (i: { + })) ++ (forEach interfaces (i: { assertion = i.preferTempAddress -> cfg.enableIPv6; message = '' Temporary addresses are only needed when IPv6 is enabled. @@ -967,8 +967,8 @@ in "net.ipv6.conf.default.disable_ipv6" = mkDefault (!cfg.enableIPv6); "net.ipv6.conf.all.forwarding" = mkDefault (any (i: i.proxyARP) interfaces); } // listToAttrs (flip concatMap (filter (i: i.proxyARP) interfaces) - (i: flip map [ "4" "6" ] (v: nameValuePair "net.ipv${v}.conf.${i.name}.proxy_arp" true))) - // listToAttrs (flip map (filter (i: i.preferTempAddress) interfaces) + (i: forEach [ "4" "6" ] (v: nameValuePair "net.ipv${v}.conf.${i.name}.proxy_arp" true))) + // listToAttrs (forEach (filter (i: i.preferTempAddress) interfaces) (i: nameValuePair "net.ipv6.conf.${i.name}.use_tempaddr" 2)); # Capabilities won't work unless we have at-least a 4.3 Linux @@ -1050,7 +1050,7 @@ in ${cfg.localCommands} ''; }; - } // (listToAttrs (flip map interfaces (i: + } // (listToAttrs (forEach interfaces (i: let deviceDependency = if (config.boot.isContainer || i.name == "lo") then [] diff --git a/nixos/modules/virtualisation/containers.nix b/nixos/modules/virtualisation/containers.nix index 948b745212eda..9fe577bd83ede 100644 --- a/nixos/modules/virtualisation/containers.nix +++ b/nixos/modules/virtualisation/containers.nix @@ -138,7 +138,7 @@ let --bind-ro=/nix/var/nix/daemon-socket \ --bind="/nix/var/nix/profiles/per-container/$INSTANCE:/nix/var/nix/profiles" \ --bind="/nix/var/nix/gcroots/per-container/$INSTANCE:/nix/var/nix/gcroots" \ - --link-journal=try-guest \ + ${optionalString (!cfg.ephemeral) "--link-journal=try-guest"} \ --setenv PRIVATE_NETWORK="$PRIVATE_NETWORK" \ --setenv HOST_BRIDGE="$HOST_BRIDGE" \ --setenv HOST_ADDRESS="$HOST_ADDRESS" \ @@ -147,6 +147,7 @@ let --setenv LOCAL_ADDRESS6="$LOCAL_ADDRESS6" \ --setenv HOST_PORT="$HOST_PORT" \ --setenv PATH="$PATH" \ + ${optionalString cfg.ephemeral "--ephemeral"} \ ${if cfg.additionalCapabilities != null && cfg.additionalCapabilities != [] then ''--capability="${concatStringsSep " " cfg.additionalCapabilities}"'' else "" } \ @@ -247,6 +248,8 @@ let Type = "notify"; + RuntimeDirectory = lib.optional cfg.ephemeral "containers/%i"; + # Note that on reboot, systemd-nspawn returns 133, so this # unit will be restarted. On poweroff, it returns 0, so the # unit won't be restarted. @@ -419,6 +422,7 @@ let { extraVeths = {}; additionalCapabilities = []; + ephemeral = false; allowedDevices = []; hostAddress = null; hostAddress6 = null; @@ -511,6 +515,26 @@ in information. ''; }; + + ephemeral = mkOption { + type = types.bool; + default = false; + description = '' + Runs container in ephemeral mode with the empty root filesystem at boot. + This way container will be bootstrapped from scratch on each boot + and will be cleaned up on shutdown leaving no traces behind. + Useful for completely stateless, reproducible containers. + + Note that this option might require to do some adjustments to the container configuration, + e.g. you might want to set + <varname>systemd.network.networks.$interface.dhcpConfig.ClientIdentifier</varname> to "mac" + if you use <varname>macvlans</varname> option. + This way dhcp client identifier will be stable between the container restarts. + + Note that the container journal will not be linked to the host if this option is enabled. + ''; + }; + enableTun = mkOption { type = types.bool; default = false; @@ -659,12 +683,14 @@ in unit = { description = "Container '%i'"; - unitConfig.RequiresMountsFor = [ "/var/lib/containers/%i" ]; + unitConfig.RequiresMountsFor = "/var/lib/containers/%i"; path = [ pkgs.iproute ]; - environment.INSTANCE = "%i"; - environment.root = "/var/lib/containers/%i"; + environment = { + root = "/var/lib/containers/%i"; + INSTANCE = "%i"; + }; preStart = preStartScript dummyConfig; @@ -703,11 +729,13 @@ in } else {}); in - unit // { + recursiveUpdate unit { preStart = preStartScript containerConfig; script = startScript containerConfig; postStart = postStartScript containerConfig; serviceConfig = serviceDirectives containerConfig; + unitConfig.RequiresMountsFor = lib.optional (!containerConfig.ephemeral) "/var/lib/containers/%i"; + environment.root = if containerConfig.ephemeral then "/run/containers/%i" else "/var/lib/containers/%i"; } // ( if containerConfig.autoStart then { diff --git a/nixos/modules/virtualisation/google-compute-config.nix b/nixos/modules/virtualisation/google-compute-config.nix index 5c59188b68b2c..79766970c757a 100644 --- a/nixos/modules/virtualisation/google-compute-config.nix +++ b/nixos/modules/virtualisation/google-compute-config.nix @@ -159,12 +159,6 @@ in # functionality/features (e.g. TCP Window scaling). "net.ipv4.tcp_syncookies" = mkDefault "1"; - # ignores source-routed packets - "net.ipv4.conf.all.accept_source_route" = mkDefault "0"; - - # ignores source-routed packets - "net.ipv4.conf.default.accept_source_route" = mkDefault "0"; - # ignores ICMP redirects "net.ipv4.conf.all.accept_redirects" = mkDefault "0"; @@ -186,10 +180,10 @@ in # don't allow traffic between networks or act as a router "net.ipv4.conf.default.send_redirects" = mkDefault "0"; - # reverse path filtering - IP spoofing protection + # strict reverse path filtering - IP spoofing protection "net.ipv4.conf.all.rp_filter" = mkDefault "1"; - # reverse path filtering - IP spoofing protection + # strict path filtering - IP spoofing protection "net.ipv4.conf.default.rp_filter" = mkDefault "1"; # ignores ICMP broadcasts to avoid participating in Smurf attacks diff --git a/nixos/modules/virtualisation/libvirtd.nix b/nixos/modules/virtualisation/libvirtd.nix index 394b4ce56563a..16b79d8691936 100644 --- a/nixos/modules/virtualisation/libvirtd.nix +++ b/nixos/modules/virtualisation/libvirtd.nix @@ -104,6 +104,18 @@ in { ''; }; + onBoot = mkOption { + type = types.enum ["start" "ignore" ]; + default = "start"; + description = '' + Specifies the action to be done to / on the guests when the host boots. + The "start" option starts all guests that were running prior to shutdown + regardless of their autostart settings. The "ignore" option will not + start the formally running guest on boot. However, any guest marked as + autostart will still be automatically started by libvirtd. + ''; + }; + onShutdown = mkOption { type = types.enum ["shutdown" "suspend" ]; default = "suspend"; @@ -221,6 +233,7 @@ in { path = with pkgs; [ coreutils libvirt gawk ]; restartIfChanged = false; + environment.ON_BOOT = "${cfg.onBoot}"; environment.ON_SHUTDOWN = "${cfg.onShutdown}"; }; |