diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index ae183ca985cc..a0aa1c5cb62a 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -1500,6 +1500,7 @@ ./services/web-apps/pingvin-share.nix ./services/web-apps/plantuml-server.nix ./services/web-apps/plausible.nix + ./services/web-apps/porn-vault/default.nix ./services/web-apps/powerdns-admin.nix ./services/web-apps/pretalx.nix ./services/web-apps/pretix.nix diff --git a/nixos/modules/services/web-apps/porn-vault/default-config.nix b/nixos/modules/services/web-apps/porn-vault/default-config.nix new file mode 100644 index 000000000000..a3872c7cf5c7 --- /dev/null +++ b/nixos/modules/services/web-apps/porn-vault/default-config.nix @@ -0,0 +1,158 @@ +# See https://gitlab.com/porn-vault/porn-vault/-/blob/dev/config.example.json +{ + auth = { + password = null; + }; + binaries = { + ffmpeg = "ffmpeg"; + ffprobe = "ffprobe"; + izzyPort = 8000; + imagemagick = { + convertPath = "convert"; + montagePath = "montage"; + identifyPath = "identify"; + }; + }; + import = { + images = [ + { + path = "/media/porn-vault/images"; + include = [ ]; + exclude = [ ]; + extensions = [ + ".jpg" + ".jpeg" + ".png" + ".gif" + ]; + enable = true; + } + ]; + videos = [ + { + path = "/media/porn-vault/videos"; + include = [ ]; + exclude = [ ]; + extensions = [ + ".mp4" + ".mov" + ".webm" + ]; + enable = true; + } + ]; + scanInterval = 10800000; + }; + log = { + level = "debug"; + maxSize = "20m"; + maxFiles = "5"; + writeFile = [ + { + level = "debug"; + prefix = "errors-"; + silent = false; + } + ]; + }; + matching = { + applyActorLabels = [ + "event:actor:create" + "event:actor:find-unmatched-scenes" + "plugin:actor:create" + "event:scene:create" + "plugin:scene:create" + "event:image:create" + "plugin:marker:create" + "event:marker:create" + ]; + applySceneLabels = true; + applyStudioLabels = [ + "event:studio:create" + "event:studio:find-unmatched-scenes" + "plugin:studio:create" + "event:scene:create" + "plugin:scene:create" + ]; + extractSceneActorsFromFilepath = true; + extractSceneLabelsFromFilepath = true; + extractSceneMoviesFromFilepath = true; + extractSceneStudiosFromFilepath = true; + matcher = { + type = "word"; + options = { + ignoreSingleNames = false; + ignoreDiacritics = true; + enableWordGroups = true; + wordSeparatorFallback = true; + camelCaseWordGroups = true; + overlappingMatchPreference = "longest"; + groupSeparators = [ + "[\\s',()[\\]{}*\\.]" + ]; + wordSeparators = [ + "[-_]" + ]; + filepathSeparators = [ + "[/\\\\&]" + ]; + }; + }; + matchCreatedActors = true; + matchCreatedStudios = true; + matchCreatedLabels = true; + }; + persistence = { + backup = { + enable = true; + maxAmount = 10; + }; + libraryPath = "/media/porn-vault/lib"; + }; + plugins = { + allowActorThumbnailOverwrite = false; + allowMovieThumbnailOverwrite = false; + allowSceneThumbnailOverwrite = false; + allowStudioThumbnailOverwrite = false; + createMissingActors = false; + createMissingLabels = false; + createMissingMovies = false; + createMissingStudios = false; + events = { + actorCreated = [ ]; + actorCustom = [ ]; + sceneCreated = [ ]; + sceneCustom = [ ]; + movieCustom = [ ]; + studioCreated = [ ]; + studioCustom = [ ]; + }; + register = { }; + markerDeduplicationThreshold = 5; + }; + processing = { + generatePreviews = true; + readImagesOnImport = false; + generateImageThumbnails = true; + }; + server = { + https = { + certificate = ""; + enable = false; + key = ""; + }; + }; + transcode = { + hwaDriver = null; + vaapiDevice = "/dev/dri/renderD128"; + h264 = { + preset = "veryfast"; + crf = 23; + }; + webm = { + deadline = "realtime"; + cpuUsed = 3; + crf = 31; + }; + }; +} diff --git a/nixos/modules/services/web-apps/porn-vault/default.nix b/nixos/modules/services/web-apps/porn-vault/default.nix new file mode 100644 index 000000000000..56978dc8c0f0 --- /dev/null +++ b/nixos/modules/services/web-apps/porn-vault/default.nix @@ -0,0 +1,110 @@ +{ + config, + pkgs, + lib, + ... +}: + +let + cfg = config.services.porn-vault; + configFormat = pkgs.formats.json { }; + defaultConfig = import ./default-config.nix; + inherit (lib) + mkIf + mkEnableOption + mkPackageOption + mkOption + getExe + literalExpression + types + ; +in +{ + options = { + services.porn-vault = { + enable = lib.mkEnableOption "Porn-Vault"; + + package = lib.mkPackageOption pkgs "porn-vault" { }; + + autoStart = lib.mkOption { + type = lib.types.bool; + default = true; + description = '' + Whether to start porn-vault automatically. + ''; + }; + + port = lib.mkOption { + type = lib.types.port; + default = 3000; + description = '' + Which port Porn-Vault will use. + ''; + }; + + openFirewall = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Whether to open the Porn-Vault port in the firewall. + ''; + }; + + settings = mkOption { + type = configFormat.type; + description = '' + Configuration for Porn-Vault. The attributes are serialized to JSON in config.json. + + See https://gitlab.com/porn-vault/porn-vault/-/blob/dev/config.example.json + ''; + default = defaultConfig; + apply = lib.recursiveUpdate defaultConfig; + }; + }; + }; + + config = lib.mkIf cfg.enable { + environment.systemPackages = [ cfg.package ]; + + systemd.services.porn-vault = { + description = "Porn-Vault server"; + environment = { + PV_CONFIG_FOLDER = "/etc/porn-vault"; + NODE_ENV = "production"; + DATABASE_NAME = "production"; + PORT = toString cfg.port; + }; + serviceConfig = { + ExecStart = getExe cfg.package; + CacheDirectory = "porn-vault"; + # Hardening options + CapabilityBoundingSet = [ "CAP_SYS_NICE" ]; + AmbientCapabilities = [ "CAP_SYS_NICE" ]; + LockPersonality = true; + NoNewPrivileges = true; + PrivateTmp = true; + ProtectControlGroups = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectSystem = true; + RestrictNamespaces = true; + RestrictSUIDSGID = true; + Restart = "on-failure"; + RestartSec = 5; + }; + wantedBy = mkIf cfg.autoStart [ "multi-user.target" ]; + wants = [ "network.target" ]; + }; + + environment.etc = { + "porn-vault/config.json".source = configFormat.generate "config.json" cfg.settings; + }; + + networking.firewall = lib.mkIf cfg.openFirewall { + allowedTCPPorts = [ cfg.port ]; + }; + }; + + meta.maintainers = [ lib.maintainers.luNeder ]; +}