Skip to content

Service commands

Commands that run and install the server roles. Writing a first configuration from flags is gdsgate setup. Global flags are in the CLI hub.

gdsgate proxy

Run the Proxy: public listener, internal reverse-tunnel listener, WebSocket fallback listener and an Authority pool. Preserve its enrolled identity directory across restarts. Live sessions belong to their Proxy process and do not migrate when it stops; see Proxy HA.

Reads: [endpoints], [enroll], [proxy].

TOKEN_FILE="<proxy-enrollment-token-file>"
GDSGATE_ENROLL_TOKEN="$(<"$TOKEN_FILE")" \
    gdsgate --config proxy.toml proxy

The Proxy registers on first start, consuming the token, persists its identity to [enroll].state_dir, and on subsequent starts reuses the persisted identity. With no [enroll].endpoint, the Proxy runs plaintext, for dev and loopback only.

gdsgate proxy init --domain <name>

Write the configuration a Proxy is started from. Writes a file and starts nothing; enrolling the node is gdsgate join.

Writes: [endpoints], [proxy], [telemetry]. Composed by setup prepare it also writes [enroll] and, where the deployment named one, [oidc].

gdsgate proxy init --domain gate.example.com \
    --tls-cert /etc/letsencrypt/live/gate.example.com/fullchain.pem \
    --tls-key /etc/letsencrypt/live/gate.example.com/privkey.pem \
    --output /etc/gdsgate/proxy.toml
Flag Default Meaning
--domain <name> required The name clients dial. The certificate has to carry it.
--listen <addr> 0.0.0.0:50061 Client-facing bind. A port below 1024 is accepted with a condition in the plan: the shipped systemd unit cannot bind it. Put a front or an nftables redirect ahead of it.
--authority <addr> 127.0.0.1:50051 Where Authority answers.
--authority-enroll <addr> 127.0.0.1:50050 Where Authority answers registration; the relay forwards a joining node's first exchange there. Written only with --join-relay. The plan names it as a condition when left at the default.
--join-relay off Bind proxy_join, for nodes whose only route to the control plane is this gateway.
--tls-cert, --tls-key unset What the client-facing listener presents.
--output <path> /etc/gdsgate/proxy.toml Where the configuration goes.
--save <dir>, --node <name> unset Write a bundle for another machine; nothing on this machine changes.
--approve-plan <digest> unset Refuse unless the plan is the one that digest names.
--dry-run, --json off Show the plan; print it as JSON.

proxy_internal (0.0.0.0:50062) and proxy_ws (0.0.0.0:50063) are always written. proxy_join is bound only with --join-relay; it accepts callers that have not authenticated, and the plan says so. With it comes authority_enroll, the address the relay forwards registration to. If Authority's ports were moved and this address was left at the default, a joining node is told its token is unknown.

An existing file is refused; change it with setup change. Exit codes are the setup contract.

gdsgate connector

Run the Connector: dials the Proxy's reverse-tunnel listener, registers the resources declared in [[connector.backends]], and serves them.

Reads: [endpoints], [enroll], [connector].

TOKEN_FILE="<connector-enrollment-token-file>"
GDSGATE_ENROLL_TOKEN="$(<"$TOKEN_FILE")" \
    gdsgate --config connector.toml connector

For any SSH backend, of either model, the connector loads its host key from <state_dir>/ssh_host_ed25519_key, generating one on first start. A jump host appears in the caller's known_hosts under this key.

An enrolled connector serving an SSH backend also keeps <state_dir>/activation.json, the highest activation epoch it has seen. It refuses to start when that file cannot be read or written. See gdsgate authority epochs activate.

On Windows a connector refuses to start with an SSH backend that uses ssh_profile = "git", login_mode = "host_user", or session ceilings in [connector.backends.session].

gdsgate agent-host

Runs the agent host: starts the agents declared for this node, each in its own cage. See the agent host guide.

Reads: [endpoints].authority, [enroll], [agent_host], [telemetry].metrics_listen.

TOKEN_FILE="<agent-host-enrollment-token-file>"
GDSGATE_ENROLL_TOKEN="$(<"$TOKEN_FILE")" \
    gdsgate --config agent-host.toml agent-host

Binds no listener. Connects to Authority over mutual TLS. The enrollment token is used once; the node certificate is renewed without a token.

The agents and their access are declared on Authority with authority agents set; this host has no configuration for them. Enroll the node with gdsgate join --role agent-host, using a token from gdsgate authority tokens create --role agent-host.

A node holding no enrolled identity is refused under [security].profile = "pilot" or "production".

Agents run on Linux only. On Linux, install the unit from packaging/systemd/gdsgate-agent-host.service by hand; service install does not offer this role. On Windows the process starts but runs no agents, and logs each declared agent as not held.

gdsgate connector recordings push [--dry-run]

Delivers the recordings a running connector is holding in central mode but has not yet gotten to Authority, or says why not, without waiting for the next scheduled delivery pass.

gdsgate --config connector.toml connector recordings push --dry-run
gdsgate --config connector.toml connector recordings push

--dry-run lists what is on disk and, for each cast, why it is still there; nothing is uploaded and nothing is removed. A real run uploads and removes what the store accepts, printing one line per cast, delivered or held back, and a summary.

The command asks the running connector to deliver, over its local control channel: the socket ${enroll.state_dir}/connector.sock on Linux, a named pipe derived from that path on Windows. When no connector is listening, the command says so and exits 1; the connector's next start runs a delivery pass.

When a delivery pass is already running, the command says it is waiting, waits for it, then runs its own.

Exit codes, the same four gdsgate join uses:

Exit Meaning
0 At least one cast was delivered.
1 Nothing was delivered and something is held back, including a pass that stopped partway through, an unreachable store for one.
2 The arguments do not parse.
3 There was nothing to deliver.

See gdsgate doctor to check whether anything is waiting before running this by hand, and the admin guide for the operator recipe this command is part of.

gdsgate all

Run Authority, Proxy and an embedded Connector in one process. store_url defaults to a SQLite file (~/.gdsgate/state/store.db) that survives restarts. Other connectors can still register on the registration listener.

Reads: every section.

gdsgate --config all.toml all

gdsgate service install|uninstall <role>

Installs a role as a service, or removes it. Server roles require root on Linux and an elevated prompt on Windows. install does not start the service unless --start is supplied. An already running service stays running. The agent host is not offered; see gdsgate agent-host.

Successful installation records the configuration the service now uses. A reinstall with a different --config replaces that role's previous service path; other role records and the selected client cluster are retained.

gdsgate service install authority --start
gdsgate service install proxy --start
gdsgate service install connector --start

gdsgate join --start also installs and starts the Connector service after saving its registration. Both commands use this service installer; a failed start can be retried without another join token.

--start checks for an immediate process exit. Setup startup uses the same start check and also waits for its control plane and Proxy readiness endpoints. If registration or startup fails, the error names the completed stage and a retry command. Existing configuration and identities are retained.

Linux

Roles: authority, proxy, connector. The unit is the shipped one from packaging/systemd, with the paths filled in.

Property Value
Unit /etc/systemd/system/gdsgate-<role>.service, enabled
Program the gdsgate that runs install; refused under /tmp, /var/tmp, /home, /root and /run/user, which the unit hides from the service
Account DynamicUser=yes, in the gdsgate group
Configuration --config, otherwise the installed role configuration (including standard platform files); its directory, its *.toml, *.cedar and *.keys, and every file the configuration names inside it (a registration key, a certificate) are given to the gdsgate group, files 0640
Environment <role>.env beside the configuration, optional
State /var/lib/gdsgate/<dir>, the one directory the service may write
Log journalctl -u gdsgate-<role>
Start with the machine; Restart=on-failure after 2 s
Configuration reload systemctl reload gdsgate-<role> applies supported changes and confirms the result; see reload.

<dir> is the directory under /var/lib/gdsgate that the role's configured paths are in: [enroll].state_dir for proxy and connector, the SQLite store and [audit].export_path for authority. Without one, it is the role's name. A file the role reads from under /var/lib/gdsgate has to be in the same directory. install refuses the configuration if one of these paths is elsewhere:

Refusal Fix
... is under ... which the unit hides Move the configuration under /etc/gdsgate, or the program under /usr/local/bin. Home and temporary paths are hidden.
... is outside /var/lib/gdsgate Move the written path under /var/lib/gdsgate/<role>.
... is where every role's directory is Name a directory under it, such as /var/lib/gdsgate/connector.
... is directly in /var/lib/gdsgate Move the file into the role's directory and change the path in the configuration.
... are in two directories under /var/lib/gdsgate Keep the role's files in one directory.

When /var/lib/gdsgate is a link into /var/lib/private (left by units that shared one state directory), install turns it into a directory. Role directories stay where they were; files that sat directly in it move back. A unit that still has StateDirectory=gdsgate no longer starts, and install names it: install that role again.

Every Linux service install, including client, checks the shared parent /var/lib/gdsgate. An install run as root creates or repairs this directory to mode 0755 before registering the service. A parent left at 0700 blocks service accounts from reaching their private state. The repair changes only the common parent; role directories and key files keep their permissions. An unprivileged install reports an invalid existing parent and requires an administrator to repair it. Unexpected links and non-directory entries are refused. doctor reports the same parent problem without changing permissions.

gdsgate --config /etc/gdsgate/authority.toml service install authority --start
gdsgate service uninstall authority

Resident client

Linux also supports client: the default protected system unit runs as the original user and retains their configuration and identity. It needs elevation and the trusted kernel filter command. A user unit is available with local_user_only = false and a loopback access level. Normal gdsgate up handles installation and startup, asking for elevation once when needed. --foreground runs the resident directly. See Resident service.

sudo gdsgate --config "$CLIENT_CONFIG" service install client --start
sudo gdsgate service uninstall client

On Windows, client installs the same privileged network helper as client-net; the resident remains in the user session. An ordinary up ensures that helper is running.

Windows

Roles: authority, proxy, connector, client-net, client.

Property Value
Service name gdsgate-<role>
Account virtual account NT SERVICE\gdsgate-<role>; client-net runs as SYSTEM
Configuration --config, default %ProgramData%\gdsgate\<role>.toml; client-net reads none
State %ProgramData%\gdsgate\state\<role>, owned by the service account
Log %ProgramData%\gdsgate\logs\gdsgate-<role>\gdsgate-<role>.log, rotated at 32 MiB, three kept; the service account writes its own directory there and no other
Start with the machine; restarted 5 s after a failure, including an exit with an error
Configuration reload gdsgate.exe reload --role <role> applies supported changes through the running service's local channel.
Certificate refresh sc.exe control gdsgate-<role> paramchange re-reads listener certificates.

install gives the service account read access to the configuration, every file it names, and gdsgate.exe. It also makes the account the owner of its state directories. Secret files lose every entry except their owner, SYSTEM and the gdsgate service accounts. Running install again for a registered server service renews those grants and updates its binary/config launch paths. It keeps the virtual account, operator startup mode, dependencies, display name, error control and failure policy. A service registered under another account is refused. Run install after adding a file or moving the binary or configuration; restart an already running service to load the updated paths.

On both systems uninstall stops the service and removes the unit or the registration. Configuration, state and log stay where they are. Removing a service that is not installed succeeds.

gdsgate service install authority --start
gdsgate service uninstall authority

gdsgate client-net

Windows only; refused on Linux, where the resident client runs from gdsgate-client@.service. The service sets the NRPT rule and holds the Wintun adapter for the resident client; see Resident client on Windows. A delegated run under --sandbox basic or strict uses it to let the run's container reach its endpoints, read drive letters and use NUL; see The sandbox on Windows. The Windows installer registers it with gdsgate service install client-net. Do not run it by hand.

Service lifecycle

proxy, connector, authority and all run in the foreground until stopped; run them under systemd on Linux or the service manager on Windows. Before treating a replacement as ready, check /healthz and /readyz: a process can be live while its dependencies are not ready.