{ config, lib, pkgs, ... }: let cfg = config.services.openvscode-server; defaultUser = "openvscode-server"; defaultGroup = defaultUser; in { options = { services.openvscode-server = { enable = lib.mkEnableOption (lib.mdDoc "openvscode-server"); package = lib.mkPackageOption pkgs "openvscode-server" { }; extraPackages = lib.mkOption { default = [ ]; description = lib.mdDoc '' Additional packages to add to the openvscode-server {env}`PATH`. ''; example = lib.literalExpression "[ pkgs.go ]"; type = lib.types.listOf lib.types.package; }; extraEnvironment = lib.mkOption { type = lib.types.attrsOf lib.types.str; description = lib.mdDoc '' Additional environment variables to pass to openvscode-server. ''; default = { }; example = { PKG_CONFIG_PATH = "/run/current-system/sw/lib/pkgconfig"; }; }; extraArguments = lib.mkOption { default = [ ]; description = lib.mdDoc '' Additional arguments to pass to openvscode-server. ''; example = lib.literalExpression ''[ "--log=info" ]''; type = lib.types.listOf lib.types.str; }; host = lib.mkOption { default = "localhost"; description = lib.mdDoc '' The host name or IP address the server should listen to. ''; type = lib.types.str; }; port = lib.mkOption { default = 3000; description = lib.mdDoc '' The port the server should listen to. If 0 is passed a random free port is picked. If a range in the format num-num is passed, a free port from the range (end inclusive) is selected. ''; type = lib.types.port; }; user = lib.mkOption { default = defaultUser; example = "yourUser"; description = lib.mdDoc '' The user to run openvscode-server as. By default, a user named `${defaultUser}` will be created. ''; type = lib.types.str; }; group = lib.mkOption { default = defaultGroup; example = "yourGroup"; description = lib.mdDoc '' The group to run openvscode-server under. By default, a group named `${defaultGroup}` will be created. ''; type = lib.types.str; }; extraGroups = lib.mkOption { default = [ ]; description = lib.mdDoc '' An array of additional groups for the `${defaultUser}` user. ''; example = [ "docker" ]; type = lib.types.listOf lib.types.str; }; withoutConnectionToken = lib.mkOption { default = false; description = lib.mdDoc '' Run without a connection token. Only use this if the connection is secured by other means. ''; example = true; type = lib.types.bool; }; socketPath = lib.mkOption { default = null; example = "/run/openvscode/socket"; description = lib.mdDoc '' The path to a socket file for the server to listen to. ''; type = lib.types.nullOr lib.types.str; }; userDataDir = lib.mkOption { default = null; description = lib.mdDoc '' Specifies the directory that user data is kept in. Can be used to open multiple distinct instances of Code. ''; type = lib.types.nullOr lib.types.str; }; serverDataDir = lib.mkOption { default = null; description = lib.mdDoc '' Specifies the directory that server data is kept in. ''; type = lib.types.nullOr lib.types.str; }; extensionsDir = lib.mkOption { default = null; description = lib.mdDoc '' Set the root path for extensions. ''; type = lib.types.nullOr lib.types.str; }; telemetryLevel = lib.mkOption { default = null; example = "crash"; description = lib.mdDoc '' Sets the initial telemetry level. Valid levels are: 'off', 'crash', 'error' and 'all'. ''; type = lib.types.nullOr (lib.types.enum [ "off" "crash" "error" "all" ]); }; connectionToken = lib.mkOption { default = null; example = "secret-token"; description = lib.mdDoc '' A secret that must be included with all requests. ''; type = lib.types.nullOr lib.types.str; }; connectionTokenFile = lib.mkOption { default = null; description = lib.mdDoc '' Path to a file that contains the connection token. ''; type = lib.types.nullOr lib.types.str; }; }; }; config = lib.mkIf cfg.enable { systemd.services.openvscode-server = { description = "OpenVSCode server"; wantedBy = [ "multi-user.target" ]; wants = [ "network-online.target" ]; after = [ "network-online.target" ]; path = cfg.extraPackages; environment = cfg.extraEnvironment; serviceConfig = { ExecStart = '' ${lib.getExe cfg.package} \ --accept-server-license-terms \ --host=${cfg.host} \ --port=${toString cfg.port} \ '' + lib.optionalString (cfg.telemetryLevel != null) '' --telemetry-level=${cfg.telemetryLevel} \ '' + lib.optionalString (cfg.withoutConnectionToken) '' --without-connection-token \ '' + lib.optionalString (cfg.socketPath != null) '' --socket-path=${cfg.socketPath} \ '' + lib.optionalString (cfg.userDataDir != null) '' --user-data-dir=${cfg.userDataDir} \ '' + lib.optionalString (cfg.serverDataDir != null) '' --server-data-dir=${cfg.serverDataDir} \ '' + lib.optionalString (cfg.extensionsDir != null) '' --extensions-dir=${cfg.extensionsDir} \ '' + lib.optionalString (cfg.connectionToken != null) '' --connection-token=${cfg.connectionToken} \ '' + lib.optionalString (cfg.connectionTokenFile != null) '' --connection-token-file=${cfg.connectionTokenFile} \ '' + lib.escapeShellArgs cfg.extraArguments; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; RuntimeDirectory = cfg.user; User = cfg.user; Group = cfg.group; Restart = "on-failure"; }; }; users.users."${cfg.user}" = lib.mkMerge [ (lib.mkIf (cfg.user == defaultUser) { isNormalUser = true; description = "openvscode-server user"; inherit (cfg) group; }) { packages = cfg.extraPackages; inherit (cfg) extraGroups; } ]; users.groups."${defaultGroup}" = lib.mkIf (cfg.group == defaultGroup) { }; }; meta.maintainers = [ lib.maintainers.drupol ]; }