Skip to content

What a change affects

A change an operator makes after the first start. The table names it, what else moves with it, and whether a role restarts. Each row links to its section below for the files, the symptom if a dependent change is missed, and a check. Procedures live at each section's reference link, including operations/change.md.

Change Also change Restart Section
The name or address clients and connectors dial DNS record, certificate SAN, client configs Authority, Proxy link
IP-only to a DNS name certificate mode, workstation and connector trust Authority, Proxy link
Public certificate renewal, same CA none none link
Public certificate: new CA, or Let's Encrypt to own CA client and connector trust none link
Registration certificate renewal, same name none none link
Registration certificate: name changes transport_sni, [enroll].endpoint scheme Proxy, connectors link
dev to pilot store, certificates or identity the role link
pilot to production OIDC issuer/client id, integrity keyrings the role link
Connector route classification firewall Authority, Proxy link
public_join / join relay toggle firewall, joined connectors' renewal address Authority, Proxy link
Join relay to public_join, connectors already joined each connector rejoins Authority, Proxy, connectors link
A listener port firewall, DNS, joined connectors' endpoints the role that binds it link
A bind address firewall, [admin].endpoint Authority link
Splitting onto two hosts firewall, registration certificate both roles link
Joining back onto one host firewall both roles link
SQLite to PostgreSQL none Authority link
PostgreSQL address or password network route, firewall Authority link
OIDC issuer or client id provider discovery document, client re-login Authority, Proxy link
OIDC group mapping provider client or mapper, complete public profile on nodes/clients Authority, Proxy when gdsgate mapping changes; fresh client login link
Adding a redirect URI provider client configuration none link
Naming or rotating control_keyring/audit_keyring every HA replica's keyring files Authority, prepare step only link
User SSH CA rotation none none link
Onward SSH CA rotation downstream sshd trust file none on gdsgate's side link
HostTls / SPIFFE / JWT-signing CA rotation propagation window for renewal or cache TTL none link
Audit export path log shipper's watched path Authority link
Recording storage mode or state_dir policy grant for central casts the connector link
Adding an Authority replica firewall, authority_failover on the Proxy every Authority, the Proxy link
Product version upgrade none each role, in order link
Evaluation build licence file none Authority link

Gateway name and address

The name or address clients and connectors dial

  • Files and keys: [endpoints].proxy_public/_internal/_ws (Authority: told to nodes; Proxy: bound)
  • Also change: DNS record; [proxy].public_cert_file SAN; [enroll].transport_sni where the Proxy dials Authority by another address; every client's ~/.gdsgate/config.toml (gdsgate connect <name> again); an already-joined connector keeps its old advertised addresses in connector.toml until it rejoins
  • Restart: Authority and Proxy ([endpoints] read at start)
  • Symptom if missed: clients and new connectors dial the old name; an already-joined connector's tunnel and renewal calls keep going to the old address until it rejoins
  • Check:
    gdsgate connect <new-name>:<port>
    gdsgate --config <authority.toml> authority nodes list
    
  • Reference: [endpoints]

IP-only to a DNS name

  • Files and keys: certificate mode: own-CA/IP-address pair to Let's Encrypt or own-CA name pair (Certificates); [proxy].public_cert_file; [authority].enroll_cert_file; drop [enroll].transport_ca/--enroll-ca once the new certificate is publicly or system trusted
  • Also change: --domain value in every future setup prepare/join; workstations trust the new pair without --fingerprint; connectors joined at the IP drop --enroll-ca on their next join
  • Restart: Authority and Proxy for the new certificate files; connectors need no restart for the reload, but a fresh --enroll-ca-free join stops them carrying the old anchor
  • Symptom if missed: old workstations still pinned by --fingerprint keep working; a new one pointed at the address fails without --fingerprint
  • Check:
    openssl x509 -in <cert> -noout -ext subjectAltName
    gdsgate connect <name>
    
  • Reference: Certificates: modes

Certificates

Public certificate renewal, same CA

  • Files and keys: [proxy].public_cert_file/public_key_file (also [authority].enroll_cert_file/enroll_key_file when one pair serves both listeners)
  • Also change: nothing
  • Restart: none; certificate refresh within 1s; kill -HUP <gdsgate-pid> or sc control ... paramchange forces it now
  • Symptom if missed: none if the pair parses and the key matches; a bad pair leaves the old one in force
  • Check: log line listener certificate reloaded cert=<path> generation=<n>; a new TLS handshake presents the new pair
  • Reference: Renewing a listener certificate; Certificates: renewal

Public certificate: new CA, or Let's Encrypt to own CA

  • Files and keys: same files; clients that pinned the old CA via SSL_CERT_FILE/system store
  • Also change: every client and connector trust source: system store update, or a fresh --enroll-ca/--fingerprint
  • Restart: none; hot reload of the files; client-side trust update is manual, per host
  • Symptom if missed: gdsgate connect reports published no transport CA anchor, and the certificate authorities this host trusts do not vouch for it either
  • Check:
    openssl verify -CAfile <root> -untrusted <chain> <leaf>
    
    on the new pair before installing it
  • Reference: Certificates: own CA

Registration certificate renewal, same name

  • Files and keys: [authority].enroll_cert_file/enroll_key_file
  • Also change: nothing
  • Restart: none; same hot reload as the public pair
  • Symptom if missed: none
  • Check: same log line, cert=<enroll_cert_file path>
  • Reference: Renewing a listener certificate

Registration certificate: name changes

  • Files and keys: same files; [enroll].transport_sni on every Proxy/connector that dials Authority by another address or an internal name; --enroll-ca on nodes trusting a private CA
  • Also change: going from cleartext to TLS on this listener changes every node's [enroll].endpoint from http:// to https:// in the same rollout
  • Restart: every Proxy and connector whose [enroll] block changes; the listener itself only hot-reloads the pair
  • Symptom if missed: no transitional mode: a node with the wrong scheme cannot connect at all; certificate refused (NotValidForName...)
  • Check:
    gdsgate join ...
    gdsgate config check <file> --role proxy
    
  • Reference: [authority], no transitional mode

Security profile

dev to pilot

  • Files and keys: [security].profile; gdsgate authority profile set --profile pilot --changed-by <name> for Authority, or gdsgate setup change --set <role>:security.profile=pilot for any role
  • Also change: Authority: store_url to PostgreSQL, [authority].enroll_cert_file/enroll_key_file; Proxy: [proxy].public_cert_file pair or an enrolled identity, [enroll].endpoint scheme https://
  • Restart: the role ([security].profile read at start; set-profile writes the file but does not restart)
  • Symptom if missed: the service refuses to start and lists every failed check at once
  • Check:
    gdsgate config check <file> --role <role> --profile pilot
    
    exit 0 clean, 1 error, 2 warning-only
  • Reference: Profile matrix; gdsgate config check

pilot to production

  • Files and keys: same, plus [oidc].issuer/client_id; [security.integrity].control_keyring/audit_keyring, two distinct files
  • Also change: keyring file ownership/mode (0640 group gdsgate, or owner-only); every replica holding the same keyrings before promoting a key
  • Restart: the role; a keyring add/rotate needs an Authority restart of every replica (ring read at start)
  • Symptom if missed: `[oidc].issuer` and `[oidc].client_id` are unset; `[security.integrity].control_keyring` names no keyring; a keyring on the wrong permissions refuses at start
  • Check:
    gdsgate config check <file> --role <role> --profile production
    
  • Reference: Profile matrix; [security.integrity]

Connector route

Route classification

  • Files and keys: [connector].authority_transport in Authority's file (direct/tunneled/fronted); setup prepare writes it from the flags below
  • Also change: firewall for the ports the new route needs
  • Restart: Authority and Proxy; an already-joined connector needs gdsgate join --if-missing --route fronted (or direct/tunneled), no token: the route rewrites the advert this node renews at
  • Symptom if missed: a connector still on the old route's advert renews at the wrong address and fails once its certificate cannot renew there
  • Check:
    gdsgate join <domain> ... --if-missing --route fronted
    
    output line --route fronted: Authority ..., renewal ... names the new address
  • Reference: Connector routes; gdsgate join

public_join, the join relay, --no-public-join

  • Files and keys: Proxy and Authority: [proxy].public_join, [endpoints].proxy_join; setup prepare flags: none (public_join), --join-relay, --no-public-join
  • Also change: firewall (50061 vs 50064 vs 50050/50051); every already-joined connector's [enroll].renew_endpoint
  • Restart: Authority and Proxy
  • Symptom if missed: an already-joined connector keeps dialing the retired relay or port for renewal; once its transport certificate cannot renew there, it drops off the cluster with no warning before that point
  • Check: gdsgate config check <proxy-file> --role proxy (proxy.public_join warns if the listener has no name-bearing certificate); renew_endpoint in the connector's own file
  • Reference: public_join; proxy_join; gdsgate join

Join relay to public_join, connectors already joined

  • Files and keys: Authority: [proxy].public_join = true, [endpoints].proxy_join removed; Proxy: [proxy].public_join = true, [endpoints].proxy_join kept until the last connector has moved
  • Also change: each connector, no token:
    gdsgate join gate.example.com --if-missing \
      --enroll-endpoint https://gate.example.com:50061
    
    plus the arguments it joined with; it renews at 50061 and writes that as renew_endpoint. Then remove proxy_join from the Proxy's file and close 50064
  • Restart: Authority, then the Proxy, before the connectors run join; each connector right after its run; the Proxy again after removing proxy_join
  • Symptom if missed: join stops with Authority's file still sets [endpoints].proxy_join while Authority advertises the relay; a connector not restarted after its run logs renewal denied: unknown identity; a connector not moved when 50064 closes cannot renew; an expired identity needs --force and a fresh token
  • Check: renew_endpoint in each connector's file; on the Proxy under RUST_LOG=gdsgate_proxy=debug, each relaying join line names the IP of a node still on 50064. list-nodes and the Proxy's metrics do not show the renewal address
  • Reference: Moving the registration address; proxy_join

Listener ports and bind addresses

A listener port

  • Files and keys: [endpoints].* on the role that binds it, and on Authority's file when split (Authority does not bind the Proxy's addresses, but advertises them)
  • Also change: firewall; DNS/clients dialing a fixed port; already-joined connectors' [endpoints].proxy_internal/proxy_ws and [enroll].renew_endpoint, static in connector.toml
  • Restart: the role that binds the port, and Authority if its [endpoints] names it for advertising
  • Symptom if missed: a connector whose one changed port has a live twin (proxy_ws when only proxy_internal moved) fails over to it on its own; with no live twin, its tunnel and renewal both fail silently until manually rejoined
  • Check:
    ss -ltn
    gdsgate --config <authority.toml> authority nodes list --health
    
  • Reference: [endpoints]; What Authority tells a joining node

A bind address

  • Files and keys: --authority-bind/[endpoints].authority/ authority_enroll
  • Also change: firewall rule scoped to the new address; [admin].endpoint if it names the old one
  • Restart: Authority
  • Symptom if missed: administrative CLI hangs dialing the old address; a joining node told a wildcard address reports it received none
  • Check:
    ss -ltn | grep 5005
    gdsgate --config <authority.toml> authority nodes list
    
  • Reference: Separate hosts: traffic

Splitting or joining Authority and Proxy

Splitting onto two hosts

  • Files and keys: Authority: --authority-bind <reachable-address> (not loopback, not a wildcard with --no-public-join); Authority's file also carries the Proxy's [endpoints], [proxy].public_join, [connector].authority_transport, since Authority does not bind them but must advertise them
  • Also change: firewall on the Authority host, allowing the Proxy's address on the registration and control-plane ports; the registration listener now needs a certificate off the loopback
  • Restart: both roles
  • Symptom if missed: the Proxy times out reaching Authority; a joining node receives only its identity, no addresses, when Authority's file lacks the Proxy's advertised settings
  • Check:
    nc -vz <authority-host> 50051
    curl 127.0.0.1:9090/readyz
    
  • Reference: Separate hosts; Split deployments must declare the Proxy's addresses

Joining back onto one host

  • Files and keys: reverse of the above; --authority-bind back to loopback
  • Also change: firewall rule removed
  • Restart: both roles
  • Symptom if missed: none specific; gdsgate all (single process) is refused under pilot/production, so the two roles stay separate processes on the one host
  • Check:
    gdsgate config check <file> --role <role>
    
  • Reference: all-in-one

The store

SQLite to PostgreSQL

  • Files and keys: store_url, store_password_file
  • Also change: nothing else in [endpoints]/[proxy]
  • Restart: Authority
  • Symptom if missed: no safe path: there is no export/import between backends; the new store_url starts an empty store (policy, catalogue, registry, audit chain all begin again)
  • Check:
    gdsgate config check <file> --role authority --profile pilot
    
    (store-postgres)
  • Reference: Top level; Profile matrix

PostgreSQL address or password, same data

  • Files and keys: store_url host/port, store_password_file
  • Also change: network route/firewall to the new address
  • Restart: Authority
  • Symptom if missed: connection refused at start; run authority store migrate --check against the new address before cutover
  • Check:
    gdsgate --config <authority.toml> authority store migrate --check
    psql <url> -c 'select 1'
    
  • Reference: Top level; Store schema

Identity provider

Issuer or client id

  • Files and keys: the complete [oidc] profile in every Authority and Proxy config, then the selected saved client configs
  • Also change: the trusted discovery issuer, registered client and authorized node issuer/client bindings must agree. Refresh client configs through verified connect, then sign in again. Retain protected node metadata; do not delete it to bypass a conflict.
  • Restart: Authority and Proxy
  • Symptom if missed: gdsgate login fails at the provider, or Authority refuses the token: issuer mismatch
  • Check:
    curl <issuer>/.well-known/openid-configuration
    gdsgate config check <authority-file> --role authority
    
  • Reference: profile lifecycle and [oidc]

Groups claim name

  • Files and keys: [oidc.claims.groups] selects the identity-token claim path, explicit format, optional delimiter and required behavior
  • Also change: the provider's identity-token mapper and exact group names in the reviewed access policy. Distribute the same OIDC mapping to every Authority, Proxy and saved client config.
  • Restart: Authority and Proxy when their OIDC config changes; client reload and a fresh login. A provider-only mapper change needs a fresh token, without changing gdsgate files.
  • Symptom if missed: an optional missing claim yields no memberships; required/malformed claims fail mapping; group-scoped policies deny
  • Check: fresh gdsgate login, its group summary, then an allowed and a denied operation against the intended cluster. Keep bearer tokens private.
  • Reference: claims-to-policy example and sanitisation

Adding a redirect URI

  • Files and keys: provider-side client configuration only
  • Also change: gdsgate login --browser: loopback http://127.0.0.1:<port>/callback; the clientless browser entry: https://gdsgate.<webapps_zone>/callback
  • Restart: none on gdsgate's side
  • Symptom if missed: the provider answers invalid redirect_uri
  • Check:
    gdsgate login --browser
    
    or open https://gdsgate.<webapps_zone>
  • Reference: gdsgate login; The clientless browser entry

Keyrings and CA rotation

Naming or rotating control_keyring/audit_keyring

  • Files and keys: [security.integrity].control_keyring/audit_keyring; gdsgate authority keys rotate <ring> --prepare|--activate|--retire
  • Also change: every HA replica needs the same keyring files before --activate
  • Restart: --prepare needs a restart of every Authority (ring read at start); --activate/--retire apply live
  • Symptom if missed: production refuses two rings naming the same file; --activate refused when a replica has not published the prepared key
  • Check:
    gdsgate authority keys status
    
  • Reference: Rotating a keyring; keys rotate

User SSH CA rotation

  • Files and keys: gdsgate authority ca rotate user-ssh, or [ca_rotation] on a schedule
  • Also change: nothing client-side; certificates reissue on the next connect
  • Restart: none; live, paced double-signing rotation
  • Symptom if missed: a session opened during too-short propagation_secs is refused by a verifier still on the old bundle
  • Check: gdsgate authority keys status; a session-level connect during the window
  • Reference: [ca_rotation]; CA rotation

Onward SSH CA rotation

  • Files and keys: gdsgate authority ca rotate onward-ssh
  • Also change: every downstream sshd's TrustedUserCAKeys
  • Restart: none on gdsgate's side; the downstream sshd needs its trust file updated and reloaded
  • Symptom if missed: the downstream host refuses the new certificate: Certificate invalid: unknown CA
  • Check:
    ssh -v <downstream-host>
    
    through the connector
  • Reference: rotate-onward-ca

HostTls / SPIFFE / JWT-signing CA rotation

  • Files and keys: gdsgate authority ca rotate host-tls/ rotate-spiffe-ca/rotate-jwt-ca
  • Also change: [ca_rotation].propagation_secs must cover a full mTLS renewal cycle (HostTls/SPIFFE) or the application's JWKS cache TTL (JWT)
  • Restart: none; nodes and applications pick up the new bundle on their next renewal or cache refresh
  • Symptom if missed: a verifier that has not refreshed refuses the new certificate inside the propagation window
  • Check: metric gdsgate_transport_identity_renewals_total; GET /.well-known/gdsgate/jwks.json cache headers
  • Reference: rotate-host-tls-ca; rotate-jwt-ca

Audit export and recording storage

Audit export path

  • Files and keys: [audit].export_path
  • Also change: the log shipper's watched path; under systemd, the new path must sit under the unit's ReadWritePaths=/state directory
  • Restart: Authority (path opened at start)
  • Symptom if missed: `[audit].export_path` is unset warning at start; or audit export file: the service cannot write it
  • Check:
    gdsgate config check <authority-file> --role authority
    journalctl -u gdsgate-authority | grep 'audit export'
    
  • Reference: [audit]

Recording storage: disk to central, or [enroll].state_dir

  • Files and keys: [recording].mode, [recording].sweep_interval_secs
  • Also change: a policy grant to read AuditLog::"recordings" for browsing central casts; a state_dir move leaves existing on-disk casts behind with no automatic carry-over
  • Restart: the connector
  • Symptom if missed: casts pile up undelivered; gdsgate doctor reports them pending or left behind
  • Check:
    gdsgate doctor
    gdsgate connector recordings push --dry-run
    
  • Reference: [recording]

High availability

Adding an Authority replica

  • Files and keys: new instance: same store_url, [ha].enabled = true; Proxy: [endpoints].authority_failover listing the new address
  • Also change: firewall opening the new Authority's 50050/50051 to the Proxy and to its peers; a shared PostgreSQL store (HA does not work on SQLite)
  • Restart: every Authority instance and the Proxy
  • Symptom if missed: without authority_failover on the Proxy, failover is invisible to it and it keeps dialing one instance only; mismatched keyrings across replicas refuse at start under production
  • Check:
    gdsgate authority keys status
    gdsgate --config <authority.toml> authority nodes list --health
    
  • Reference: [ha]; authority_failover

Version and licensing

Product version upgrade

  • Files and keys: binary replacement; store_auto_migrate explicitly set for a planned migration
  • Also change: order: upgrade every Proxy before Authority, and Authority before connectors when the SSH gate is on
  • Restart: each role in order
  • Symptom if missed: auth refused connector registration reason registration carries no resource kinds (wrong order); gate_not_offered on unupgraded connectors after activation
  • Check:
    gdsgate --config <file> doctor --json
    authority store migrate --check
    authority audit verify
    
  • Reference: Upgrade guide

Evaluation build licence file

  • Files and keys: none in TOML: --file <path> on gdsgate license show/verify, or GDSGATE_LICENSE_FILE in the process environment
  • Also change: nothing else; the document is read once, at Authority start
  • Restart: Authority: the licence loads once into memory at start, not re-read while running
  • Symptom if missed: Authority keeps enforcing the previous document's expiry until restarted, even after the file is replaced
  • Check:
    gdsgate license show
    gdsgate license verify
    
    metric gdsgate_license_expires_unix
  • Reference: Metrics and health