Skip to content

Resident client

The Resident client is an optional local daemon. It keeps the identity and catalog current, assigns a loopback address to each visible resource, and regenerates native-client files when the catalog changes. It is a convenience layer over the explicit commands in the User guide, not a second authorization system.

Reader: a user deciding whether this machine should carry access for one shell, several local applications, or the whole host. The deployment owner supplies a Linux x86_64 musl binary and a client configuration. The examples use the canonical lab resources authority-1, proxy-1, connector-1, lab-read, lab-denied, and principal alice@example.test.

Access levels

access and resolver are independent settings. The first controls how an application reaches a local relay. The second controls how names are published.

Decide whether this machine should run a Resident client before choosing a level:

Machine Recommended starting point Required owner decision
Personal Linux workstation basic; move to direct only for a native-client need user owns identity, generated files, listeners, and cleanup
Managed desktop basic under the managed user desktop owner approves service policy, resolver changes, trust, rollback, and removal
Shared host off or per-user basic host owner accepts that another process under the same user can reach the listener
Server or non-interactive service explicit command or reviewed workload identity service owner supplies supervision, renewal, state paths, and incident response
Container explicit command by default container owner proves persistent identity/state and accepts that transparent changes only the granted network namespace

The supported public client target is Linux x86-64 with the administrator- supplied static musl binary. Another platform requires a separate support record; a successful local build is not that record.

Level What it publishes Host and permission boundary
off no local access safest default; use explicit commands
basic loopback listeners applications on this user account can reach them
direct loopback listeners and direct native paths may bind privileged ports when the host permits it
transparent a virtual interface and per-resource addresses Linux network namespace and CAP_NET_ADMIN are required
auto the strongest level the host can prove degrades to a supported lower level and explains why

Action on the client host:

gdsgate --config "$CLIENT_CONFIG" up
gdsgate --config "$CLIENT_CONFIG" status --explain

Expected result: up waits until the selected level is settled and status reports the level actually serving. Positive proof is a local address for a visible resource and a successful native request. The nearest negative is a catalogued but denied resource: its address, name, and status row remain stable, but the gateway refuses the connection and reports the reason. Recovery is to choose a lower level or fix the host capability; do not treat a degraded level as transparent. Cleanup is gdsgate down, followed by checking that managed listeners and names are gone.

Privileged ports at direct

direct may request a low port only when the host grants that bind. A refusal means the kernel or service policy rejected the bind, not that Authority denied the resource. Use a high loopback port or basic; never grant broad privilege to make a user-facing example pass. Positive proof is the actual listener address shown by status, not a requested port.

The transparent level

transparent routes traffic addressed to the client's virtual pool through the resident process. It is intended for applications that cannot be configured with a local proxy. It changes host routing, so treat it as system-wide for the duration of the daemon.

Capabilities

The process needs Linux support for a virtual interface, a configured address pool, and the ability to install routes. The daemon reports each missing property in status --explain. This is not a container or kernel boundary: an application that can change host networking can affect more than a resident client's managed entries.

Requirements

Prerequisites are Linux, a non-overlapping private address pool, and the administrator's permission to grant CAP_NET_ADMIN to the daemon path. The pool must not overlap the host LAN or another virtual network. Test with the safe basic level first, then request transparent:

gdsgate --config "$CLIENT_CONFIG" up
gdsgate --config "$CLIENT_CONFIG" status --explain

Expected result: ACCESS and SERVING report transparent, and a test request to a visible resource succeeds. The nearest negative is a host capability or pool conflict; the daemon must refuse or degrade without claiming transparent coverage. Recovery is to select basic or fix the pool and capability. Cleanup is down plus a check that the managed interface and routes have been removed.

Tradeoffs

Transparent access reaches applications that ignore proxy variables, but it also applies to every process that can route to the pool. A loopback listener is not a complete isolation boundary either: another process under the same user can use it. Choose basic on shared machines and use explicit client commands for sensitive resources.

Connection identity

The resident daemon holds the identity for the configured user and obtains short-lived resource access certificates. A local address does not grant a new right: Authority still decides connect, and request-aware lanes decide their own operations. Positive evidence is a successful request with the expected principal in audit. A stale or revoked certificate yields ACCESS refusal and must not be worked around by dialing the backend directly.

Shared machines

On a shared machine, use off or basic with a per-user configuration. Avoid transparent, intercept_names, and a service unit unless the host owner accepts their system-wide consequences. A Resident socket is not a credential, but a process that can reach it may use the access of its owning user. Cleanup must include down, generated-file removal, and identity-cache removal at account retirement.

Names

Names are another independent choice. resolver = off publishes no names; hosts manages an owner-marked block in the hosts file; system serves the configured zone and points the system resolver at it; auto chooses the strongest mode the host can safely configure. A resolver downgrade does not change the access level.

Name resolution per access level

Access resolver = off hosts system auto
off no names managed hosts entries if allowed explicit system resolver if configured hosts or off
basic no names managed hosts entries possible when the host routes queries to the daemon system, hosts, or off
direct no names managed hosts entries possible without transparent access system, hosts, or off
transparent no names managed hosts entries normally required for whole-host names system or hosts

The system mode is not implied by transparent, and it is not forbidden at direct or basic. Record the chosen mode in the deployment handoff.

hosts

Prerequisite: permission to edit the host's managed block. Action:

gdsgate --config "$CLIENT_CONFIG" up
getent hosts RESOURCE_NAME

Expected result: the name maps to the current assigned local address. Positive proof is the managed marker and a request through that address. The nearest negative is a missing or read-only hosts file; status must say names - or names ?, not claim a working name. Recovery is resolver = system where the host allows it, or explicit loopback addresses. Cleanup is down, which removes only the block owned by this configuration.

system

system requires a daemon listener, a zone, and a host resolver path that sends queries to it. Verify both the daemon and the system resolver:

gdsgate --config "$CLIENT_CONFIG" status --explain
getent hosts RESOURCE_NAME

The nearest negative is a successful local daemon with a system resolver that still asks another server. Recovery is to restore the prior resolver settings or switch to hosts; never leave a partial resolver redirect on uninstall.

Verifying name resolution

Use status --explain to see the selected resolver, managed state, and any downgrade reason. Test one positive catalog name and one name outside the catalog. The second must not resolve to a managed resource. Cleanup is to run down and repeat both lookups, then inspect only the daemon-owned markers.

An application's own name

A web resource may declare a native_name that belongs to the upstream application. The Resident client intercepts it only if the user also places the whole name in [client].intercept_names. Catalog declaration alone cannot widen the user's opt-in.

Actor: a user who owns the client and the application-name decision. Prerequisites: the catalog has the matching web resource and the client configuration names the exact domain. Action: start the Resident client, then open the name with the browser or HTTP client. Expected result: the application sees its original host name. Positive proof is the expected certificate and an httpRequest row. The nearest negative is a name in only one of the two lists; the client must leave it untouched. Recovery is to reconcile the catalog and local opt-in. Cleanup is removing the opt-in and running down.

Certificate root for intercepted names

The owner must install the deployment's public certificate root in the browser or native client trust store before interception. The generated certificate is not a credential and does not prove policy access. A trust warning is a TLS configuration failure; do not click through it. Remove the root when retiring the deployment.

Limitations

Interception affects the whole host's DNS and TLS behavior for the opted-in names. It does not intercept a name absent from the catalog, and it cannot turn an HTTP application denial into a network success. Native names also depend on the resolver mode and can be unavailable during a downgrade.

Status output

status distinguishes identity, catalog, names, listener, access, and serving states. ok means the check completed positively; ? means control-plane uncertainty; - means the check was not requested. Example fields are stable concepts, not a promise that every release prints identical spacing:

identity  ok   catalog ok   names ok   access ok   serving ok

Start-up sequence

The daemon validates settings and the access level, refuses to start over an existing client, signs in the parent when needed, starts the child or foreground process, binds its socket, settles the interface and names, fetches the catalog, assigns addresses, generates native files, and then reports serving state. The source currently waits up to 10 seconds for the socket and 3 seconds for name/interface settlement. These timings are version-sensitive; use status instead of scripting exact sleeps.

Background execution

gdsgate --config "$CLIENT_CONFIG" up
gdsgate --config "$CLIENT_CONFIG" status
gdsgate --config "$CLIENT_CONFIG" down

up returns after the daemon is ready enough to report, not merely after a child process exists. Expected result is a positive SERVING state. The nearest negative is an existing client or an identity refusal; the command must leave the old process and its state unchanged. Recover by inspecting status --explain, then retry after the cause is fixed. Cleanup is down.

The client journal

The daemon journal records startup decisions, degradation, listener changes, and errors. It must not contain private keys or provider tokens. Use the host's service-log reader or the configured log path supplied by the owner. A malformed generated state file is a local recovery problem: stop the daemon, preserve the file for diagnosis, and regenerate it only after verifying the config.

--foreground

Use foreground mode on the command host when diagnosing startup or running a supervised service:

gdsgate --config "$CLIENT_CONFIG" up --foreground

Expected result: the command remains attached while the daemon serves. Positive proof is the same status state and a test request. The nearest negative is a startup error in the terminal; fix that error before switching to a service. Interrupting foreground mode is cleanup and must remove managed state through the normal shutdown path.

Automatic authentication

When no usable identity exists, up can invoke the configured login path. A browser choice is explicit:

gdsgate --config "$CLIENT_CONFIG" up --browser

Expected result is a resident process under the signed-in principal. The nearest negative is a non-interactive service with no token or browser. Use a workload identity or a pre-provisioned service route instead of putting a human token in a unit file. Cleanup is expiry and cache removal.

Certificate prefetch

With warm access enabled, the daemon requests access certificates during the catalog pass. status then distinguishes a resource that is visible from one that is ready to connect. A refusal is cached with its reason and is not polled continuously. Positive proof is ACCESS ok; the nearest negative is ACCESS step-up or ACCESS denied. Recover with the named one-time step-up or policy change, then wait for the next catalog pass. Cleanup is certificate expiry, not manual key copying.

Address stability

Assigned addresses remain stable for a running client and are not immediately reused after a resource leaves the catalog. The reuse grace period is a safety boundary against an old application reaching a new resource. Positive proof is the same resource ID in successive status reports. Recovery from an address conflict is a client restart after the owner resolves the pool; do not edit the state map by hand.

Resources removed from the catalog

When a resource disappears, the client marks it unavailable, stops serving its address after the configured grace, and removes generated native entries on the next safe update. Existing sessions are closed by their own revocation/session rules. The nearest negative is a stale name still resolving locally; run status --explain, stop the client if needed, and remove only managed entries.

Address reuse

An address is reused only after the grace period and a restart that confirms no never-used address remains. This prevents a stale process from silently talking to a different resource. Record the old and new resource IDs when reviewing a reuse event. Cleanup is the same managed-state removal path.

Generated files

Generated files are owner-only, written atomically, and marked so the daemon can replace only its own content. They are not credentials. SSH host keys remain in the native client's known-hosts store; Resident does not make a host-key change safe. A generated kubeconfig or environment file contains routing metadata and short-lived endpoints, not a license to bypass Authority.

Inspect the generated directory before handing it to another user:

gdsgate --config "$CLIENT_CONFIG" status --json

Expected result: paths and resource states match the current catalog. The nearest negative is a partial file after an interrupted update; stop the client, restore the previous atomic file if the owner has one, and restart. Cleanup is down followed by removal of files marked as managed by this client. Never use rm against an unreviewed directory.

Shutdown

Normal cleanup is:

gdsgate --config "$CLIENT_CONFIG" down
gdsgate --config "$CLIENT_CONFIG" status --explain

Expected result: no resident socket, no managed listeners, and no managed names. down is idempotent. After a crash, the next up detects stale state, cleans only its own markers, and reports anything it could not remove. If the host was powered off, inspect the interface, routes, hosts block, and resolver before re-enabling transparent mode. Uninstall cleanup also removes the client identity cache and service authorization, after active sessions are terminated.

Safe uninstall

The user and host owner perform removal in this order:

  1. End or transfer active sessions, and retain the request or session IDs needed for the deployment's audit record.
  2. If a service unit owns Resident, stop and disable that exact unit. Run gdsgate down as the same user and with the same configuration that ran up.
  3. Require status --explain to show no Resident socket, listener, managed address, or served name. Inspect the managed interface, routes, hosts block, and system resolver against their pre-install record.
  4. Restore only the resolver, hosts, trust, and service entries marked as owned by this installation. Leave unrelated host configuration unchanged.
  5. Remove the exact generated fragments, endpoint map, socket directory, identity cache, and service-owned state paths recorded by the configuration. Review every resolved path before deletion; do not recursively remove a parent configuration or home directory.
  6. Run a negative native-client and name-resolution check. The old endpoint must not listen or resolve, while an unrelated host entry and resolver path must still work.

If any managed route, name, listener, or file owner cannot be reconciled, stop the uninstall and restore the last known host configuration. Do not erase the evidence needed to distinguish stale Resident state from unrelated host state.

Access refusals

The Resident client keeps a refused resource's local address, name, and status row so a denial does not silently renumber other resources. The address does not bypass the refusal: the gateway still denies the connection. A refusal can come from identity, catalog visibility, connect policy, a per-request action, an expired certificate, or a host capability. The message should name the operation, cause, and safe next action.

Refusals in gdsgate status

ACCESS denied means policy or identity refused the resource. ACCESS step-up means a one-time grant may cure it. ACCESS ? means the control plane could not be reached and the cached result is not a new allow. SERVING - means no local listener was requested. Do not interpret ? as success.

Step-up grants are single-use

A step-up grant belongs to one principal, resource, and action. Prefetch does not spend it, because doing so would authorize a connection the user did not make. The next matching operation consumes it once. A second operation is the nearest negative and must be denied. Recover by minting a fresh, narrow grant.

Desktop notifications

Notifications are a convenience for a local user, not an authorization channel. If the notification program is unavailable, the refusal remains in status and the journal. A service account must not depend on a desktop notification for recovery.

Refusals inside an SSH connection

An SSH session can open while a later forward or downstream action is denied. Keep the connect decision separate from sshForwardLocal, sshForwardRemote, and native host-key failures. Positive evidence is the specific channel that opened; the nearest negative names the channel that did not. Close the session after recovery or policy review.

Resolving access failures

Check in order: status --explain, identity freshness, catalog row, action name, local listener, then backend reachability. Use gdsgate --no-remediate for a non-interactive negative test. Never test a policy denial by bypassing the Proxy.

Reading gdsgate status

Use the compact view for a quick handoff and JSON for automation:

gdsgate --config "$CLIENT_CONFIG" status
gdsgate --config "$CLIENT_CONFIG" status --json --explain

The report distinguishes these states:

Field ok ? -
identity usable local identity control-plane freshness unknown not requested
catalog current catalog refresh uncertain not requested
names resolver serving resolver state uncertain names disabled
listener local listener bound bind status uncertain no listener requested
access policy/certificate usable cached decision only not warmed
serving request can reach its relay tunnel uncertain no resource served

Resources without an active connector

A catalog row can exist while no Connector serves it. status reports that state as declared but not serving; no local address is evidence of a working backend. Recovery is for the administrator to register connector-1 or the appropriate Connector and publish the resource again. Cleanup is removing a stale catalog row through the Admin guide.

Status details

--explain includes the resource ID, kind, action, identity state, connector state, local address, and last refusal. Treat its output as diagnostic metadata, not a credential. A JSON consumer should fail closed when a required field is ? or -.

Runtime files and state

The client configuration, identity cache, resident socket, generated endpoint map, and generated native fragments have separate purposes. The exact paths come from the user's configuration and service environment. Keep private keys mode 0600, keep generated files owner-only, and back up neither as a shared credential archive. The endpoint map is local state and may be regenerated.

Running under sudo

sudo gdsgate changes the user, configuration lookup, identity cache, socket, and generated-file owner. It does not make a user policy allow. Use an explicit --config and a deliberate output directory if a privileged port is required, then inspect status as the same user that will run the native client. Do not run the resident client as root on behalf of an unprivileged user unless the service design explicitly accepts that shared boundary. Cleanup both identities and their managed files.

As a service

The service path is for a host owner who wants access to survive a login shell. Prerequisites are a dedicated service account, an explicit configuration, local authorization for the service action, and a workload identity or other non-interactive login path. The service must not store a human browser token in an environment file.

The system unit

Install the supplied unit through the host's service manager, review its user, configuration, capabilities, and generated-file directories, then start it. Expected result: the unit is active and gdsgate status --json reports the intended access. The nearest negative is a unit that is active but has no identity, catalog, or serving state. Recovery is to fix that state, not to add unbounded privileges. Cleanup is stop, disable, down, and removal of the service-owned identity and generated files.

Names under the system unit

Names are owned by the service account and its resolver configuration. A unit that edits a host-wide resolver or hosts file must document that ownership and its rollback command. Positive proof is a name lookup as a normal user. The nearest negative is a name that works only as the service account; fix routing or use a per-user hosts mode. Cleanup restores the pre-service resolver.

/etc/hosts under a service

The unit may manage a marked block only when the host owner grants that scope. On stop or uninstall, remove that block and leave unrelated entries unchanged. Verify with a positive lookup before start and a negative lookup after stop.

Completion

Generate shell completion without contacting Authority:

gdsgate completion bash > "$COMPLETION_FILE"

Resource completion reads local Resident state and may be empty when the daemon is stopped. It is not evidence that a resource is reachable. Cleanup is removal of the generated completion file when the binary is retired.

Settings

The complete configuration reference is Configuration. For this page, record at least access, resolver, warm_access, step_up_on_denial, the transparent address pool, intercept_names, generated file roots, and the service user. Mark any version-sensitive host capability and the date it was last checked. The next safe action after a setting change is gdsgate doctor, then up, then a positive fixture request and its nearest negative.