Configuration examples
Adapt the excerpts below into the gateway.yaml supplied in the release archive, then validate it before use:
/opt/particle_horizon/keystone-gateway config validate --config /opt/particle_horizon/local_config/keystone-gateway/gateway.yaml
Standalone
Use the complete configuration in standalone installation. For production TLS, enable api.https, set its TLS files, use api.auth.mode: mtls, and disable api.http.
Multiple caller principals
The fixed fields under api.auth support only the one shared principal used by mode: none. For multiple installations or both product types, select a mapping-based mode. This mTLS excerpt points the Gateway at a separate principal mapping file:
api:
auth:
mode: mtls
https:
enabled: true
listen: "0.0.0.0:8443"
advertise_url: "https://gateway-a.internal:8443"
server_cert_file: /opt/particle_horizon/local_config/keystone-gateway/server.crt
server_key_file: /opt/particle_horizon/local_config/keystone-gateway/server.key
client_ca_file: /opt/particle_horizon/local_config/keystone-gateway/client-ca.crt
principal_mappings_file: /opt/particle_horizon/local_config/keystone-gateway/principals.yaml
http:
enabled: false
# /opt/particle_horizon/local_config/keystone-gateway/principals.yaml
principals:
- common_name: product-phocol-01
principal_id: product-phocol-01
allowed_license_type: phocol
operator: false
- common_name: product-lmc-exporter-01
principal_id: product-lmc-exporter-01
allowed_license_type: lmc_exporter
operator: false
Each entry permits exactly one product license type. Add entries for additional installations; the mapping document has a 1 MiB total size limit rather than a fixed entry-count limit. See client authentication for bearer mappings, validation constraints, and endpoint visibility.
HA A-side
A complete Active/Standby configuration for replica A. Both replicas share gateway_id, the state-encryption key, and a signed license listing both replica IDs; everything else is per-replica. storage.peer.replica_id names the other replica, and the peer channels are private to the pair — publish only the client listener.
gateway_id: gw-acme-production
api:
http:
enabled: true
listen: "10.20.0.10:8080"
advertise_url: "http://gateway-a.internal:8080"
allow_insecure_http: true
auth:
mode: none
principal_id: local-operator
allowed_license_type: phocol
operator: true
storage:
directory: /opt/particle_horizon/local_data/keystone-gateway/state
encryption_key_file: /opt/particle_horizon/local_config/keystone-gateway/state.key
peer:
replica_id: gateway-b
listen: "10.20.0.10:9443"
target: "10.20.0.11:9443"
reconcile_listen: "10.20.0.10:9543"
reconcile_target: "10.20.0.11:9543"
tls:
cert_file: /opt/particle_horizon/local_config/keystone-gateway/peer.crt
key_file: /opt/particle_horizon/local_config/keystone-gateway/peer.key
ca_file: /opt/particle_horizon/local_config/keystone-gateway/peer-ca.crt
license: { file: /opt/particle_horizon/local_config/keystone-gateway/gateway-license.json }
ha: { enabled: true, replica_id: gateway-a, bootstrap_expect: 2, peer_loss_timeout_seconds: 5 }
leases: { default_ttl_seconds: 120, min_ttl_seconds: 30, max_ttl_seconds: 300, max_clock_skew_seconds: 5, expiry_sweep_seconds: 15 }
reports: { directory: /opt/particle_horizon/local_data/keystone-gateway/reports, retention_days: 90 }
logging: { level: info, format: json }
Peer traffic always uses mutual TLS: each certificate must chain to ca_file, carry a CN matching the peer identity configured on the other node, and carry a SAN matching the address that node targets. This example uses a private HTTP client listener for brevity; for production TLS, enable api.https, set its TLS files, use api.auth.mode: mtls, and disable api.http.
HA B-side delta
Copy the A-side configuration above, then swap all local and target peer values, update the client address, and set unique replica IDs:
api:
http: { enabled: true, listen: "10.20.0.11:8080", advertise_url: "http://gateway-b.internal:8080", allow_insecure_http: true }
storage:
peer:
replica_id: gateway-a
listen: "10.20.0.11:9443"
target: "10.20.0.10:9443"
reconcile_listen: "10.20.0.11:9543"
reconcile_target: "10.20.0.10:9543"
ha: { enabled: true, replica_id: gateway-b, bootstrap_expect: 2, peer_loss_timeout_seconds: 5 }
Telemetry and air gap
telemetry:
enabled: true
protocol: grpc
otlp_endpoint: "https://otel-collector.internal:4317"
ca_file: /opt/particle_horizon/local_config/keystone-gateway/otel-ca.crt
export_timeout_seconds: 10
For air-gapped use, omit telemetry or set enabled: false; no external connectivity is needed for license verification or leasing.