diff options
Diffstat (limited to 'nixos')
52 files changed, 1528 insertions, 801 deletions
diff --git a/nixos/doc/manual/development/releases.xml b/nixos/doc/manual/development/releases.xml index 3cb16d33cd48..1cdec64f69b0 100755 --- a/nixos/doc/manual/development/releases.xml +++ b/nixos/doc/manual/development/releases.xml @@ -220,6 +220,30 @@ </itemizedlist> </section> </section> + <section xml:id="release-managers"> + <title>Release Management Team</title> + <para> + For each release there are two release managers. After each release the + release manager having managed two releases steps down and the release + management team of the last release appoints a new release manager. + </para> + <para> + This makes sure a release management team always consists of one release + manager who already has managed one release and one release manager being + introduced to their role, making it easier to pass on knowledge and + experience. + </para> + <para> + A release manager's role and responsibilities are: + </para> + <itemizedlist> + <listitem><para>manage the release process</para></listitem> + <listitem><para>start discussions about features and changes for a given release</para></listitem> + <listitem><para>create a roadmap</para></listitem> + <listitem><para>release in cooperation with Eelco Dolstra</para></listitem> + <listitem><para>decide which bug fixes, features, etc... get backported after a release</para></listitem> + </itemizedlist> + </section> <section xml:id="release-schedule"> <title>Release schedule</title> diff --git a/nixos/doc/manual/release-notes/rl-1909.xml b/nixos/doc/manual/release-notes/rl-1909.xml index 7d2d98ddfee1..6493bb995967 100644 --- a/nixos/doc/manual/release-notes/rl-1909.xml +++ b/nixos/doc/manual/release-notes/rl-1909.xml @@ -237,6 +237,12 @@ </para> </listitem> <listitem> + <para> + The <literal>shibboleth-sp</literal> package has been updated to version 3. + It is largely backward compatible, for further information refer to the + <link xlink:href="https://wiki.shibboleth.net/confluence/display/SP3/ReleaseNotes">release notes</link> + and <link xlink:href="https://wiki.shibboleth.net/confluence/display/SP3/UpgradingFromV2">upgrade guide</link>. + </para> <para> Nodejs 8 is scheduled EOL under the lifetime of 19.09 and has been dropped. </para> @@ -273,6 +279,18 @@ The <option>services.mantisbt</option> module has been removed from nixpkgs due to lack of maintainer. </para> </listitem> + <listitem> + <para> + Squid 3 has been removed and the <option>squid</option> derivation now refers to Squid 4. + </para> + </listitem> + <listitem> + <para> + The <option>services.pdns-recursor.extraConfig</option> option has been replaced by + <option>services.pdns-recursor.settings</option>. The new option allows setting extra + configuration while being better type-checked and mergeable. + </para> + </listitem> </itemizedlist> </section> @@ -495,6 +513,20 @@ been removed. </para> </listitem> + <listitem> + <para> + The <literal>rmilter</literal> package was removed with associated module and options due deprecation by upstream developer. + Use <literal>rspamd</literal> in proxy mode instead. + </para> + </listitem> + <listitem> + <para> + systemd cgroup accounting via the + <link linkend="opt-systemd.enableCgroupAccounting">systemd.enableCgroupAccounting</link> + option is now enabled by default. It now also enables the more recent Block IO and IP accounting + features. + </para> + </listitem> </itemizedlist> </section> </section> diff --git a/nixos/modules/config/update-users-groups.pl b/nixos/modules/config/update-users-groups.pl index ef5e6346f02e..59cea51c611b 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 index 9024ceddaee8..d4a8c926fef2 100644 --- a/nixos/modules/config/vte.nix +++ b/nixos/modules/config/vte.nix @@ -42,7 +42,7 @@ in config = mkMerge [ (mkIf config.programs.bash.vteIntegration { - programs.bash.interactiveShellInit = vteInitSnippet; + programs.bash.interactiveShellInit = mkBefore vteInitSnippet; }) (mkIf config.programs.zsh.vteIntegration { diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index 1047df95cdf5..efd8544d6a21 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 5335ba3abd18..6331e76c648f 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -387,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 @@ -609,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 @@ -648,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 @@ -788,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 @@ -801,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 diff --git a/nixos/modules/programs/environment.nix b/nixos/modules/programs/environment.nix index 4d762314298d..66eb83482664 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/gnupg.nix b/nixos/modules/programs/gnupg.nix index 9618d61a1f5b..bcbc994efe9b 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 3cbfd8fa4d32..6e9eefd74d18 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 && setopt prompt_sp - fi + autoload -U promptinit && promptinit && prompt walters && setopt prompt_sp ''; description = '' Shell script code used to initialise the zsh prompt. @@ -213,6 +211,14 @@ in ${cfg.promptInit} + # Need to disable features to support TRAMP + if [ "$TERM" = dumb ]; then + unsetopt zle prompt_cr prompt_subst + 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 e32fa6fded4a..348ad094e5ad 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" ]) diff --git a/nixos/modules/services/databases/memcached.nix b/nixos/modules/services/databases/memcached.nix index f9e403dfc0c2..84d2c8674f4e 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 4286251357f7..748a025414a7 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-user-share.nix b/nixos/modules/services/desktops/gnome3/gnome-user-share.nix index 1f6ce2ae968e..f83962877700 100644 --- a/nixos/modules/services/desktops/gnome3/gnome-user-share.nix +++ b/nixos/modules/services/desktops/gnome3/gnome-user-share.nix @@ -12,14 +12,7 @@ with lib; services.gnome3.gnome-user-share = { - enable = mkOption { - type = types.bool; - default = false; - description = '' - Whether to enable GNOME User Share, a service that exports the - contents of the Public folder in your home directory on the local network. - ''; - }; + enable = mkEnableOption "GNOME User Share, a user-level file sharing service for GNOME"; }; @@ -30,12 +23,13 @@ with lib; config = mkIf config.services.gnome3.gnome-user-share.enable { - environment.systemPackages = [ pkgs.gnome3.gnome-user-share ]; + environment.systemPackages = [ + pkgs.gnome3.gnome-user-share + ]; - services.xserver.displayManager.sessionCommands = with pkgs.gnome3; '' - # Don't let gnome-control-center depend upon gnome-user-share - export XDG_DATA_DIRS=$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}${gnome-user-share}/share/gsettings-schemas/${gnome-user-share.name} - ''; + systemd.packages = [ + pkgs.gnome3.gnome-user-share + ]; }; diff --git a/nixos/modules/services/desktops/gnome3/tracker-miners.nix b/nixos/modules/services/desktops/gnome3/tracker-miners.nix index 20154fc2fed3..b390d8368c65 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 c061f7890499..2e8292742264 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/hardware/trezord.nix b/nixos/modules/services/hardware/trezord.nix index 20bcbf83109e..62824ed7350a 100644 --- a/nixos/modules/services/hardware/trezord.nix +++ b/nixos/modules/services/hardware/trezord.nix @@ -22,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. + ''; + }; }; }; @@ -50,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/mail/rmilter.nix b/nixos/modules/services/mail/rmilter.nix deleted file mode 100644 index 466365b6b305..000000000000 --- 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 e8b2e11bf726..bdedfa1bb701 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/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix index 6bc88c66dc19..088dfd71860b 100644 --- a/nixos/modules/services/misc/nix-daemon.nix +++ b/nixos/modules/services/misc/nix-daemon.nix @@ -8,7 +8,9 @@ let nix = cfg.package.out; - isNix20 = versionAtLeast (getVersion nix) "2.0pre"; + nixVersion = getVersion nix; + + isNix20 = versionAtLeast nixVersion "2.0pre"; makeNixBuildUser = nr: { name = "nixbld${toString nr}"; @@ -61,6 +63,9 @@ let builders = ''} system-features = ${toString cfg.systemFeatures} + ${optionalString (versionAtLeast nixVersion "2.3pre") '' + sandbox-fallback = false + ''} $extraOptions END '' + optionalString cfg.checkConfig ( diff --git a/nixos/modules/services/misc/zoneminder.nix b/nixos/modules/services/misc/zoneminder.nix index cf56ae89b399..bf38b9ad7a2d 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/networking/dnschain.nix b/nixos/modules/services/networking/dnschain.nix index 0c2add424bac..5b58ea9b0c91 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/jormungandr.nix b/nixos/modules/services/networking/jormungandr.nix new file mode 100644 index 000000000000..0c66b85fe8a5 --- /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 000000000000..40ef9433de0f --- /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 d07deb9dcc67..ec69cc838da9 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,17 +119,55 @@ 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 { + 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; @@ -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/unifi.nix b/nixos/modules/services/networking/unifi.nix index 6239c88b7e41..c922ba15960f 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/security/usbguard.nix b/nixos/modules/services/security/usbguard.nix index 88d2f69db572..20d5e3b28eb9 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 f544928fb6b1..a94a471361ef 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 6740131dccde..95c8fb160510 100644 --- a/nixos/modules/services/web-apps/icingaweb2/icingaweb2.nix +++ b/nixos/modules/services/web-apps/icingaweb2/icingaweb2.nix @@ -1,7 +1,7 @@ { 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 = { @@ -164,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 = { @@ -208,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 84a94fc446e5..2797feb32ebf 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 14aca45a342b..d9f840408cc8 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 5bd5977e592b..ec2568bf952d 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 000000000000..f2516c67c6b3 --- /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 a0214a75d93e..ada14ad39291 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 b200a89260ac..6a1b4143bc16 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 @@ -180,7 +180,7 @@ in services.phpfpm.pools = { "${poolName}" = { - listen = phpfpmSocketName; + inherit (cfg) user group; phpOptions = '' date.timezone = "CET" @@ -191,20 +191,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 +239,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 cd0f743a5fb8..56b7cafffe8b 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"; @@ -116,21 +115,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 1bd9de93735d..59b0ee1addc6 100644 --- a/nixos/modules/services/web-apps/tt-rss.nix +++ b/nixos/modules/services/web-apps/tt-rss.nix @@ -521,20 +521,19 @@ 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 - ''; + 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 624b0089a037..98dc84588189 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 4b5334579a99..fa358ffafbc3 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/darkhttpd.nix b/nixos/modules/services/web-servers/darkhttpd.nix new file mode 100644 index 000000000000..80870118c334 --- /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/phpfpm/default.nix b/nixos/modules/services/web-servers/phpfpm/default.nix index ffafbc5e92f2..e95e71e0d997 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 d9ad7eff71f2..000000000000 --- 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 6434731d951f..0caa93ad217f 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,138 +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-user-share.enable = mkDefault true; - services.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.dconf.enable = true; - 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; - - # 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.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/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix index 23a2dd45d492..2a0360b12cbc 100644 --- a/nixos/modules/system/boot/systemd.nix +++ b/nixos/modules/system/boot/systemd.nix @@ -537,7 +537,7 @@ in }; systemd.enableCgroupAccounting = mkOption { - default = false; + default = true; type = types.bool; description = '' Whether to enable cgroup accounting. @@ -804,10 +804,10 @@ 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} diff --git a/nixos/modules/virtualisation/libvirtd.nix b/nixos/modules/virtualisation/libvirtd.nix index 394b4ce56563..16b79d869193 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}"; }; diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 47eaec7c7838..557ee78df7c6 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -97,6 +97,7 @@ in glusterfs = handleTest ./glusterfs.nix {}; gnome3-xorg = handleTest ./gnome3-xorg.nix {}; gnome3 = handleTest ./gnome3.nix {}; + gnome-photos = handleTest ./gnome-photos.nix {}; gocd-agent = handleTest ./gocd-agent.nix {}; gocd-server = handleTest ./gocd-server.nix {}; google-oslogin = handleTest ./google-oslogin {}; @@ -127,6 +128,7 @@ in jackett = handleTest ./jackett.nix {}; jellyfin = handleTest ./jellyfin.nix {}; jenkins = handleTest ./jenkins.nix {}; + jormungandr = handleTest ./jormungandr.nix {}; kafka = handleTest ./kafka.nix {}; kerberos = handleTest ./kerberos/default.nix {}; kernel-latest = handleTest ./kernel-latest.nix {}; @@ -141,6 +143,7 @@ in latestKernel.login = handleTest ./login.nix { latestKernel = true; }; ldap = handleTest ./ldap.nix {}; leaps = handleTest ./leaps.nix {}; + libxmlb = handleTest ./libxmlb.nix {}; lidarr = handleTest ./lidarr.nix {}; lightdm = handleTest ./lightdm.nix {}; limesurvey = handleTest ./limesurvey.nix {}; @@ -158,6 +161,7 @@ in minio = handleTest ./minio.nix {}; misc = handleTest ./misc.nix {}; mongodb = handleTest ./mongodb.nix {}; + moodle = handleTest ./moodle.nix {}; morty = handleTest ./morty.nix {}; mosquitto = handleTest ./mosquitto.nix {}; mpd = handleTest ./mpd.nix {}; @@ -262,6 +266,7 @@ in tinydns = handleTest ./tinydns.nix {}; tor = handleTest ./tor.nix {}; transmission = handleTest ./transmission.nix {}; + trezord = handleTest ./trezord.nix {}; udisks2 = handleTest ./udisks2.nix {}; upnp = handleTest ./upnp.nix {}; uwsgi = handleTest ./uwsgi.nix {}; diff --git a/nixos/tests/gnome-photos.nix b/nixos/tests/gnome-photos.nix new file mode 100644 index 000000000000..2ecda1d68ce3 --- /dev/null +++ b/nixos/tests/gnome-photos.nix @@ -0,0 +1,42 @@ +# run installed tests +import ./make-test.nix ({ pkgs, lib, ... }: + +let + + # gsettings tool with access to gsettings-desktop-schemas + desktop-gsettings = with pkgs; stdenv.mkDerivation { + name = "desktop-gsettings"; + dontUnpack = true; + nativeBuildInputs = [ glib wrapGAppsHook ]; + buildInputs = [ gsettings-desktop-schemas ]; + installPhase = '' + runHook preInstall + mkdir -p $out/bin + ln -s ${glib.bin}/bin/gsettings $out/bin/desktop-gsettings + runHook postInstall + ''; + }; + +in + +{ + name = "gnome-photos"; + meta = { + maintainers = pkgs.gnome-photos.meta.maintainers; + }; + + machine = { pkgs, ... }: { + imports = [ ./common/x11.nix ]; + programs.dconf.enable = true; + services.gnome3.at-spi2-core.enable = true; # needed for dogtail + environment.systemPackages = with pkgs; [ gnome-desktop-testing desktop-gsettings ]; + services.dbus.packages = with pkgs; [ gnome-photos ]; + }; + + testScript = '' + $machine->waitForX; + # dogtail needs accessibility enabled + $machine->succeed("desktop-gsettings set org.gnome.desktop.interface toolkit-accessibility true 2>&1"); + $machine->succeed("gnome-desktop-testing-runner -d '${pkgs.gnome-photos.installedTests}/share' 2>&1"); + ''; +}) diff --git a/nixos/tests/jormungandr.nix b/nixos/tests/jormungandr.nix new file mode 100644 index 000000000000..2abafc53ce51 --- /dev/null +++ b/nixos/tests/jormungandr.nix @@ -0,0 +1,77 @@ +import ./make-test.nix ({ pkgs, ... }: { + name = "jormungandr"; + meta = with pkgs.stdenv.lib.maintainers; { + maintainers = [ mmahut ]; + }; + + nodes = { + # Testing the Byzantine Fault Tolerant protocol + bft = { ... }: { + environment.systemPackages = [ pkgs.jormungandr ]; + services.jormungandr.enable = true; + services.jormungandr.genesisBlockFile = "/var/lib/jormungandr/block-0.bin"; + services.jormungandr.secretFile = "/etc/secrets/jormungandr.yaml"; + }; + + # Testing the Ouroboros Genesis Praos protocol + genesis = { ... }: { + environment.systemPackages = [ pkgs.jormungandr ]; + services.jormungandr.enable = true; + services.jormungandr.genesisBlockFile = "/var/lib/jormungandr/block-0.bin"; + services.jormungandr.secretFile = "/etc/secrets/jormungandr.yaml"; + }; + }; + + testScript = '' + startAll; + + ## Testing BFT + # Let's wait for the StateDirectory + $bft->waitForFile("/var/lib/jormungandr/"); + + # First, we generate the genesis file for our new blockchain + $bft->succeed("jcli genesis init > /root/genesis.yaml"); + + # We need to generate our secret key + $bft->succeed("jcli key generate --type=Ed25519 > /root/key.prv"); + + # We include the secret key into our services.jormungandr.secretFile + $bft->succeed("mkdir -p /etc/secrets"); + $bft->succeed("echo -e \"bft:\\n signing_key:\" \$(cat /root/key.prv) > /etc/secrets/jormungandr.yaml"); + + # After that, we generate our public key from it + $bft->succeed("cat /root/key.prv | jcli key to-public > /root/key.pub"); + + # We add our public key as a consensus leader in the genesis configration file + $bft->succeed("sed -ie \"s/ed25519_pk1vvwp2s0n5jl5f4xcjurp2e92sj2awehkrydrlas4vgqr7xzt33jsadha32/\$(cat /root/key.pub)/\" /root/genesis.yaml"); + + # Now we can generate the genesis block from it + $bft->succeed("jcli genesis encode --input /root/genesis.yaml --output /var/lib/jormungandr/block-0.bin"); + + # We should have everything to start the service now + $bft->succeed("systemctl restart jormungandr"); + $bft->waitForUnit("jormungandr.service"); + + # Now we can test if we are able to reach the REST API + $bft->waitUntilSucceeds("curl -L http://localhost:8607/api/v0/node/stats | grep uptime"); + + ## Testing Genesis + # Let's wait for the StateDirectory + $genesis->waitForFile("/var/lib/jormungandr/"); + + # Bootstraping the configuration + $genesis->succeed("jormungandr-bootstrap -g -p 8607 -s 1"); + + # Moving generated files in place + $genesis->succeed("mkdir -p /etc/secrets"); + $genesis->succeed("mv pool-secret1.yaml /etc/secrets/jormungandr.yaml"); + $genesis->succeed("mv block-0.bin /var/lib/jormungandr/"); + + # We should have everything to start the service now + $genesis->succeed("systemctl restart jormungandr"); + $genesis->waitForUnit("jormungandr.service"); + + # Now we can create and delegate an account + $genesis->succeed("./create-account-and-delegate.sh | tee -a /tmp/delegate.log"); + ''; +}) diff --git a/nixos/tests/libxmlb.nix b/nixos/tests/libxmlb.nix new file mode 100644 index 000000000000..3bee568ac5a2 --- /dev/null +++ b/nixos/tests/libxmlb.nix @@ -0,0 +1,17 @@ +# run installed tests +import ./make-test.nix ({ pkgs, ... }: + +{ + name = "libxmlb"; + meta = { + maintainers = pkgs.libxmlb.meta.maintainers; + }; + + machine = { pkgs, ... }: { + environment.systemPackages = with pkgs; [ gnome-desktop-testing ]; + }; + + testScript = '' + $machine->succeed("gnome-desktop-testing-runner -d '${pkgs.libxmlb.installedTests}/share'"); + ''; +}) diff --git a/nixos/tests/moodle.nix b/nixos/tests/moodle.nix new file mode 100644 index 000000000000..565a6b636949 --- /dev/null +++ b/nixos/tests/moodle.nix @@ -0,0 +1,22 @@ +import ./make-test.nix ({ pkgs, lib, ... }: { + name = "moodle"; + meta.maintainers = [ lib.maintainers.aanderse ]; + + machine = + { ... }: + { services.moodle.enable = true; + services.moodle.virtualHost.hostName = "localhost"; + services.moodle.virtualHost.adminAddr = "root@example.com"; + services.moodle.initialPassword = "correcthorsebatterystaple"; + + # Ensure the virtual machine has enough memory to avoid errors like: + # Fatal error: Out of memory (allocated 152047616) (tried to allocate 33554440 bytes) + virtualisation.memorySize = 2000; + }; + + testScript = '' + startAll; + $machine->waitForUnit('phpfpm-moodle.service'); + $machine->succeed('curl http://localhost/') =~ /You are not logged in/ or die; + ''; +}) diff --git a/nixos/tests/systemd.nix b/nixos/tests/systemd.nix index 3168c026d514..1c201e3b5dcc 100644 --- a/nixos/tests/systemd.nix +++ b/nixos/tests/systemd.nix @@ -89,5 +89,12 @@ import ./make-test.nix ({ pkgs, ... }: { $machine->waitForUnit('multi-user.target'); $machine->succeed('sysctl net.core.default_qdisc | grep -q "fq_codel"'); }; + + # Test cgroup accounting is enabled + subtest "systemd cgroup accounting is enabled", sub { + $machine->waitForUnit('multi-user.target'); + $machine->succeed('systemctl show testservice1.service -p IOAccounting | grep -q "yes"'); + $machine->succeed('systemctl status testservice1.service | grep -q "CPU:"'); + }; ''; }) diff --git a/nixos/tests/trezord.nix b/nixos/tests/trezord.nix new file mode 100644 index 000000000000..1c85bf539345 --- /dev/null +++ b/nixos/tests/trezord.nix @@ -0,0 +1,20 @@ +import ./make-test.nix ({ pkgs, ... }: { + name = "trezord"; + meta = with pkgs.stdenv.lib.maintainers; { + maintainers = [ mmahut ]; + }; + + nodes = { + machine = { ... }: { + services.trezord.enable = true; + services.trezord.emulator.enable = true; + }; + }; + + testScript = '' + startAll; + $machine->waitForUnit("trezord.service"); + $machine->waitForOpenPort(21325); + $machine->waitUntilSucceeds("curl -L http://localhost:21325/status/ | grep Version"); + ''; +}) diff --git a/nixos/tests/xmpp/ejabberd.nix b/nixos/tests/xmpp/ejabberd.nix index 7eb566b54685..196a04aca300 100644 --- a/nixos/tests/xmpp/ejabberd.nix +++ b/nixos/tests/xmpp/ejabberd.nix @@ -45,8 +45,7 @@ import ../make-test.nix ({ pkgs, ... }: { ip: "127.0.0.1" module: ejabberd_service access: local - shaper_rule: fast - ip: "127.0.0.1" + shaper: fast ## Disabling digest-md5 SASL authentication. digest-md5 requires plain-text ## password storage (see auth_password_format option). @@ -181,7 +180,6 @@ import ../make-test.nix ({ pkgs, ... }: { mod_client_state: {} mod_configure: {} # requires mod_adhoc ## mod_delegation: {} # for xep0356 - mod_echo: {} #mod_irc: # host: "irc.@HOST@" # default_encoding: "utf-8" |