diff options
author | Vladimír Čunát <vcunat@gmail.com> | 2017-08-29 10:51:54 +0200 |
---|---|---|
committer | Vladimír Čunát <vcunat@gmail.com> | 2017-08-29 10:51:54 +0200 |
commit | 2858c41823db1654f123c455cca2b145b8d8737b (patch) | |
tree | 48518e1eb8916d1528d75823c2d1232822d059e9 /nixos/modules/services | |
parent | 34b6bbe021baa11a4dddf9532b331dac8d4162f2 (diff) | |
parent | e1f755e44faa5745ad3a8b18e18017e77dfbe67c (diff) | |
download | nixlib-2858c41823db1654f123c455cca2b145b8d8737b.tar nixlib-2858c41823db1654f123c455cca2b145b8d8737b.tar.gz nixlib-2858c41823db1654f123c455cca2b145b8d8737b.tar.bz2 nixlib-2858c41823db1654f123c455cca2b145b8d8737b.tar.lz nixlib-2858c41823db1654f123c455cca2b145b8d8737b.tar.xz nixlib-2858c41823db1654f123c455cca2b145b8d8737b.tar.zst nixlib-2858c41823db1654f123c455cca2b145b8d8737b.zip |
Merge branch 'master' into staging
There were some conflicts in python modules, commented at #28314.
Diffstat (limited to 'nixos/modules/services')
-rw-r--r-- | nixos/modules/services/misc/airsonic.nix | 117 | ||||
-rw-r--r-- | nixos/modules/services/networking/i2pd.nix | 198 | ||||
-rw-r--r-- | nixos/modules/services/networking/lldpd.nix | 9 | ||||
-rw-r--r-- | nixos/modules/services/printing/cupsd.nix | 32 | ||||
-rw-r--r-- | nixos/modules/services/security/usbguard.nix | 200 | ||||
-rw-r--r-- | nixos/modules/services/web-servers/phpfpm/default.nix | 3 |
6 files changed, 444 insertions, 115 deletions
diff --git a/nixos/modules/services/misc/airsonic.nix b/nixos/modules/services/misc/airsonic.nix new file mode 100644 index 000000000000..b92104787a56 --- /dev/null +++ b/nixos/modules/services/misc/airsonic.nix @@ -0,0 +1,117 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.airsonic; +in { + options = { + + services.airsonic = { + enable = mkEnableOption "Airsonic, the Free and Open Source media streaming server (fork of Subsonic and Libresonic)"; + + user = mkOption { + type = types.str; + default = "airsonic"; + description = "User account under which airsonic runs."; + }; + + home = mkOption { + type = types.path; + default = "/var/lib/airsonic"; + description = '' + The directory where Airsonic will create files. + Make sure it is writable. + ''; + }; + + listenAddress = mkOption { + type = types.string; + default = "127.0.0.1"; + description = '' + The host name or IP address on which to bind Airsonic. + Only relevant if you have multiple network interfaces and want + to make Airsonic available on only one of them. The default value + will bind Airsonic to all available network interfaces. + ''; + }; + + port = mkOption { + type = types.int; + default = 4040; + description = '' + The port on which Airsonic will listen for + incoming HTTP traffic. Set to 0 to disable. + ''; + }; + + contextPath = mkOption { + type = types.path; + default = "/"; + description = '' + The context path, i.e., the last part of the Airsonic + URL. Typically '/' or '/airsonic'. Default '/' + ''; + }; + + maxMemory = mkOption { + type = types.int; + default = 100; + description = '' + The memory limit (max Java heap size) in megabytes. + Default: 100 + ''; + }; + + transcoders = mkOption { + type = types.listOf types.path; + default = [ "${pkgs.ffmpeg.bin}/bin/ffmpeg" ]; + defaultText= [ "\${pkgs.ffmpeg.bin}/bin/ffmpeg" ]; + description = '' + List of paths to transcoder executables that should be accessible + from Airsonic. Symlinks will be created to each executable inside + ${cfg.home}/transcoders. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + systemd.services.airsonic = { + description = "Airsonic Media Server"; + after = [ "local-fs.target" "network.target" ]; + wantedBy = [ "multi-user.target" ]; + + preStart = '' + # Install transcoders. + rm -rf ${cfg.home}/transcode + mkdir -p ${cfg.home}/transcode + for exe in ${toString cfg.transcoders}; do + ln -sf "$exe" ${cfg.home}/transcode + done + ''; + serviceConfig = { + ExecStart = '' + ${pkgs.jre}/bin/java -Xmx${toString cfg.maxMemory}m \ + -Dairsonic.home=${cfg.home} \ + -Dserver.address=${cfg.listenAddress} \ + -Dserver.port=${toString cfg.port} \ + -Dairsonic.contextPath=${cfg.contextPath} \ + -Djava.awt.headless=true \ + -verbose:gc \ + -jar ${pkgs.airsonic}/webapps/airsonic.war + ''; + Restart = "always"; + User = "airsonic"; + UMask = "0022"; + }; + }; + + users.extraUsers.airsonic = { + description = "Airsonic service user"; + name = cfg.user; + home = cfg.home; + createHome = true; + }; + }; +} diff --git a/nixos/modules/services/networking/i2pd.nix b/nixos/modules/services/networking/i2pd.nix index 7622f030f832..5c4932075fed 100644 --- a/nixos/modules/services/networking/i2pd.nix +++ b/nixos/modules/services/networking/i2pd.nix @@ -28,15 +28,15 @@ let }; mkKeyedEndpointOpt = name: addr: port: keyFile: - (mkEndpointOpt name addr port) // { - keys = mkOption { - type = types.str; - default = ""; - description = '' - File to persist ${lib.toUpper name} keys. - ''; + (mkEndpointOpt name addr port) // { + keys = mkOption { + type = types.str; + default = ""; + description = '' + File to persist ${lib.toUpper name} keys. + ''; + }; }; - }; commonTunOpts = let i2cpOpts = { @@ -59,7 +59,7 @@ let description = "Number of ElGamal/AES tags to send."; default = 40; }; - destination = mkOption { + destination = mkOption { type = types.str; description = "Remote endpoint, I2P hostname or b32.i2p address."; }; @@ -70,88 +70,91 @@ let }; } // mkEndpointOpt name "127.0.0.1" 0; - i2pdConf = pkgs.writeText "i2pd.conf" - '' - ipv4 = ${boolToString cfg.enableIPv4} - ipv6 = ${boolToString cfg.enableIPv6} - notransit = ${boolToString cfg.notransit} - floodfill = ${boolToString cfg.floodfill} - netid = ${toString cfg.netid} - ${if isNull cfg.bandwidth then "" else "bandwidth = ${toString cfg.bandwidth}" } - ${if isNull cfg.port then "" else "port = ${toString cfg.port}"} - - [limits] - transittunnels = ${toString cfg.limits.transittunnels} - - [upnp] - enabled = ${boolToString cfg.upnp.enable} - name = ${cfg.upnp.name} - - [precomputation] - elgamal = ${boolToString cfg.precomputation.elgamal} - - [reseed] - verify = ${boolToString cfg.reseed.verify} - file = ${cfg.reseed.file} - urls = ${builtins.concatStringsSep "," cfg.reseed.urls} - - [addressbook] - defaulturl = ${cfg.addressbook.defaulturl} - subscriptions = ${builtins.concatStringsSep "," cfg.addressbook.subscriptions} - ${flip concatMapStrings + i2pdConf = pkgs.writeText "i2pd.conf" '' + # DO NOT EDIT -- this file has been generated automatically. + loglevel = ${cfg.logLevel} + + ipv4 = ${boolToString cfg.enableIPv4} + ipv6 = ${boolToString cfg.enableIPv6} + notransit = ${boolToString cfg.notransit} + floodfill = ${boolToString cfg.floodfill} + netid = ${toString cfg.netid} + ${if isNull cfg.bandwidth then "" else "bandwidth = ${toString cfg.bandwidth}" } + ${if isNull cfg.port then "" else "port = ${toString cfg.port}"} + + [limits] + transittunnels = ${toString cfg.limits.transittunnels} + + [upnp] + enabled = ${boolToString cfg.upnp.enable} + name = ${cfg.upnp.name} + + [precomputation] + elgamal = ${boolToString cfg.precomputation.elgamal} + + [reseed] + verify = ${boolToString cfg.reseed.verify} + file = ${cfg.reseed.file} + urls = ${builtins.concatStringsSep "," cfg.reseed.urls} + + [addressbook] + defaulturl = ${cfg.addressbook.defaulturl} + subscriptions = ${builtins.concatStringsSep "," cfg.addressbook.subscriptions} + + ${flip concatMapStrings (collect (proto: proto ? port && proto ? address && proto ? name) cfg.proto) - (proto: let portStr = toString proto.port; in - '' - [${proto.name}] - enabled = ${boolToString proto.enable} - address = ${proto.address} - port = ${toString proto.port} - ${if proto ? keys then "keys = ${proto.keys}" else ""} - ${if proto ? auth then "auth = ${boolToString proto.auth}" else ""} - ${if proto ? user then "user = ${proto.user}" else ""} - ${if proto ? pass then "pass = ${proto.pass}" else ""} - ${if proto ? outproxy then "outproxy = ${proto.outproxy}" else ""} - ${if proto ? outproxyPort then "outproxyport = ${toString proto.outproxyPort}" else ""} - '') - } + (proto: let portStr = toString proto.port; in '' + [${proto.name}] + enabled = ${boolToString proto.enable} + address = ${proto.address} + port = ${toString proto.port} + ${if proto ? keys then "keys = ${proto.keys}" else ""} + ${if proto ? auth then "auth = ${boolToString proto.auth}" else ""} + ${if proto ? user then "user = ${proto.user}" else ""} + ${if proto ? pass then "pass = ${proto.pass}" else ""} + ${if proto ? outproxy then "outproxy = ${proto.outproxy}" else ""} + ${if proto ? outproxyPort then "outproxyport = ${toString proto.outproxyPort}" else ""} + '') + } ''; i2pdTunnelConf = pkgs.writeText "i2pd-tunnels.conf" '' - ${flip concatMapStrings - (collect (tun: tun ? port && tun ? destination) cfg.outTunnels) - (tun: let portStr = toString tun.port; in '' - [${tun.name}] - type = client - destination = ${tun.destination} - keys = ${tun.keys} - address = ${tun.address} - port = ${toString tun.port} - inbound.length = ${toString tun.inbound.length} - outbound.length = ${toString tun.outbound.length} - inbound.quantity = ${toString tun.inbound.quantity} - outbound.quantity = ${toString tun.outbound.quantity} - crypto.tagsToSend = ${toString tun.crypto.tagsToSend} - '') - } - ${flip concatMapStrings - (collect (tun: tun ? port && tun ? host) cfg.inTunnels) - (tun: let portStr = toString tun.port; in '' - [${tun.name}] - type = server - destination = ${tun.destination} - keys = ${tun.keys} - host = ${tun.address} - port = ${tun.port} - inport = ${tun.inPort} - accesslist = ${builtins.concatStringsSep "," tun.accessList} - '') - } + # DO NOT EDIT -- this file has been generated automatically. + ${flip concatMapStrings + (collect (tun: tun ? port && tun ? destination) cfg.outTunnels) + (tun: let portStr = toString tun.port; in '' + [${tun.name}] + type = client + destination = ${tun.destination} + keys = ${tun.keys} + address = ${tun.address} + port = ${toString tun.port} + inbound.length = ${toString tun.inbound.length} + outbound.length = ${toString tun.outbound.length} + inbound.quantity = ${toString tun.inbound.quantity} + outbound.quantity = ${toString tun.outbound.quantity} + crypto.tagsToSend = ${toString tun.crypto.tagsToSend} + '') + } + ${flip concatMapStrings + (collect (tun: tun ? port && tun ? host) cfg.inTunnels) + (tun: let portStr = toString tun.port; in '' + [${tun.name}] + type = server + destination = ${tun.destination} + keys = ${tun.keys} + host = ${tun.address} + port = ${tun.port} + inport = ${tun.inPort} + accesslist = ${builtins.concatStringsSep "," tun.accessList} + '') + } ''; i2pdSh = pkgs.writeScriptBin "i2pd" '' #!/bin/sh - ${pkgs.i2pd}/bin/i2pd \ - ${if isNull cfg.extIp then "" else "--host="+cfg.extIp} \ + exec ${pkgs.i2pd}/bin/i2pd \ + ${if isNull cfg.address then "" else "--host="+cfg.address} \ --conf=${i2pdConf} \ --tunconf=${i2pdTunnelConf} ''; @@ -176,11 +179,23 @@ in ''; }; - extIp = mkOption { + logLevel = mkOption { + type = types.enum ["debug" "info" "warn" "error"]; + default = "error"; + description = '' + The log level. <command>i2pd</command> defaults to "info" + but that generates copious amounts of log messages. + + We default to "error" which is similar to the default log + level of <command>tor</command>. + ''; + }; + + address = mkOption { type = with types; nullOr str; default = null; description = '' - Your external IP. + Your external IP or hostname. ''; }; @@ -213,7 +228,7 @@ in default = null; description = '' Set a router bandwidth limit integer in KBps. - If not set, i2pd defaults to 32KBps. + If not set, <command>i2pd</command> defaults to 32KBps. ''; }; @@ -261,9 +276,14 @@ in precomputation.elgamal = mkOption { type = types.bool; - default = false; + default = true; description = '' - Use ElGamal precomputated tables. + Whenever to use precomputated tables for ElGamal. + <command>i2pd</command> defaults to <literal>false</literal> + to save 64M of memory (and looses some performance). + + We default to <literal>true</literal> as that is what most + users want anyway. ''; }; @@ -353,7 +373,7 @@ in }; }; - proto.httpProxy = mkKeyedEndpointOpt "httpproxy" "127.0.0.1" 4446 ""; + proto.httpProxy = mkKeyedEndpointOpt "httpproxy" "127.0.0.1" 4444 ""; proto.socksProxy = (mkKeyedEndpointOpt "socksproxy" "127.0.0.1" 4447 "") // { outproxy = mkOption { diff --git a/nixos/modules/services/networking/lldpd.nix b/nixos/modules/services/networking/lldpd.nix index 4f951d843e2c..ba4e1b1542fe 100644 --- a/nixos/modules/services/networking/lldpd.nix +++ b/nixos/modules/services/networking/lldpd.nix @@ -28,16 +28,11 @@ in users.extraGroups._lldpd = {}; environment.systemPackages = [ pkgs.lldpd ]; + systemd.packages = [ pkgs.lldpd ]; systemd.services.lldpd = { wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - requires = [ "network.target" ]; - serviceConfig = { - ExecStart = "${pkgs.lldpd}/bin/lldpd -d ${concatStringsSep " " cfg.extraArgs}"; - PrivateTmp = true; - PrivateDevices = true; - }; + environment.LLDPD_OPTIONS = concatStringsSep " " cfg.extraArgs; }; }; } diff --git a/nixos/modules/services/printing/cupsd.nix b/nixos/modules/services/printing/cupsd.nix index 855c89303847..4c7f58d1d8bc 100644 --- a/nixos/modules/services/printing/cupsd.nix +++ b/nixos/modules/services/printing/cupsd.nix @@ -4,7 +4,7 @@ with lib; let - inherit (pkgs) cups cups-pk-helper cups-filters gutenprint; + inherit (pkgs) cups cups-pk-helper cups-filters; cfg = config.services.printing; @@ -35,7 +35,6 @@ let name = "cups-progs"; paths = [ cups.out additionalBackends cups-filters pkgs.ghostscript ] - ++ optional cfg.gutenprint gutenprint ++ cfg.drivers; pathsToLink = [ "/lib" "/share/cups" "/bin" ]; postBuild = cfg.bindirCmds; @@ -97,12 +96,15 @@ let (writeConf "client.conf" cfg.clientConf) (writeConf "snmp.conf" cfg.snmpConf) ] ++ optional avahiEnabled browsedFile - ++ optional cfg.gutenprint gutenprint ++ cfg.drivers; pathsToLink = [ "/etc/cups" ]; ignoreCollisions = true; }; + filterGutenprint = pkgs: filter (pkg: pkg.meta.isGutenprint or false == true) pkgs; + containsGutenprint = pkgs: length (filterGutenprint pkgs) > 0; + getGutenprint = pkgs: head (filterGutenprint pkgs); + in { @@ -224,23 +226,17 @@ in ''; }; - gutenprint = mkOption { - type = types.bool; - default = false; - description = '' - Whether to enable Gutenprint drivers for CUPS. This includes auto-updating - Gutenprint PPD files. - ''; - }; - drivers = mkOption { type = types.listOf types.path; default = []; - example = literalExample "[ pkgs.splix ]"; + example = literalExample "[ pkgs.gutenprint pkgs.hplip pkgs.splix ]"; description = '' - CUPS drivers to use. Drivers provided by CUPS, cups-filters, Ghostscript - and Samba are added unconditionally. For adding Gutenprint, see - <literal>gutenprint</literal>. + CUPS drivers to use. Drivers provided by CUPS, cups-filters, + Ghostscript and Samba are added unconditionally. If this list contains + Gutenprint (i.e. a derivation with + <literal>meta.isGutenprint = true</literal>) the PPD files in + <filename>/var/lib/cups/ppd</filename> will be updated automatically + to avoid errors due to incompatible versions. ''; }; @@ -318,9 +314,9 @@ in [ ! -e /var/lib/cups/path ] && \ ln -s ${bindir} /var/lib/cups/path - ${optionalString cfg.gutenprint '' + ${optionalString (containsGutenprint cfg.drivers) '' if [ -d /var/lib/cups/ppd ]; then - ${gutenprint}/bin/cups-genppdupdate -p /var/lib/cups/ppd + ${getGutenprint cfg.drivers}/bin/cups-genppdupdate -p /var/lib/cups/ppd fi ''} ''; diff --git a/nixos/modules/services/security/usbguard.nix b/nixos/modules/services/security/usbguard.nix new file mode 100644 index 000000000000..1f2c56a9efa1 --- /dev/null +++ b/nixos/modules/services/security/usbguard.nix @@ -0,0 +1,200 @@ +{config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.usbguard; + + # valid policy options + policy = (types.enum [ "allow" "block" "reject" "keep" "apply-policy" ]); + + # decide what file to use for rules + ruleFile = if cfg.rules != null then pkgs.writeText "usbguard-rules" cfg.rules else cfg.ruleFile; + + daemonConf = '' + # generated by nixos/modules/services/security/usbguard.nix + RuleFile=${ruleFile} + ImplicitPolicyTarget=${cfg.implictPolicyTarget} + PresentDevicePolicy=${cfg.presentDevicePolicy} + PresentControllerPolicy=${cfg.presentControllerPolicy} + InsertedDevicePolicy=${cfg.insertedDevicePolicy} + RestoreControllerDeviceState=${if cfg.restoreControllerDeviceState then "true" else "false"} + # this does not seem useful for endusers to change + DeviceManagerBackend=uevent + IPCAllowedUsers=${concatStringsSep " " cfg.IPCAllowedUsers} + IPCAllowedGroups=${concatStringsSep " " cfg.IPCAllowedGroups} + IPCAccessControlFiles=${cfg.IPCAccessControlFiles} + DeviceRulesWithPort=${if cfg.deviceRulesWithPort then "true" else "false"} + AuditFilePath=${cfg.auditFilePath} + ''; + + daemonConfFile = pkgs.writeText "usbguard-daemon-conf" daemonConf; + +in { + + ###### interface + + options = { + services.usbguard = { + enable = mkEnableOption "USBGuard daemon"; + + ruleFile = mkOption { + type = types.path; + default = "/var/lib/usbguard/rules.conf"; + description = '' + The USBGuard daemon will use this file to load the policy rule set + from it and to write new rules received via the IPC interface. + + Running the command <literal>usbguard generate-policy</literal> as + root will generate a config for your currently plugged in devices. + For a in depth guide consult the official documentation. + + Setting the <literal>rules</literal> option will ignore the + <literal>ruleFile</literal> option. + ''; + }; + + rules = mkOption { + type = types.nullOr types.str; + default = null; + example = '' + allow with-interface equals { 08:*:* } + ''; + description = '' + The USBGuard daemon will load this policy rule set. Modifying it via + the IPC interface won't work if you use this option, since the + contents of this option will be written into the nix-store it will be + read-only. + + You can still use <literal> usbguard generate-policy</literal> to + generate rules, but you would have to insert them here. + + Setting the <literal>rules</literal> option will ignore the + <literal>ruleFile</literal> option. + ''; + }; + + implictPolicyTarget = mkOption { + type = policy; + default = "block"; + description = '' + How to treat USB devices that don't match any rule in the policy. + Target should be one of allow, block or reject (logically remove the + device node from the system). + ''; + }; + + presentDevicePolicy = mkOption { + type = policy; + default = "apply-policy"; + description = '' + How to treat USB devices that are already connected when the daemon + starts. Policy should be one of allow, block, reject, keep (keep + whatever state the device is currently in) or apply-policy (evaluate + the rule set for every present device). + ''; + }; + + presentControllerPolicy = mkOption { + type = policy; + default = "keep"; + description = '' + How to treat USB controller devices that are already connected when + the daemon starts. One of allow, block, reject, keep or apply-policy. + ''; + }; + + insertedDevicePolicy = mkOption { + type = policy; + default = "apply-policy"; + description = '' + How to treat USB devices that are already connected after the daemon + starts. One of block, reject, apply-policy. + ''; + }; + + restoreControllerDeviceState = mkOption { + type = types.bool; + default = false; + description = '' + The USBGuard daemon modifies some attributes of controller + devices like the default authorization state of new child device + instances. Using this setting, you can controll whether the daemon + will try to restore the attribute values to the state before + modificaton on shutdown. + ''; + }; + + IPCAllowedUsers = mkOption { + type = types.listOf types.str; + default = [ "root" ]; + example = [ "root" "yourusername" ]; + description = '' + A list of usernames that the daemon will accept IPC connections from. + ''; + }; + + IPCAllowedGroups = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "wheel" ]; + description = '' + A list of groupnames that the daemon will accept IPC connections + from. + ''; + }; + + IPCAccessControlFiles = mkOption { + type = types.path; + default = "/var/lib/usbguard/IPCAccessControl.d/"; + description = '' + The files at this location will be interpreted by the daemon as IPC + access control definition files. See the IPC ACCESS CONTROL section + in <citerefentry><refentrytitle>usbguard-daemon.conf</refentrytitle> + <manvolnum>5</manvolnum></citerefentry> for more details. + ''; + }; + + deviceRulesWithPort = mkOption { + type = types.bool; + default = false; + description = '' + Generate device specific rules including the "via-port" attribute. + ''; + }; + + auditFilePath = mkOption { + type = types.path; + default = "/var/log/usbguard/usbguard-audit.log"; + description = '' + USBGuard audit events log file path. + ''; + }; + }; + }; + + + ###### implementation + + config = mkIf cfg.enable { + + environment.systemPackages = [ pkgs.usbguard ]; + + systemd.services.usbguard = { + description = "USBGuard daemon"; + + wantedBy = [ "basic.target" ]; + wants = [ "systemd-udevd.service" "local-fs.target" ]; + + # make sure an empty rule file and required directories exist + preStart = ''mkdir -p $(dirname "${cfg.ruleFile}") "${cfg.IPCAccessControlFiles}" && ([ -f "${cfg.ruleFile}" ] || touch ${cfg.ruleFile})''; + + serviceConfig = { + Type = "simple"; + ExecStart = ''${pkgs.usbguard}/bin/usbguard-daemon -d -k -c ${daemonConfFile}''; + Restart = "on-failure"; + }; + }; + }; +} diff --git a/nixos/modules/services/web-servers/phpfpm/default.nix b/nixos/modules/services/web-servers/phpfpm/default.nix index f9febbfbacdf..e1f4ff5db7f2 100644 --- a/nixos/modules/services/web-servers/phpfpm/default.nix +++ b/nixos/modules/services/web-servers/phpfpm/default.nix @@ -150,7 +150,8 @@ in { PrivateDevices = true; ProtectSystem = "full"; ProtectHome = true; - RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6"; + # 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 = "${cfg.phpPackage}/bin/php-fpm -y ${cfgFile} -c ${phpIni}"; ExecReload = "${pkgs.coreutils}/bin/kill -USR2 $MAINPID"; |