Loading maintainers/maintainer-list.nix +6 −0 Original line number Diff line number Diff line Loading @@ -16251,6 +16251,12 @@ github = "M0ustach3"; githubId = 37956764; }; m1-s = { email = "michael@m1-s.com"; github = "m1-s"; githubId = 94642227; name = "Michael Schneider"; }; m1cr0man = { email = "lucas+nix@m1cr0man.com"; github = "m1cr0man"; Loading nixos/modules/module-list.nix +1 −0 Original line number Diff line number Diff line Loading @@ -1833,6 +1833,7 @@ ./services/web-servers/traefik.nix ./services/web-servers/trafficserver/default.nix ./services/web-servers/ttyd.nix ./services/web-servers/tusd.nix ./services/web-servers/unit/default.nix ./services/web-servers/uwsgi.nix ./services/web-servers/varnish/default.nix Loading nixos/modules/services/web-servers/tusd.nix 0 → 100644 +162 −0 Original line number Diff line number Diff line { config, lib, pkgs, ... }: let cfg = config.services.tusd; username = "tusd"; groupname = "tusd"; args = [ "-host=${cfg.host}" "-port=${toString cfg.port}" "-base-path=${cfg.basePath}" "-upload-dir=${cfg.uploadDir}" ] ++ lib.optional cfg.behindProxy "-behind-proxy" ++ lib.optional (cfg.maxSize != null) "-max-size=${toString cfg.maxSize}" ++ lib.optional (cfg.networkTimeout != null) "-network-timeout=${cfg.networkTimeout}" ++ lib.optional (cfg.hooksHttp != null) "-hooks-http=${cfg.hooksHttp}" ++ lib.optional ( cfg.hooksEnabledEvents != [ ] ) "-hooks-enabled-events=${lib.concatStringsSep "," cfg.hooksEnabledEvents}" ++ cfg.extraArgs; in { meta.maintainers = with lib.maintainers; [ m1-s ]; options.services.tusd = { enable = lib.mkEnableOption "tus resumable upload protocol server"; host = lib.mkOption { type = lib.types.str; default = "0.0.0.0"; description = "The host to bind the HTTP server to."; }; port = lib.mkOption { type = lib.types.port; default = 8080; description = "The port to bind the HTTP server to."; }; openFirewall = lib.mkOption { type = lib.types.bool; default = false; description = "Whether to open the firewall port for tusd."; }; basePath = lib.mkOption { type = lib.types.str; default = "/files/"; description = "The basepath of the HTTP server."; }; uploadDir = lib.mkOption { type = lib.types.path; default = "/var/lib/tusd/data"; description = "The directory to store uploads in."; }; behindProxy = lib.mkEnableOption null // { description = "Whether to respect X-Forwarded-* and similar headers which may be set by proxies."; }; maxSize = lib.mkOption { type = lib.types.nullOr lib.types.int; default = null; description = "The maximum size of a single upload in bytes."; }; networkTimeout = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; description = '' The timeout for reading the request and writing the response. If tusd does not receive data for this duration, it will consider the connection dead. ''; example = "30s"; }; hooksHttp = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; description = "The HTTP endpoint to which hook events will be sent to."; example = "http://localhost:8081/hooks"; }; hooksEnabledEvents = lib.mkOption { type = lib.types.listOf lib.types.str; default = [ ]; description = "The list of enabled hook events."; example = [ "pre-create" "post-finish" ]; }; extraArgs = lib.mkOption { type = lib.types.listOf lib.types.str; default = [ ]; description = "Additional arguments given to tusd."; example = [ "-verbose" "-log-format=json" ]; }; }; config = lib.mkIf cfg.enable { users.users.${username} = { isSystemUser = true; group = groupname; }; users.groups.${groupname} = { }; # tusd knows how to create subdirectories in this folder but we have to # create the root folder ourselves. systemd.tmpfiles.settings."tusd".${cfg.uploadDir}.d = { user = username; group = groupname; # default taken from https://github.com/tus/tusd/blob/55a096a10942b85360664a1e8aea7bd758272053/pkg/filestore/filestore.go#L37 mode = "0775"; }; systemd.services.tusd = { description = "tusd - tus resumable upload protocol server"; documentation = [ "https://github.com/tus/tusd" ]; wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; serviceConfig = { User = username; Group = groupname; ExecStart = lib.escapeShellArgs ([ (lib.getExe pkgs.tusd) ] ++ args); Restart = "on-failure"; StateDirectory = "tusd"; # Hardening LockPersonality = true; ProtectClock = true; ProtectControlGroups = true; ProtectHostUserNamespaces = true; ProtectKernelLogs = true; ProtectKernelModules = true; ProtectKernelTunables = true; ProtectProc = "invisible"; RestrictNamespaces = true; RestrictRealtime = true; RestrictSUIDSGID = true; }; }; networking.firewall.allowedTCPPorts = lib.optional cfg.openFirewall cfg.port; }; } nixos/tests/tusd/default.nix +16 −22 Original line number Diff line number Diff line Loading @@ -2,37 +2,28 @@ let port = 1080; client = { pkgs, ... }: { environment.systemPackages = [ pkgs.curl ]; }; server = { pkgs, ... }: { # tusd does not have a NixOS service yet. systemd.services.tusd = { wantedBy = [ "multi-user.target" ]; serviceConfig = { ExecStart = ''${pkgs.tusd}/bin/tusd -port "${toString port}" -upload-dir=/data''; }; }; networking.firewall.allowedTCPPorts = [ port ]; }; uploadDir = "/var/lib/tusd/data"; in { name = "tusd"; meta.maintainers = with lib.maintainers; [ m1-s nh2 kalbasit ]; nodes = { inherit server; inherit client; client = { environment.systemPackages = [ pkgs.curl ]; }; server = { services.tusd = { enable = true; inherit port uploadDir; openFirewall = true; }; }; }; testScript = '' Loading @@ -46,6 +37,9 @@ in client.wait_for_unit("network.target") client.succeed("${./tus-curl-upload.sh} file-100M.bin http://server:${toString port}/files/") # Verify file was created in uploadDir server.succeed("test -n \"$(ls -A ${uploadDir})\"") print("Upload succeeded") ''; } pkgs/by-name/tu/tusd/package.nix +1 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ buildGoModule (finalAttrs: { description = "Reference server implementation in Go of tus: the open protocol for resumable file uploads"; license = lib.licenses.mit; homepage = "https://tus.io/"; mainProgram = "tusd"; maintainers = with lib.maintainers; [ nh2 kalbasit Loading Loading
maintainers/maintainer-list.nix +6 −0 Original line number Diff line number Diff line Loading @@ -16251,6 +16251,12 @@ github = "M0ustach3"; githubId = 37956764; }; m1-s = { email = "michael@m1-s.com"; github = "m1-s"; githubId = 94642227; name = "Michael Schneider"; }; m1cr0man = { email = "lucas+nix@m1cr0man.com"; github = "m1cr0man"; Loading
nixos/modules/module-list.nix +1 −0 Original line number Diff line number Diff line Loading @@ -1833,6 +1833,7 @@ ./services/web-servers/traefik.nix ./services/web-servers/trafficserver/default.nix ./services/web-servers/ttyd.nix ./services/web-servers/tusd.nix ./services/web-servers/unit/default.nix ./services/web-servers/uwsgi.nix ./services/web-servers/varnish/default.nix Loading
nixos/modules/services/web-servers/tusd.nix 0 → 100644 +162 −0 Original line number Diff line number Diff line { config, lib, pkgs, ... }: let cfg = config.services.tusd; username = "tusd"; groupname = "tusd"; args = [ "-host=${cfg.host}" "-port=${toString cfg.port}" "-base-path=${cfg.basePath}" "-upload-dir=${cfg.uploadDir}" ] ++ lib.optional cfg.behindProxy "-behind-proxy" ++ lib.optional (cfg.maxSize != null) "-max-size=${toString cfg.maxSize}" ++ lib.optional (cfg.networkTimeout != null) "-network-timeout=${cfg.networkTimeout}" ++ lib.optional (cfg.hooksHttp != null) "-hooks-http=${cfg.hooksHttp}" ++ lib.optional ( cfg.hooksEnabledEvents != [ ] ) "-hooks-enabled-events=${lib.concatStringsSep "," cfg.hooksEnabledEvents}" ++ cfg.extraArgs; in { meta.maintainers = with lib.maintainers; [ m1-s ]; options.services.tusd = { enable = lib.mkEnableOption "tus resumable upload protocol server"; host = lib.mkOption { type = lib.types.str; default = "0.0.0.0"; description = "The host to bind the HTTP server to."; }; port = lib.mkOption { type = lib.types.port; default = 8080; description = "The port to bind the HTTP server to."; }; openFirewall = lib.mkOption { type = lib.types.bool; default = false; description = "Whether to open the firewall port for tusd."; }; basePath = lib.mkOption { type = lib.types.str; default = "/files/"; description = "The basepath of the HTTP server."; }; uploadDir = lib.mkOption { type = lib.types.path; default = "/var/lib/tusd/data"; description = "The directory to store uploads in."; }; behindProxy = lib.mkEnableOption null // { description = "Whether to respect X-Forwarded-* and similar headers which may be set by proxies."; }; maxSize = lib.mkOption { type = lib.types.nullOr lib.types.int; default = null; description = "The maximum size of a single upload in bytes."; }; networkTimeout = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; description = '' The timeout for reading the request and writing the response. If tusd does not receive data for this duration, it will consider the connection dead. ''; example = "30s"; }; hooksHttp = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; description = "The HTTP endpoint to which hook events will be sent to."; example = "http://localhost:8081/hooks"; }; hooksEnabledEvents = lib.mkOption { type = lib.types.listOf lib.types.str; default = [ ]; description = "The list of enabled hook events."; example = [ "pre-create" "post-finish" ]; }; extraArgs = lib.mkOption { type = lib.types.listOf lib.types.str; default = [ ]; description = "Additional arguments given to tusd."; example = [ "-verbose" "-log-format=json" ]; }; }; config = lib.mkIf cfg.enable { users.users.${username} = { isSystemUser = true; group = groupname; }; users.groups.${groupname} = { }; # tusd knows how to create subdirectories in this folder but we have to # create the root folder ourselves. systemd.tmpfiles.settings."tusd".${cfg.uploadDir}.d = { user = username; group = groupname; # default taken from https://github.com/tus/tusd/blob/55a096a10942b85360664a1e8aea7bd758272053/pkg/filestore/filestore.go#L37 mode = "0775"; }; systemd.services.tusd = { description = "tusd - tus resumable upload protocol server"; documentation = [ "https://github.com/tus/tusd" ]; wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; serviceConfig = { User = username; Group = groupname; ExecStart = lib.escapeShellArgs ([ (lib.getExe pkgs.tusd) ] ++ args); Restart = "on-failure"; StateDirectory = "tusd"; # Hardening LockPersonality = true; ProtectClock = true; ProtectControlGroups = true; ProtectHostUserNamespaces = true; ProtectKernelLogs = true; ProtectKernelModules = true; ProtectKernelTunables = true; ProtectProc = "invisible"; RestrictNamespaces = true; RestrictRealtime = true; RestrictSUIDSGID = true; }; }; networking.firewall.allowedTCPPorts = lib.optional cfg.openFirewall cfg.port; }; }
nixos/tests/tusd/default.nix +16 −22 Original line number Diff line number Diff line Loading @@ -2,37 +2,28 @@ let port = 1080; client = { pkgs, ... }: { environment.systemPackages = [ pkgs.curl ]; }; server = { pkgs, ... }: { # tusd does not have a NixOS service yet. systemd.services.tusd = { wantedBy = [ "multi-user.target" ]; serviceConfig = { ExecStart = ''${pkgs.tusd}/bin/tusd -port "${toString port}" -upload-dir=/data''; }; }; networking.firewall.allowedTCPPorts = [ port ]; }; uploadDir = "/var/lib/tusd/data"; in { name = "tusd"; meta.maintainers = with lib.maintainers; [ m1-s nh2 kalbasit ]; nodes = { inherit server; inherit client; client = { environment.systemPackages = [ pkgs.curl ]; }; server = { services.tusd = { enable = true; inherit port uploadDir; openFirewall = true; }; }; }; testScript = '' Loading @@ -46,6 +37,9 @@ in client.wait_for_unit("network.target") client.succeed("${./tus-curl-upload.sh} file-100M.bin http://server:${toString port}/files/") # Verify file was created in uploadDir server.succeed("test -n \"$(ls -A ${uploadDir})\"") print("Upload succeeded") ''; }
pkgs/by-name/tu/tusd/package.nix +1 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ buildGoModule (finalAttrs: { description = "Reference server implementation in Go of tus: the open protocol for resumable file uploads"; license = lib.licenses.mit; homepage = "https://tus.io/"; mainProgram = "tusd"; maintainers = with lib.maintainers; [ nh2 kalbasit Loading