Device configuration
A device has one stable ingress profile. Its default Internet egress is a hub-side policy and can change without editing the client. Private-network routes are destination-based and work in addition to that egress.
devices[].id
- Type
string- Required
- Yes
- Default
- None
- Validation
- Unique; 1–32 characters matching lowercase letters, digits, and internal hyphens.
- Secret classification
- No; identifier metadata.
- Side effects
- Names peers, bot callbacks, revocations, profile-key files, and policies.
- Minimal example
laptop
devices[].address
- Type
IPv4 host CIDR string- Required
- Yes
- Default
- None
- Validation
- The parser accepts a /32 or /128 host route inside client_cidr; not the network, IPv4 broadcast, or dns_address; unique. The supported deployment is IPv4 /32 only.
- Secret classification
- No; topology metadata.
- Side effects
- Becomes the peer address and IPv4 policy source identity. Current nftables and host provisioning are IPv4-only, so a parsed /128 is not an operational IPv6 promise.
- Minimal example
10.80.0.2/32
devices[].public_key
- Type
base64 string- Required
- Yes
- Default
- None
- Validation
- Unique and decodes to a 32-byte X25519 public key.
- Secret classification
- No; the client private half must remain secret.
- Side effects
- Admits the AmneziaWG peer and participates in REALITY credential derivation.
- Minimal example
TE5crMJPBmCr2bF/uSbHqAlTAHKQwLKMs0RQxfQ0LU4=
devices[].egress
- Type
string- Required
- Yes
- Default
- None
- Validation
- Either direct or an existing, enabled role=egress tunnel that permits this device.
- Secret classification
- No; policy metadata.
- Side effects
- Marks this device's non-private traffic for the selected path.
- Minimal example
direct
The following profiles shape is decoded only to produce a migration error. It is not accepted by validation; remove it and use the four fields above.
devices[].profiles[]
- Type
deprecated array- Required
- Must be absent
- Default
- Empty
- Validation
- Any non-empty value is rejected as a pre-M5 configuration.
- Secret classification
- May contain private keys; remove and rotate them.
- Side effects
- Blocks validation and deployment.
- Minimal example
profiles: []
devices[].profiles[].id
- Type
deprecated string- Required
- Must be absent
- Default
- None
- Validation
- Parent profiles list is rejected.
- Secret classification
- No.
- Side effects
- Blocks validation when present inside a non-empty legacy profile.
- Minimal example
legacy-profile
devices[].profiles[].egress
- Type
deprecated string- Required
- Must be absent
- Default
- None
- Validation
- Parent profiles list is rejected.
- Secret classification
- No.
- Side effects
- Blocks validation when present inside a non-empty legacy profile.
- Minimal example
direct
devices[].profiles[].address
- Type
deprecated string- Required
- Must be absent
- Default
- None
- Validation
- Parent profiles list is rejected.
- Secret classification
- No.
- Side effects
- Blocks validation when present inside a non-empty legacy profile.
- Minimal example
10.80.0.2/32
devices[].profiles[].client_public_key
- Type
deprecated string- Required
- Must be absent
- Default
- None
- Validation
- Parent profiles list is rejected.
- Secret classification
- Public half only.
- Side effects
- Blocks validation when present inside a non-empty legacy profile.
- Minimal example
deprecated
devices[].profiles[].client_private_key
- Type
deprecated secret string- Required
- Must be absent
- Default
- None
- Validation
- Parent profiles list is rejected.
- Secret classification
- Yes; rotate if this legacy field was exposed.
- Side effects
- Blocks validation; a private key must never live in hub YAML.
- Minimal example
REDACTED
CLI-generated profiles are written 0600 and their private key is not retained. Bot-issued profiles deliberately retain the private key at /var/lib/vpn-hub/device-profiles/<id>.key, mode 0600 inside a 0700 directory, so the bot can deliver the same profile again.
Use only IPv4 /32 device addresses. Although structural validation currently accepts IPv6 /128, the generated packet filter uses IPv4 address sets and the supported host disables IPv6; deploying /128 is unsupported.
Next: Tunnel configuration and Client ACLs.