diff --git a/modules/module-list.nix b/modules/module-list.nix index 77acac42802..bf985fe5800 100644 --- a/modules/module-list.nix +++ b/modules/module-list.nix @@ -50,6 +50,7 @@ ./security/sudo.nix ./services/amqp/rabbitmq.nix ./services/audio/alsa.nix + ./services/audio/fuppes.nix ./services/audio/pulseaudio.nix ./services/backup/hydra-mirror.nix ./services/backup/mysql-backup.nix @@ -73,6 +74,7 @@ ./services/logging/logrotate.nix ./services/logging/syslogd.nix ./services/mail/dovecot.nix + ./services/mail/freepops.nix ./services/mail/mail.nix ./services/mail/postfix.nix ./services/misc/autofs.nix @@ -89,6 +91,7 @@ ./services/misc/virtualbox.nix ./services/monitoring/monit.nix ./services/monitoring/nagios/default.nix + ./services/monitoring/ups.nix ./services/monitoring/smartd.nix ./services/monitoring/systemhealth.nix ./services/monitoring/zabbix-agent.nix diff --git a/modules/services/audio/fuppes.nix b/modules/services/audio/fuppes.nix new file mode 100644 index 00000000000..df73e62fc94 --- /dev/null +++ b/modules/services/audio/fuppes.nix @@ -0,0 +1,114 @@ +{config, pkgs, ...}: + +let + cfg = config.services.fuppesd; +in + +with pkgs.lib; + +{ + options = { + services.fuppesd = { + enable = mkOption { + default = false; + type = with types; bool; + description = '' + Enables Fuppes (UPnP A/V Media Server). Can be used to watch + photos, video and listen to music from a phone/tv connected to the + local network. + ''; + }; + + name = mkOption { + example = "Media Center"; + type = with types; uniq string; + description = '' + Enables Fuppes (UPnP A/V Media Server). Can be used to watch + photos, video and listen to music from a phone/tv connected to the + local network. + ''; + }; + + log = { + level = mkOption { + default = 0; + example = 3; + type = with types; uniq int; + description = '' + Logging level of fuppes, An integer between 0 and 3. + ''; + }; + + file = mkOption { + default = "/var/log/fuppes.log"; + type = with types; uniq string; + description = '' + File which will contains the log produced by the daemon. + ''; + }; + }; + + config = mkOption { + example = "/etc/fuppes/fuppes.cfg"; + type = with types; uniq string; + description = '' + Mutable configuration file which can be edited with the web + interface. Due to possible modification, double quote the full + path of the filename stored in your filesystem to avoid attempts + to modify the content of the nix store. + ''; + }; + + vfolder = mkOption { + default = ./fuppes/vfolder.cfg; + example = /etc/fuppes/vfolder.cfg; + description = '' + XML file describing the layout of virtual folder visible by the + client. + ''; + }; + + database = mkOption { + default = "/var/lib/fuppes/fuppes.db"; + type = with types; uniq string; + description = '' + Database file which index all shared files. + ''; + }; + + ## At the moment, no plugins are packaged. + /* + plugins = mkOption { + type = with types; listOf package; + description = '' + List of Fuppes plugins. + ''; + }; + */ + + user = mkOption { + default = "root"; # The default is not secure. + example = "fuppes"; + type = with types; uniq string; + description = '' + Name of the user which own the configuration files and under which + the fuppes daemon will be executed. + ''; + }; + + }; + }; + + config = mkIf cfg.enable { + jobs.fuppesd = { + description = "UPnP A/V Media Server. (${cfg.name})"; + startOn = "ip-up"; + daemonType = "fork"; + exec = ''/var/setuid-wrappers/sudo -u ${cfg.user} -- ${pkgs.fuppes}/bin/fuppesd --friendly-name ${cfg.name} --log-level ${toString cfg.log.level} --log-file ${cfg.log.file} --config-file ${cfg.config} --vfolder-config-file ${cfg.vfolder} --database-file ${cfg.database}''; + }; + + services.fuppesd.name = mkDefault config.networking.hostName; + + security.sudo.enable = true; + }; +} diff --git a/modules/services/audio/fuppes/vfolder.cfg b/modules/services/audio/fuppes/vfolder.cfg new file mode 100644 index 00000000000..35ec3bffeb0 --- /dev/null +++ b/modules/services/audio/fuppes/vfolder.cfg @@ -0,0 +1,155 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/services/mail/freepops.nix b/modules/services/mail/freepops.nix new file mode 100644 index 00000000000..9f8b93d3e33 --- /dev/null +++ b/modules/services/mail/freepops.nix @@ -0,0 +1,87 @@ +{config, pkgs, ...}: + +with pkgs.lib; + +let + cfg = config.services.mail.freepopsd; +in + +{ + options = { + services.mail.freepopsd = { + enable = mkOption { + default = false; + type = with types; bool; + description = '' + Enables Freepops, a POP3 webmail wrapper. + ''; + }; + + port = mkOption { + default = 2000; + type = with types; uniq int; + description = '' + Port on which the pop server will listen. + ''; + }; + + threads = mkOption { + default = 5; + type = with types; uniq int; + description = '' + Max simultaneous connections. + ''; + }; + + bind = mkOption { + default = "0.0.0.0"; + type = with types; uniq string; + description = '' + Bind over an IPv4 address instead of any. + ''; + }; + + logFile = mkOption { + default = "/var/log/freepopsd"; + example = "syslog"; + type = with types; uniq string; + description = '' + Filename of the log file or syslog to rely on the logging daemon. + ''; + }; + + suid = { + user = mkOption { + default = "nobody"; + type = with types; uniq string; + description = '' + User name under which freepopsd will be after binding the port. + ''; + }; + + group = mkOption { + default = "nogroup"; + type = with types; uniq string; + description = '' + Group under which freepopsd will be after binding the port. + ''; + }; + }; + + }; + }; + + config = mkIf cfg.enable { + jobs.freepopsd = { + description = "Freepopsd (webmail over POP3)"; + startOn = "ip-up"; + exec = ''${pkgs.freepops}/bin/freepopsd \ + -p ${toString cfg.port} \ + -t ${toString cfg.threads} \ + -b ${cfg.bind} \ + -vv -l ${cfg.logFile} \ + -s ${cfg.suid.user}.${cfg.suid.group} + ''; + }; + }; +} \ No newline at end of file diff --git a/modules/services/monitoring/ups.nix b/modules/services/monitoring/ups.nix new file mode 100644 index 00000000000..8dd80afe42c --- /dev/null +++ b/modules/services/monitoring/ups.nix @@ -0,0 +1,268 @@ +{config, pkgs, ...}: + +# TODO: This is not secure, have a look at the file docs/security.txt inside +# the project sources. +with pkgs.lib; + +let + cfg = config.power.ups; +in + +let + upsOptions = {name, config, ...}: + { + options = { + # This can be infered from the UPS model by looking at + # /nix/store/nut/share/driver.list + driver = mkOption { + type = types.uniq types.string; + description = '' + Specify the program to run to talk to this UPS. apcsmart, + bestups, and sec are some examples. + ''; + }; + + port = mkOption { + type = types.uniq types.string; + description = '' + The serial port where your UPS is connected. /dev/ttyS0 is + usually the first port on Linux boxes, for example. + ''; + }; + + shutdownOrder = mkOption { + default = 0; + type = types.uniq types.int; + description = '' + When you have multiple UPSes on your system, you usually need to + turn them off in a certain order. upsdrvctl shuts down all the + 0s, then the 1s, 2s, and so on. To exclude a UPS from the + shutdown sequence, set this to -1. + ''; + }; + + maxStartDelay = mkOption { + default = null; + type = types.uniq (types.nullOr types.int); + description = '' + This can be set as a global variable above your first UPS + definition and it can also be set in a UPS section. This value + controls how long upsdrvctl will wait for the driver to finish + starting. This keeps your system from getting stuck due to a + broken driver or UPS. + ''; + }; + + description = mkOption { + default = ""; + type = types.string; + description = '' + Description of the UPS. + ''; + }; + + directives = mkOption { + default = []; + type = types.listOf types.string; + description = '' + List of configuration directives for this UPS. + ''; + }; + + summary = mkOption { + default = ""; + type = types.string; + description = '' + Lines which would be added inside ups.conf for handling this UPS. + ''; + }; + + }; + + config = { + directives = mkHeader ([ + "driver = ${config.driver}" + "port = ${config.port}" + ''desc = "${config.description}"'' + "sdorder = ${toString config.shutdownOrder}" + ] ++ (optional (config.maxStartDelay != null) + "maxstartdelay = ${toString config.maxStartDelay}") + ); + + summary = + concatStringsSep "\n " + (["[${name}]"] ++ config.directives); + }; + }; + +in + + +{ + options = { + # powerManagement.powerDownCommands + + power.ups = { + enable = mkOption { + default = false; + type = with types; bool; + description = '' + Enables support for Power Devices, such as Uninterruptible Power + Supplies, Power Distribution Units and Solar Controllers. + ''; + }; + + # This option is not used yet. + mode = mkOption { + default = "standalone"; + type = types.uniq types.string; + description = '' + The MODE determines which part of the NUT is to be started, and + which configuration files must be modified. + + The values of MODE can be: + + - none: NUT is not configured, or use the Integrated Power + Management, or use some external system to startup NUT + components. So nothing is to be started. + + - standalone: This mode address a local only configuration, with 1 + UPS protecting the local system. This implies to start the 3 NUT + layers (driver, upsd and upsmon) and the matching configuration + files. This mode can also address UPS redundancy. + + - netserver: same as for the standalone configuration, but also + need some more ACLs and possibly a specific LISTEN directive in + upsd.conf. Since this MODE is opened to the network, a special + care should be applied to security concerns. + + - netclient: this mode only requires upsmon. + ''; + }; + + schedulerRules = mkOption { + example = "/etc/nixos/upssched.conf"; + type = types.uniq types.string; + description = '' + File which contains the rules to handle UPS events. + ''; + }; + + + maxStartDelay = mkOption { + default = 45; + type = types.uniq types.int; + description = '' + This can be set as a global variable above your first UPS + definition and it can also be set in a UPS section. This value + controls how long upsdrvctl will wait for the driver to finish + starting. This keeps your system from getting stuck due to a + broken driver or UPS. + ''; + }; + + ups = mkOption { + default = {}; + # see nut/etc/ups.conf.sample + description = '' + This is where you configure all the UPSes that this system will be + monitoring directly. These are usually attached to serial ports, + but USB devices are also supported. + ''; + type = types.attrsOf types.optionSet; + options = [ upsOptions ]; + }; + + }; + }; + + config = mkIf cfg.enable { + + environment.systemPackages = [ pkgs.nut ]; + + jobs.upsmon = { + description = "Uninterruptible Power Supplies (Monitor)"; + startOn = "ip-up"; + daemonType = "fork"; + exec = ''${pkgs.nut}/sbin/upsmon''; + environment.NUT_CONFPATH = "/etc/nut/"; + environment.NUT_STATEPATH = "/var/lib/nut/"; + }; + + jobs.upsd = { + description = "Uninterruptible Power Supplies (Daemon)"; + startOn = "started network-interfaces and upsmon"; + daemonType = "fork"; + # TODO: replace 'root' by another username. + exec = ''${pkgs.nut}/sbin/upsd -u root''; + environment.NUT_CONFPATH = "/etc/nut/"; + environment.NUT_STATEPATH = "/var/lib/nut/"; + }; + + jobs.upsdrv = { + description = "Uninterruptible Power Supplies (Register all UPS)"; + startOn = "started upsd"; + # TODO: replace 'root' by another username. + exec = ''${pkgs.nut}/bin/upsdrvctl -u root start''; + task = true; + environment.NUT_CONFPATH = "/etc/nut/"; + environment.NUT_STATEPATH = "/var/lib/nut/"; + }; + + environment.etc = [ + { source = pkgs.writeText "nut.conf" + '' + MODE = ${cfg.mode} + ''; + target = "nut/nut.conf"; + } + { source = pkgs.writeText "ups.conf" + '' + maxstartdelay = ${toString cfg.maxStartDelay} + + ${flip concatStringsSep (flip map (attrValues cfg.ups) (ups: ups.summary)) " + + "} + ''; + target = "nut/ups.conf"; + } + { source = cfg.schedulerRules; + target = "nut/upssched.conf"; + } + # These file are containing private informations and thus should not + # be stored inside the Nix store. + /* + { source = ; + target = "nut/upsd.conf"; + } + { source = ; + target = "nut/upsd.users"; + } + { source = ; + target = "nut/upsmon.conf; + } + */ + ]; + + power.ups.schedulerRules = mkDefault "${pkgs.nut}/etc/upssched.conf.sample"; + +/* + users.extraUsers = [ + { name = "nut"; + uid = 84; + home = "/var/lib/nut"; + createHome = true; + group = "nut"; + description = "UPnP A/V Media Server user"; + } + ]; + + users.extraGroups = [ + { name = "nut"; + gid = 84; + } + ]; +*/ + + }; +}