diff --git a/nixos/doc/manual/release-notes/rl-2411.section.md b/nixos/doc/manual/release-notes/rl-2411.section.md index 000df6e978b445..fc46f6b53e66e5 100644 --- a/nixos/doc/manual/release-notes/rl-2411.section.md +++ b/nixos/doc/manual/release-notes/rl-2411.section.md @@ -87,6 +87,8 @@ - [Goatcounter](https://www.goatcounter.com/), an easy web analytics platform with no tracking of personal data. Available as [services.goatcounter](options.html#opt-services.goatcocunter.enable). +- [Porn-Vault](https://gitlab.com/porn-vault/porn-vault), a porn organizing web app. Available as [services.porn-vault](#opt-services.porn-vault.enable). + - [Privatebin](https://github.com/PrivateBin/PrivateBin/), a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Available as [services.privatebin](#opt-services.privatebin.enable). - [UWSM](https://github.com/Vladimir-csp/uwsm), a wayland session manager to wrap Wayland compositors into useful systemd units such as `graphical-session.target`. Available as [programs.uwsm](#opt-programs.uwsm.enable). diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index eef106a91229c1..a2539742305630 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -1494,6 +1494,7 @@ ./services/web-apps/pingvin-share.nix ./services/web-apps/plantuml-server.nix ./services/web-apps/plausible.nix + ./services/web-apps/porn-vault.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.nix b/nixos/modules/services/web-apps/porn-vault.nix new file mode 100644 index 00000000000000..03dfc199984af8 --- /dev/null +++ b/nixos/modules/services/web-apps/porn-vault.nix @@ -0,0 +1,264 @@ +{ config, pkgs, lib, ... }: + +let + cfg = config.services.porn-vault; + configFormat = pkgs.formats.json { }; + inherit (lib) + mkIf + mkEnableOption + mkPackageOption + mkOption + getExe + 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 = false; + 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 default ports in the firewall for porn-vault. + ''; + }; + + config = { + enable = mkEnableOption "Porn-Vault configuration"; + 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 = { + 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; + }; + }; + }; + }; + }; + }; + }; + + 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); + # 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 = 0; + }; + wantedBy = mkIf cfg.autoStart [ "multi-user.target" ]; + }; + }; + }; + + environment.etc = mkIf cfg.config.enable { + "porn-vault/config.json".source = configFormat.generate "config.json" cfg.config.settings; + }; + + networking.firewall = lib.mkIf cfg.openFirewall { + allowedTCPPorts = [ cfg.port ]; + allowedUDPPorts = [ cfg.port ]; + }; + }; + + meta.maintainers = with lib.maintainers; [ luNeder ]; +} \ No newline at end of file