diff --git a/nixos/doc/manual/release-notes/rl-2305.section.md b/nixos/doc/manual/release-notes/rl-2305.section.md index c81cbc69f94..abaefac66e3 100644 --- a/nixos/doc/manual/release-notes/rl-2305.section.md +++ b/nixos/doc/manual/release-notes/rl-2305.section.md @@ -32,6 +32,8 @@ In addition to numerous new and upgraded packages, this release has the followin - [stevenblack-blocklist](https://github.com/StevenBlack/hosts), A unified hosts file with base extensions for blocking unwanted websites. Available as [networking.stevenblack](options.html#opt-networking.stevenblack.enable). +- [imaginary](https://github.com/h2non/imaginary), a microservice for high-level image processing that Nextcloud can use to generate previews. Available as [services.imaginary](#opt-services.imaginary.enable). + - [goeland](https://github.com/slurdge/goeland), an alternative to rss2email written in golang with many filters. Available as [services.goeland](#opt-services.goeland.enable). - [atuin](https://github.com/ellie/atuin), a sync server for shell history. Available as [services.atuin](#opt-services.atuin.enable). diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 752c0213f05..74651efc0c5 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -860,6 +860,7 @@ ./services/networking/i2pd.nix ./services/networking/icecream/daemon.nix ./services/networking/icecream/scheduler.nix + ./services/networking/imaginary.nix ./services/networking/inspircd.nix ./services/networking/iodine.nix ./services/networking/iperf3.nix diff --git a/nixos/modules/services/networking/imaginary.nix b/nixos/modules/services/networking/imaginary.nix new file mode 100644 index 00000000000..5437da57277 --- /dev/null +++ b/nixos/modules/services/networking/imaginary.nix @@ -0,0 +1,110 @@ +{ lib, config, pkgs, utils, ... }: + +let + inherit (lib) mdDoc mkEnableOption mkIf mkOption types; + + cfg = config.services.imaginary; +in { + options.services.imaginary = { + enable = mkEnableOption (mdDoc "imaginary image processing microservice"); + + address = mkOption { + type = types.str; + default = ""; + description = mdDoc "Bind address. Corresponds to the `-a` flag."; + example = "localhost"; + }; + + port = mkOption { + type = types.port; + default = 8088; + description = mdDoc "Bind port. Corresponds to the `-p` flag."; + }; + + settings = mkOption { + description = mdDoc '' + Command line arguments passed to the imaginary executable, stripped of + the prefix `-`. See upstream's + [README](https://github.com/h2non/imaginary#command-line-usage) for all + options. + ''; + type = types.submodule { + freeformType = with types; attrsOf (oneOf [ + bool + int + (nonEmptyListOf str) + str + ]); + + options = { + return-size = mkOption { + type = types.bool; + default = false; + description = mdDoc "Return the image size in the HTTP headers."; + }; + }; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ { + assertion = ! lib.hasAttr "a" cfg.settings; + message = "Use services.imaginary.address to specify the -a flag."; + } { + assertion = ! lib.hasAttr "p" cfg.settings; + message = "Use services.imaginary.port to specify the -p flag."; + } ]; + + systemd.services.imaginary = { + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = rec { + ExecStart = let + args = lib.mapAttrsToList (key: val: + "-" + key + "=" + lib.concatStringsSep "," (map toString (lib.toList val)) + ) (cfg.settings // { a = cfg.address; p = cfg.port; }); + in "${pkgs.imaginary}/bin/imaginary ${utils.escapeSystemdExecArgs args}"; + ProtectProc = "invisible"; + BindReadOnlyPaths = lib.optional (cfg.settings ? mount) cfg.settings.mount; + CapabilityBoundingSet = if cfg.port < 1024 then + [ "CAP_NET_BIND_SERVICE" ] + else + [ "" ]; + AmbientCapabilities = CapabilityBoundingSet; + NoNewPrivileges = true; + DynamicUser = true; + ProtectSystem = "strict"; + ProtectHome = true; + TemporaryFileSystem = [ "/:ro" ]; + PrivateTmp = true; + PrivateDevices = true; + PrivateUsers = cfg.port >= 1024; + ProtectHostname = true; + ProtectClock = true; + ProtectKernelTunables = true; + ProtectKernelModules = true; + ProtectKernelLogs = true; + ProtectControlGroups = true; + RestrictAddressFamilies = [ + "AF_INET" + "AF_INET6" + ]; + RestrictNamespaces = true; + LockPersonality = true; + MemoryDenyWriteExecute = true; + RestrictRealtime = true; + PrivateMounts = true; + SystemCallFilter = [ + "@system-service" + "~@privileged" + ]; + DevicePolicy = "closed"; + }; + }; + }; + + meta = { + maintainers = with lib.maintainers; [ dotlambda ]; + }; +}