# https://discourse.nixos.org/t/casual-nixpkgs-contributions/9607/11? { config, lib, pkgs, ... }: with lib; let seaweedfs = pkgs.unstable.seaweedfs; user = "seaweedfs"; group = "seaweedfs"; cfg = config.services.seaweedfs; enabledVolumes = filterAttrs (_: v: v.enable) cfg.volumes; anyEnabled = cfg.master.enable || cfg.filer.enable || cfg.webdav.enable || enabledVolumes != { }; mkCmdLineArguments = mapAttrsToList (option: value: if isBool value then "-${option}" else "-${option}=${ if isList value then builtins.concatStringsSep "," value else toString value }"); mkWeedExec = subcmd: options: (toString ([ "${seaweedfs}/bin/weed" subcmd ] ++ mkCmdLineArguments ((removeAttrs options [ "enable" "extraConfig" ]) // (if options ? "extraConfig" then (removeAttrs options.extraConfig (builtins.attrNames options)) else { })))); mkExtraConfigOption = subcmd: mkOption { default = { }; type = with types; attrs; description = '' Additional configuration, see output of 'weed ${subcmd} --help' for attributes. Do not define settings for flags for which explicit configuration options exist, these will be ignored. ''; }; mkPortOption = defaultPort: mkOption { default = defaultPort; type = with types; uniq port; description = "Http listen port"; }; mkServerListOption = subcmd: mkOption { default = [ "localhost:${toString cfg.${subcmd}.port}" ]; type = with types; listOf str; description = "List of ${subcmd} servers (host/ip:port)"; }; mkVolumeService = id: options: nameValuePair "seaweedfs-volume-${id}" { wantedBy = [ "multi-user.target" ]; after = [ "network.target" ] ++ optional cfg.master.enable "seaweedfs-master.service"; description = "SeaweedFS volume - ${id}"; unitConfig.ConditionPathIsDirectory = options.dir; serviceConfig = { User = user; Group = group; ExecStart = mkWeedExec "volume" options; KillSignal = "SIGTERM"; }; }; mkVolumeOptions = { id, ... }: { options = { enable = mkEnableOption "SeaweedFS volume server"; port = mkPortOption 8080; mserver = mkServerListOption "master"; extraConfig = mkExtraConfigOption "volume"; dir = mkOption { default = [ "/tmp" ]; type = with types; listOf path; description = '' One or more directories to store data files. These must exist before the volume server service is started, and must be owned by ${user}:${group}.''; }; }; }; in { ###### interface options = { services.seaweedfs = { master = { enable = mkEnableOption "SeaweedFS master server"; port = mkPortOption 9333; peers = mkServerListOption "peers"; extraConfig = mkExtraConfigOption "master"; }; filer = { enable = mkEnableOption "SeaweedFS file server"; port = mkPortOption 8888; master = mkServerListOption "master"; extraConfig = mkExtraConfigOption "filer"; }; volumes = mkOption { default = { }; type = with types; attrsOf (submodule mkVolumeOptions); }; webdav = { enable = mkEnableOption "SeaweedFS webdav server"; port = mkPortOption 7333; filer = mkServerListOption "filer"; extraConfig = mkExtraConfigOption "webdav"; }; }; }; ###### implementation config = mkIf anyEnabled { environment.systemPackages = [ seaweedfs ]; users.users.${user} = { description = "SeaweedFS user"; isSystemUser = true; }; users.groups.${group} = { }; systemd.services = (mapAttrs' mkVolumeService enabledVolumes) // { seaweedfs-master = mkIf cfg.master.enable { wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; description = "SeaweedFS master"; serviceConfig = rec { User = user; Group = group; StateDirectory = "seaweedfs/master"; ExecStart = (mkWeedExec "master" cfg.master) + " -mdir=/var/lib/${StateDirectory}"; KillSignal = "SIGTERM"; }; }; seaweedfs-filer = mkIf cfg.filer.enable { wantedBy = [ "multi-user.target" ]; after = [ "network.target" ] ++ optional cfg.master.enable "seaweedfs-master.service"; description = "SeaweedFS filer"; serviceConfig = rec { User = user; Group = group; WorkingDirectory = "/var/lib/${StateDirectory}"; StateDirectory = "seaweedfs/filer"; ExecStart = mkWeedExec "filer" cfg.filer; KillSignal = "SIGTERM"; }; }; seaweedfs-webdav = mkIf cfg.webdav.enable { wantedBy = [ "multi-user.target" ]; after = [ "network.target" ] ++ optional cfg.filer.enable "seaweedfs-filer.service"; description = "SeaweedFS webdav"; serviceConfig = { User = user; Group = group; ExecStart = mkWeedExec "webdav" cfg.webdav; KillSignal = "SIGTERM"; }; }; }; }; }