{ config, lib, pkgs, ... }: let cfg = config.services.provenance.ui; common = import ./common.nix { inherit lib; }; localAppview = config.services.provenance.appview.enable or false; in { options.services.provenance.ui = { enable = lib.mkEnableOption "the Provenance UI"; package = lib.mkOption { type = lib.types.package; default = pkgs.callPackage ../package.nix { pname = "provenance-ui"; subPackages = [ "cmd/ui" ]; }; defaultText = lib.literalExpression "the Provenance UI package"; description = "Package that provides bin/ui."; }; listenAddress = lib.mkOption { type = lib.types.str; default = "127.0.0.1:8000"; description = "HTTP listen address in host:port form. Use brackets for IPv6 hosts."; }; stateDirectory = common.stateOption "provenance-ui"; dataDirectory = common.dataOption cfg.stateDirectory; externalWorkers = common.externalWorkersOption; logLevel = common.logLevelOption; databaseFile = common.databaseOption "ui.db"; serviceKeyFile = common.secretOption "Absolute runtime path to the appview service key. Keep the file outside the Nix store."; encryptionKeyFile = common.secretOption "Absolute runtime path to the base64-encoded 32-byte encryption key. Keep the file outside the Nix store."; publicOrigin = lib.mkOption { type = lib.types.str; default = "http://127.0.0.1:8000"; example = "https://provenance.example.com"; description = "Browser origin and OAuth callback origin. Use HTTPS except for loopback development."; }; appviewURL = lib.mkOption { type = lib.types.str; default = "http://127.0.0.1:8001"; description = "Appview origin. Use HTTPS for remote appviews or HTTP on loopback."; }; }; config = lib.mkIf cfg.enable ( lib.mkMerge [ (common.dataConfig "ui" cfg.stateDirectory cfg.dataDirectory) { assertions = [ { assertion = common.validSecret cfg.serviceKeyFile; message = "services.provenance.ui.serviceKeyFile must name an absolute runtime file outside the Nix store."; } { assertion = common.validSecret cfg.encryptionKeyFile; message = "services.provenance.ui.encryptionKeyFile must name an absolute runtime file outside the Nix store."; } { assertion = !localAppview || cfg.stateDirectory != config.services.provenance.appview.stateDirectory; message = "The Provenance UI and appview require separate state directories."; } { assertion = !localAppview || cfg.dataDirectory != config.services.provenance.appview.dataDirectory; message = "The Provenance UI and appview require separate data directories."; } ]; systemd.services.provenance-ui = lib.mkMerge [ (common.unit { inherit (cfg) package stateDirectory dataDirectory; binary = "ui"; credentials = { PROVENANCE_SERVICE_KEY = cfg.serviceKeyFile; PROVENANCE_ENCRYPTION_KEY = cfg.encryptionKeyFile; }; environment = { PROVENANCE_UI_ADDR = cfg.listenAddress; PROVENANCE_UI_DB = "${cfg.dataDirectory}/${cfg.databaseFile}"; PROVENANCE_PUBLIC_ORIGIN = cfg.publicOrigin; PROVENANCE_APPVIEW_URL = cfg.appviewURL; PROVENANCE_EXTERNAL_WORKERS = toString cfg.externalWorkers; PROVENANCE_LOG_LEVEL = cfg.logLevel; }; }) (lib.mkIf localAppview { after = [ "provenance-appview.service" ]; }) ]; } ] ); }