diff --git a/nixos/module-list.nix b/nixos/module-list.nix index fadbdec0..af554d46 100644 --- a/nixos/module-list.nix +++ b/nixos/module-list.nix @@ -5,4 +5,5 @@ ./modules/phoebus/alarm-server.nix ./modules/phoebus/local-kafka.nix ./modules/phoebus/olog.nix + ./modules/phoebus/save-and-restore.nix ] diff --git a/nixos/modules/phoebus/alarm-logger.nix b/nixos/modules/phoebus/alarm-logger.nix index 8b39ed52..d8e49444 100644 --- a/nixos/modules/phoebus/alarm-logger.nix +++ b/nixos/modules/phoebus/alarm-logger.nix @@ -173,7 +173,7 @@ in { services.elasticsearch = lib.mkIf localElasticsearch { enable = true; - # Should be kept in sync with the phoebus-olog service + # Should be kept in sync with the phoebus-olog and phoebus-save-and-restore services package = pkgs.elasticsearch7; }; diff --git a/nixos/modules/phoebus/olog.nix b/nixos/modules/phoebus/olog.nix index 7ec9bb16..2b6dbb40 100644 --- a/nixos/modules/phoebus/olog.nix +++ b/nixos/modules/phoebus/olog.nix @@ -116,7 +116,7 @@ in { services.elasticsearch = { enable = true; - # Should be kept in sync with the phoebus-alarm-logger service + # Should be kept in sync with the phoebus-alarm-logger and phoebus-save-and-restore services package = pkgs.elasticsearch7; }; services.mongodb.enable = true; diff --git a/nixos/modules/phoebus/save-and-restore.nix b/nixos/modules/phoebus/save-and-restore.nix new file mode 100644 index 00000000..b518c3e0 --- /dev/null +++ b/nixos/modules/phoebus/save-and-restore.nix @@ -0,0 +1,155 @@ +{ + config, + epnixLib, + lib, + pkgs, + ... +}: let + cfg = config.services.phoebus-save-and-restore; + settingsFormat = pkgs.formats.javaProperties {}; + configFile = settingsFormat.generate "phoebus-save-and-restore.properties" cfg.settings; + + localElasticsearch = cfg.settings."elasticsearch.network.host" == "localhost"; +in { + options.services.phoebus-save-and-restore = { + enable = lib.mkEnableOption '' + the Phoebus Save-and-restore service. + + This service is used by clients + to manage configurations (aka save sets) and snapshots, + to compare snapshots, + and to restore PV values from snapshots. + ''; + + openFirewall = lib.mkOption { + description = '' + Open the firewall for the Phoebus Save-and-restore service. + + Warning: this opens the firewall on all network interfaces. + ''; + type = lib.types.bool; + default = false; + }; + + settings = lib.mkOption { + description = '' + Configuration for the Phoebus Alarm Logger. + + These options will be put into a `.properties` file. + + Note that options containing a "." must be quoted. + + Available options can be seen here: + + ''; + default = {}; + type = lib.types.submodule { + freeformType = settingsFormat.type; + options = { + "server.port" = lib.mkOption { + description = "Port for the Alarm Logger service"; + type = lib.types.port; + default = 8080; + apply = toString; + }; + + "elasticsearch.network.host" = lib.mkOption { + description = '' + Elasticsearch server host + + If `localhost` (the default), + the Elasticsearch service will be automatically set up. + ''; + type = lib.types.str; + default = "localhost"; + }; + + "elasticsearch.http.port" = lib.mkOption { + description = "Elasticsearch server port"; + type = lib.types.port; + default = config.services.elasticsearch.port; + defaultText = lib.literalExpression "config.services.elasticsearch.port"; + apply = toString; + }; + }; + }; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.services.phoebus-save-and-restore = { + description = "Phoebus Save-and-restore"; + + wantedBy = ["multi-user.target"]; + after = lib.mkIf localElasticsearch ["elasticsearch.service"]; + + serviceConfig = { + ExecStart = "${pkgs.epnix.phoebus-save-and-restore}/bin/phoebus-save-and-restore --spring.config.location=file://${configFile}"; + Restart = "on-failure"; + DynamicUser = true; + + # Security options: + # --- + + # NETLINK needed to enumerate available interfaces + RestrictAddressFamilies = ["AF_INET" "AF_INET6"]; + # Service may not create new namespaces + RestrictNamespaces = true; + + # Service does not have access to other users + PrivateUsers = true; + # Service has no access to hardware devices + PrivateDevices = true; + + # Service cannot write to the hardware clock or system clock + ProtectClock = true; + # Service cannot modify the control group file system + ProtectControlGroups = true; + # Service has no access to home directories + ProtectHome = true; + # Service cannot change system host/domainname + ProtectHostname = true; + # Service cannot read from or write to the kernel log ring buffer + ProtectKernelLogs = true; + # Service cannot load or read kernel modules + ProtectKernelModules = true; + # Service cannot alter kernel tunables (/proc/sys, …) + ProtectKernelTunables = true; + # Service has restricted access to process tree (/proc hidepid=) + ProtectProc = "invisible"; + + # Service may not acquire new capabilities + CapabilityBoundingSet = ""; + # Service cannot change ABI personality + LockPersonality = true; + # Service has no access to non-process /proc files (/proc subset=) + ProcSubset = "pid"; + # Service may execute system calls only with native ABI + SystemCallArchitectures = "native"; + # Access write directories + UMask = "0077"; + # Service may create writable executable memory mappings + # This option isn't set due to the JVM marking some memory pages as executable + #MemoryDenyWriteExecute = true; + + # Service can only use a reasonable set of system calls, + # used by common system services + SystemCallFilter = ["@system-service"]; + # Disallowed system calls return EPERM instead of terminating the service + SystemCallErrorNumber = "EPERM"; + }; + }; + + services.elasticsearch = lib.mkIf localElasticsearch { + enable = true; + # Should be kept in sync with the phoebus-alarm-logger and phoebus-olog services + package = pkgs.elasticsearch7; + }; + + networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [ + (lib.toInt cfg.settings."server.port") + ]; + }; + + meta.maintainers = with epnixLib.maintainers; [minijackson]; +}