diff --git a/flake.nix b/flake.nix index efb16d0..e8d3354 100644 --- a/flake.nix +++ b/flake.nix @@ -47,11 +47,11 @@ syndicate-py = python3Packages.syndicate; }) self.legacyPackages; + nixosModules.default = self.nixosModules.syndicate-server; nixosModules.syndicate-server = # A little hack to apply our overlay to this module only. - let f = import ./nixos/syndicate-server.nix; - in { config, lib, pkgs, ... }: - f { + { config, lib, pkgs, ... }: + (import ./nixos/syndicate-server.nix) { inherit config lib; pkgs = pkgs.extend self.overlays.default; }; diff --git a/nixos/syndicate-server.nix b/nixos/syndicate-server.nix index 6668093..850be4a 100644 --- a/nixos/syndicate-server.nix +++ b/nixos/syndicate-server.nix @@ -2,70 +2,95 @@ with lib; { - options.services.syndicate-server = { - enable = mkEnableOption "the Syndicate dataspace server"; - - group = mkOption { - type = types.str; - default = "wheel"; - example = "users"; - description = "Group account under which the Syndicate server runs."; - }; - - package = mkOption { - default = pkgs.syndicate-server; - defaultText = "pkgs.syndicate-server"; - type = types.package; - description = "The package to use for the Syndicate dataspace server."; - }; - - tcpListeners = mkOption { - default = [ ]; - example = [{ - address = "0.0.0.0"; - port = 8001; - }]; - type = with types; - listOf (submodule { - options = { - address = mkOption { type = str; }; - port = mkOption { type = port; }; - }; - }); - description = "TCP ports to listen for connections on."; - }; - - unixListeners = mkOption { - default = [ "/run/syndicate/ds" ]; - type = types.listOf types.path; - description = "Sockets to listen for connections on."; - }; - - }; - - config = let cfg = config.services.syndicate-server; - in mkIf cfg.enable { - - assertions = [{ - assertion = cfg.tcpListeners == [ ]; - message = - "tcpListeners configuration not implemented for Syndicate server"; - }]; - - systemd.services.syndicate-server = { - description = "Syndicate dataspace server"; - wantedBy = [ "multi-user.target" ]; - serviceConfig = { - ExecStart = "${cfg.package}/bin/syndicate-server --no-banner ${ - lib.strings.concatMapStrings (l: " --socket ${l}") cfg.unixListeners - }"; - Group = cfg.group; - AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ]; - DynamicUser = true; - Restart = "always"; - RuntimeDirectory = "syndicate"; + options.services.syndicate = mkOption { + default = { }; + example = { + tty1 = { + enable = true; + user = "jane"; + config = [ "/etc/syndicate" ]; }; }; + description = '' + Syndicate dataspace server instances. + If the key is in the form of "tty''${N}" it will + be attached to the appropriate teletypwriter. + ''; + type = types.attrsOf (types.submodule { + options = { + enable = mkEnableOption "this Syndicate dataspace server instance"; + + user = mkOption { + type = types.str; + example = "jane"; + description = "User account under which the Syndicate server runs."; + }; + + package = mkOption { + default = pkgs.syndicate-server; + defaultText = "pkgs.syndicate-server"; + type = types.package; + description = + "The package to use for the Syndicate dataspace server."; + }; + + config = mkOption { + type = types.listOf types.path; + description = "Configurations to load."; + example = [ "/etc/syndicate" ]; + }; + + }; + }); + }; + + config = { + + systemd.services = lib.attrsets.mapAttrs' (name: cfg: { + name = "syndicate-${name}"; + value = let + flags = lib.strings.concatMapStrings (c: " --config ${c}") cfg.config; + serviceConfig = { + ExecStart = + "${cfg.package}/bin/syndicate-server --no-banner ${flags}"; + User = cfg.user; + }; + in if builtins.match "tty[0-9]" name != null then { + description = "Syndicate dataspace server"; + after = [ + "systemd-user-sessions.service" + "systemd-logind.service" + "getty@${name}.service" + ]; + before = [ "graphical.target" ]; + wants = [ "dbus.socket" "systemd-logind.service" ]; + wantedBy = [ "graphical.target" ]; + conflicts = [ "getty@${name}.service" ]; + + restartIfChanged = false; + unitConfig.ConditionPathExists = "/dev/${name}"; + + serviceConfig = serviceConfig // { + PAMName = "login"; + StandardError = "journal"; + StandardInput = "tty-fail"; + StandardOutput = "journal"; + TTYPath = "/dev/${name}"; + TTYReset = "yes"; + TTYVHangup = "yes"; + TTYVTDisallocate = "yes"; + UtmpIdentifier = "%n"; + UtmpMode = "user"; + WorkingDirectory = "~"; + }; + } else { + description = "Syndicate dataspace server"; + wantedBy = [ "multi-user.target" ]; + inherit serviceConfig; + }; + }) + (lib.attrsets.filterAttrs (_: cfg: cfg.enable) config.services.syndicate); }; + }