{ config, lib, pkgs, ... }: let inherit (lib.attrsets) optionalAttrs; inherit (lib.generators) toINIWithGlobalSection; inherit (lib.lists) optional; inherit (lib.modules) mkIf; inherit (lib.options) literalExpression mkEnableOption mkOption; inherit (lib.strings) escape; inherit (lib.types) attrsOf bool int lines oneOf str submodule; cfg = config.services.davfs2; escapeString = escape ["\"" "\\"]; formatValue = value: if true == value then "1" else if false == value then "0" else if builtins.isString value then "\"${escapeString value}\"" else toString value; configFile = pkgs.writeText "davfs2.conf" ( if (cfg.settings != { }) then (toINIWithGlobalSection { mkSectionName = escapeString; mkKeyValue = k: v: "${k} ${formatValue v}"; } cfg.settings) else cfg.extraConfig ); in { options.services.davfs2 = { enable = mkEnableOption "davfs2"; davUser = mkOption { type = str; default = "davfs2"; description = '' When invoked by root the mount.davfs daemon will run as this user. Value must be given as name, not as numerical id. ''; }; davGroup = mkOption { type = str; default = "davfs2"; description = '' The group of the running mount.davfs daemon. Ordinary users must be member of this group in order to mount a davfs2 file system. Value must be given as name, not as numerical id. ''; }; extraConfig = mkOption { type = lines; default = ""; example = '' proxy foo.bar:8080 use_locks 0 [/media/dav] use_locks 1 [/home/otto/mywebspace] gui_optimize 1 ''; description = '' Extra lines appended to the configuration of davfs2. See {manpage}`davfs2.conf(5)` for available settings. **Note**: Please pass structured settings via {option}`settings` instead, this option will get deprecated in the future. '' ; }; settings = mkOption { type = submodule { freeformType = let valueTypes = [ bool int str ]; in attrsOf (attrsOf (oneOf (valueTypes ++ [ (attrsOf (oneOf valueTypes)) ] ))); }; default = { }; example = literalExpression '' { globalSection = { proxy = "foo.bar:8080"; use_locks = false; }; sections = { "/media/dav" = { use_locks = true; }; "/home/otto/mywebspace" = { gui_optimize = true; }; }; } ''; description = '' Extra settings appended to the configuration of davfs2. See {manpage}`davfs2.conf(5)` for available settings. '' ; }; }; config = mkIf cfg.enable { assertions = [ { assertion = cfg.extraConfig != "" -> cfg.settings == { }; message = '' services.davfs2.extraConfig and services.davfs2.settings cannot be used together. Please prefer using services.davfs2.settings. ''; } ]; warnings = optional (cfg.extraConfig != "") '' services.davfs2.extraConfig will be deprecated in future releases; please use services.davfs2.settings instead. ''; environment.systemPackages = [ pkgs.davfs2 ]; environment.etc."davfs2/davfs2.conf".source = configFile; services.davfs2.settings = { globalSection = { dav_user = cfg.davUser; dav_group = cfg.davGroup; }; }; users.groups = optionalAttrs (cfg.davGroup == "davfs2") { davfs2.gid = config.ids.gids.davfs2; }; users.users = optionalAttrs (cfg.davUser == "davfs2") { davfs2 = { createHome = false; group = cfg.davGroup; uid = config.ids.uids.davfs2; description = "davfs2 user"; }; }; security.wrappers."mount.davfs" = { program = "mount.davfs"; source = "${pkgs.davfs2}/bin/mount.davfs"; owner = "root"; group = cfg.davGroup; setuid = true; permissions = "u+rx,g+x"; }; security.wrappers."umount.davfs" = { program = "umount.davfs"; source = "${pkgs.davfs2}/bin/umount.davfs"; owner = "root"; group = cfg.davGroup; setuid = true; permissions = "u+rx,g+x"; }; }; }