Configuration reference
Reference for Arctic CLI and compose configuration files
This page documents two file formats: the CLI configuration file that stores your connection details, and the compose configuration that declares the desired state of a cluster. For a task-oriented walkthrough of compose, see the compose guide.
CLI configuration
The Arctic CLI stores cluster connection details and global preferences in a YAML file.
File location
Default: ~/.config/arctic/config.yaml (or $XDG_CONFIG_HOME/arctic/config.yaml).
Override with the --config flag or the ARCTIC_CONFIG environment variable.
Format
Peers are grouped by cluster. Each cluster carries a shared OAuth credential that works across all of its peers.
current_cluster: clu_01HABCDEF456...
clusters:
clu_01HABCDEF456...:
cluster_id: clu_01HABCDEF456...
customer_id: cust_xyz789...
client_id: cli_01HXYZ...
client_secret: sec_abc123...
peers:
- peer_id: peer_01HXYZABC123...
name: agent-a
endpoints:
- http://192.168.1.10:8080
- peer_id: peer_01HXYZDEF789...
name: agent-b
endpoints:
- http://192.168.1.20:8080
default_peer: peer_01HXYZABC123...
name: Production
preferences:
output_format: table
timeout: 30
cache_ttl: 3600
backup_retention: 5Cluster entry
| Field | Type | Description |
|---|---|---|
cluster_id | string | Cluster identifier (clu_ prefix) |
customer_id | string | Customer identifier from the license (cust_ prefix) |
client_id | string | Shared OAuth client ID (cli_ prefix) |
client_secret | string | Shared OAuth client secret (sec_ prefix) |
peers | array | Peers in this cluster |
default_peer | string | Peer ID used by default; falls back to the first peer when empty |
name | string | Optional human-friendly alias |
description | string | Optional longer description |
Peer entry
| Field | Type | Description |
|---|---|---|
peer_id | string | Peer identifier (peer_ prefix) |
endpoints | array | Ordered list of agent API URLs; the CLI tries them in order and remembers the last working one |
url | string | Deprecated single-endpoint field, kept for older configs. endpoints wins when both are set |
name | string | Optional human-friendly alias |
client_id | string | Optional per-peer OAuth client ID; falls back to the cluster credential |
client_secret | string | Optional per-peer OAuth client secret; falls back to the cluster credential |
Preferences
Global CLI preferences. Every key is optional; defaults apply when unset.
| Field | Type | Default | Description |
|---|---|---|---|
output_format | string | table | Default output format: table, json, or yaml. Overridden by --output |
color | boolean | true | Colored terminal output. Disabled automatically when NO_COLOR is set |
timeout | integer | 30 | Default request timeout in seconds. Overridden by --timeout |
cache_ttl | integer | 3600 | Completion cache TTL in seconds |
auto_failover | boolean | false | Reserved; not yet implemented |
backup_retention | integer | 5 | Number of .arctic/backup/ entries compose apply keeps before pruning the oldest. Valid range 1-100 (0 means "use the default") |
Managing the config
arctic config current # show the current cluster
arctic config use-cluster Production # switch clusters
arctic config list # list clusters and peers
arctic config view # print the full config fileSecurity
The config file holds credentials in plaintext. Restrict its permissions:
chmod 600 ~/.config/arctic/config.yamlFor CI/CD, prefer environment variables over a checked-in config:
export ARCTIC_URL=http://agent:8080
export ARCTIC_TOKEN=eyJ...
arctic peers listCompose configuration
The compose file declares the desired state of an Arctic cluster in YAML. Apply it with arctic compose apply.
File format
Compose files use schema version v1. The file can be named anything, but cluster.yaml is the convention. Two top-level optional blocks, requires and server, were added in v1.4.0; both are backwards-compatible.
Root structure
| Field | Type | Required | Description |
|---|---|---|---|
version | string | Yes | Schema version; must be v1 |
license | string | No | Path to the license file, relative to the config file location |
requires | object | No | Version constraints every peer must satisfy before apply or diff proceeds |
server | object | No | Designated server peer for centralized operations. Absent means fully decentralized |
peers | array | Yes | Peer definitions |
services | array | No | Service definitions |
requires
Version constraints checked after pre-flight connectivity and before diff or apply. Skip with --skip-requires.
| Field | Type | Description |
|---|---|---|
agent | string | Constraint on every peer's running agent version |
Constraint syntax: vX.Y.Z (exact), ~vX.Y.Z (patch range), or ^vX.Y.Z (minor range).
requires:
agent: "^v1.4.0"server
Declares a designated server peer for centralized operations such as the cluster apply lock. The peer still gossips like any other; "server" is an entry-point role, not a state authority. Omit this block for a fully decentralized cluster.
| Field | Type | Required | Description |
|---|---|---|---|
peer | string | Yes | Name of the primary server peer; must reference a peer in the peers list |
fallback_peer | string | No | Single fallback used only when the primary is unreachable at the connection level |
features | object | No | Reserved server-side feature flags (webui, stun) |
server:
peer: hub
fallback_peer: hub-standbyPeer configuration
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Unique identifier for this peer; referenced by services |
description | string | No | Free-form description shown in operator output; not gossiped |
type | string | No | Peer role: agent (default) or server |
api_access | string | No | API exposure: full (default) or internal |
endpoints | array | Yes* | Ordered list of addresses; first responder wins |
address | string | No | Deprecated single endpoint; prefer endpoints |
*At least one endpoint is required: either endpoints (preferred) or the deprecated address. Each endpoint may be a bare host (10.0.0.2), host:port (10.0.0.2:9090), or a full URL (https://node-a.internal).
An internal peer rejects user-facing endpoints; at least one peer in the cluster must use api_access: full, or the cluster is unmanageable via the API.
Peers cannot be deleted via compose. Removing a peer from the file does not remove it from the cluster. Use arctic peers delete.
Service configuration
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Unique identifier for this service |
source_peer | string | Yes | Name of the source peer (must exist in peers) |
target_peer | string | Yes | Name of the target peer (must exist in peers) |
transport_type | string | Yes | Tunnel protocol: tcp or kcp |
fully_transparent | bool | No | Fully transparent proxying mode (default false) |
interface | object | No | MACVLAN interface configuration |
qos | object | No | Quality-of-service settings |
routes | array | No | Routing rules |
A service needs a routing mode: either interface with enabled: true (MACVLAN interface mode) or one or more routes (policy/CIDR routes mode). source_peer and target_peer must differ. Setting both interface (enabled) and routes on the same service is allowed but triggers an advisory warning, since you typically use one or the other.
Interface configuration
| Field | Type | Required | Description |
|---|---|---|---|
enabled | bool | Yes | Create a MACVLAN interface for this service |
vlan_id | integer | No | IEEE 802.1Q VLAN tag; valid range 1-4094 (0 and 4095 reserved). Omit for untagged |
ipv4 | string | No | Desired IPv4 address in CIDR notation (e.g. 10.0.0.1/24). Omit for DHCP |
mac | string | No | Hardware address mode (see below) |
mac values:
""(omitted): the agent generates a MAC at runtime; it may change when the service is recreated."auto": a deterministic MAC derived from the cluster ID, source peer name, and service name. Stable across applies as long as those names do not change.- explicit MAC: a lowercase colon-separated hex address, e.g.
02:ab:cd:ef:12:34. Must parse cleanly.
ipv4 cannot be 0.0.0.0/0, and IPv4 addresses must be unique per source peer across services.
QoS configuration
bandwidth_limit_mbps applies to both transports, but differently. On a tcp
service it drives the full traffic shaper (holds the rate, queues flows fairly,
and keeps latency low under load). On a kcp service it acts as a bandwidth
ceiling that caps the link in both directions, without the shaper's fair
queueing or latency control. The remaining fields below (default_rtt_ms,
disable_auto_rtt, memlimit_cap_mb) tune the TCP shaper only and have no
effect on a KCP service.
| Field | Type | Description |
|---|---|---|
bandwidth_limit_mbps | uint64 | Maximum bandwidth in Mbps; 0 means unlimited (no shaping or ceiling) |
default_rtt_ms | uint64 | Seed round-trip time in milliseconds used to tune shaping; 0 uses the system default |
disable_auto_rtt | bool | Disable automatic RTT latency probing for this link |
memlimit_cap_mb | uint64 | Cap the memory the shaper may use, in megabytes; 0 means no cap |
memlimit_cap_mb is useful on memory-constrained hosts to keep the shaper from allocating excessive RAM.
Route configuration
| Field | Type | Required | Description |
|---|---|---|---|
source_cidr | string | Conditional | Source network in CIDR notation |
dest_cidr | string | Conditional | Destination network in CIDR notation |
priority | uint64 | Yes | Tie-breaker; lower value = higher priority |
At least one of source_cidr or dest_cidr is required. Both cannot be 0.0.0.0/0. Priorities must be unique within a service.
Routes are matched by specificity first, with priority only breaking ties. Specificity order, most specific first: MACVLAN interface match, source plus destination CIDR, source-only CIDR, destination-only CIDR.
Canonical key ordering
arctic compose fmt reorders keys to a canonical order:
| Context | Order |
|---|---|
| Root | version, license, requires, server, peers, services |
| Peer | name, description, type, api_access, address, endpoints |
| Service | name, source_peer, target_peer, transport_type, fully_transparent, interface, qos, routes |
| Interface | enabled, vlan_id, ipv4, mac |
| QoS | bandwidth_limit_mbps, default_rtt_ms, disable_auto_rtt, memlimit_cap_mb |
| Route | source_cidr, dest_cidr, priority |
| Requires | agent |
| Server | peer, fallback_peer, features |
Validation rules
Validate a file with arctic compose validate cluster.yaml. Errors block apply; warnings are advisory unless you pass --strict.
Errors
| Field | Description |
|---|---|
version | Required; must be v1 |
peers | At least one peer is required |
peers[N].name | Required and unique |
peers[N].endpoints | At least one endpoint required (via endpoints or address) |
peers[N].type | Must be agent or server |
peers[N].api_access | Must be full or internal; at least one peer must be full |
server.peer | Required when the server block is present; must reference a peer |
server.fallback_peer | Must differ from server.peer and reference a peer |
services[N].name | Required and unique |
services[N].source_peer | Required; must reference a peer |
services[N].target_peer | Required; must reference a peer; must differ from source |
services[N].transport_type | Required; must be tcp or kcp |
services[N] | Must define interface (enabled) or routes |
services[N].interface.ipv4 | Valid CIDR; cannot be 0.0.0.0/0; unique per source peer |
services[N].interface.vlan_id | Must be in range 1-4094 |
services[N].interface.mac | Valid lowercase colon-hex MAC or the literal auto |
services[N].routes[M] | At least one of source_cidr or dest_cidr; not both 0.0.0.0/0 |
services[N].routes[M].priority | Unique within the service |
Warnings
| Rule | Field | Description |
|---|---|---|
deprecated-address | peers[N].address | address is deprecated; use endpoints |
address-ignored | peers[N].address | Both address and endpoints set; address is ignored |
interface-and-routes | services[N] | Service has both interface and routes; typically use one |
mac-not-locally-administered | services[N].interface.mac | Explicit MAC looks vendor-burned |
mac-multicast | services[N].interface.mac | Explicit MAC has the multicast bit set |
server-features-need-type-server | server.features.* | Server features set but the server peer is not type: server |
Examples
Minimal configuration
version: v1
peers:
- name: peer-1
endpoints:
- 192.168.1.10:8080
- name: peer-2
endpoints:
- 192.168.1.20:8080
services:
- name: tunnel-1-to-2
source_peer: peer-1
target_peer: peer-2
transport_type: tcp
routes:
- dest_cidr: 10.0.0.0/8
priority: 100MACVLAN interface mode
version: v1
license: ./license.json
requires:
agent: "^v1.4.0"
peers:
- name: datacenter-west
description: Primary west DC node
endpoints:
- 10.0.1.10:8080
- name: datacenter-east
endpoints:
- 10.0.2.10:8080
- 10.0.2.11:8080
services:
- name: west-to-east
source_peer: datacenter-west
target_peer: datacenter-east
transport_type: tcp
fully_transparent: true
interface:
enabled: true
ipv4: 10.100.0.1/24
mac: auto
qos:
bandwidth_limit_mbps: 100Policy routes mode with KCP
version: v1
license: ./license.json
peers:
- name: site-a
endpoints:
- 192.168.1.10:8080
- name: site-b
endpoints:
- 192.168.2.10:8080
services:
- name: kcp-tunnel
source_peer: site-a
target_peer: site-b
transport_type: kcp
routes:
- source_cidr: 0.0.0.0/0
dest_cidr: 10.20.0.0/16
priority: 100
- dest_cidr: 172.16.0.0/12
priority: 200