diff --git a/README.md b/README.md index 2c9ba67..8ceefb8 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,7 @@ services. Also, the design will be extendable to allow users to add services not - [X] Database Postgres - [ ] Slow log monitoring. - [ ] Export metrics to Prometheus. +- [X] Mount webdav folders ## Repo layout diff --git a/flake.nix b/flake.nix index 59b9219..15a2b5f 100644 --- a/flake.nix +++ b/flake.nix @@ -13,6 +13,7 @@ modules/authelia.nix modules/backup.nix modules/deluge.nix + modules/davfs.nix modules/hledger.nix modules/home-assistant.nix modules/jellyfin.nix diff --git a/modules/davfs.nix b/modules/davfs.nix new file mode 100644 index 0000000..5512054 --- /dev/null +++ b/modules/davfs.nix @@ -0,0 +1,108 @@ +{ config, pkgs, lib, ... }: + +let + cfg = config.shb.davfs; + + template = file: newPath: replacements: + let + templatePath = newPath + ".template"; + + sedPatterns = lib.strings.concatStringsSep " " (lib.attrsets.mapAttrsToList (from: to: "\"s|${from}|${to}|\"") replacements); + in + '' + ln -fs ${file} ${templatePath} + rm ${newPath} || : + sed ${sedPatterns} ${templatePath} > ${newPath} + ''; +in +{ + options.shb.davfs = { + mounts = lib.mkOption { + type = lib.types.listOf (lib.types.submodule { + options = { + remoteUrl = lib.mkOption { + type = lib.types.str; + description = "Webdav endpoint to connect to."; + example = "https://my.domain.com/dav"; + }; + + mountPoint = lib.mkOption { + type = lib.types.str; + description = "Mount point to mount the webdav endpoint on."; + example = "/mnt"; + }; + + username = lib.mkOption { + type = lib.types.str; + description = "Username to connect to the webdav endpoint."; + }; + + passwordFile = lib.mkOption { + type = lib.types.str; + description = "Password to connect to the webdav endpoint."; + }; + + uid = lib.mkOption { + type = lib.types.nullOr lib.types.int; + description = "User owner of the mount point."; + example = 1000; + default = null; + }; + + gid = lib.mkOption { + type = lib.types.nullOr lib.types.int; + description = "Group owner of the mount point."; + example = 1000; + default = null; + }; + + fileMode = lib.mkOption { + type = lib.types.nullOr lib.types.str; + description = "File creation mode"; + example = "0664"; + default = null; + }; + + directoryMode = lib.mkOption { + type = lib.types.nullOr lib.types.str; + description = "Directory creation mode"; + example = "2775"; + default = null; + }; + + automount = lib.mkOption { + type = lib.types.bool; + description = "Create a systemd automount unit"; + default = true; + }; + }; + }); + }; + }; + + config = { + services.davfs2.enable = builtins.length cfg.mounts > 0; + + systemd.mounts = + let + mkMountCfg = c: { + enable = true; + description = "Webdav mount point"; + after = [ "network-online.target" ]; + wants = [ "network-online.target" ]; + + what = c.remoteUrl; + where = c.mountPoint; + options = lib.concatStringsSep "," ( + (lib.optional (!(isNull c.uid)) "uid=${toString c.uid}") + ++ (lib.optional (!(isNull c.gid)) "gid=${toString c.uid}") + ++ (lib.optional (!(isNull c.fileMode)) "file_mode=${toString c.fileMode}") + ++ (lib.optional (!(isNull c.directoryMode)) "dir_mode=${toString c.directoryMode}") + ); + type = "davfs"; + mountConfig.TimeoutSet = 15; + }; + in + lib.debug.traceValSeqN 2 (map mkMountCfg cfg.mounts); + }; +}