Tillered Docs

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: 5

Cluster entry

FieldTypeDescription
cluster_idstringCluster identifier (clu_ prefix)
customer_idstringCustomer identifier from the license (cust_ prefix)
client_idstringShared OAuth client ID (cli_ prefix)
client_secretstringShared OAuth client secret (sec_ prefix)
peersarrayPeers in this cluster
default_peerstringPeer ID used by default; falls back to the first peer when empty
namestringOptional human-friendly alias
descriptionstringOptional longer description

Peer entry

FieldTypeDescription
peer_idstringPeer identifier (peer_ prefix)
endpointsarrayOrdered list of agent API URLs; the CLI tries them in order and remembers the last working one
urlstringDeprecated single-endpoint field, kept for older configs. endpoints wins when both are set
namestringOptional human-friendly alias
client_idstringOptional per-peer OAuth client ID; falls back to the cluster credential
client_secretstringOptional per-peer OAuth client secret; falls back to the cluster credential

Preferences

Global CLI preferences. Every key is optional; defaults apply when unset.

FieldTypeDefaultDescription
output_formatstringtableDefault output format: table, json, or yaml. Overridden by --output
colorbooleantrueColored terminal output. Disabled automatically when NO_COLOR is set
timeoutinteger30Default request timeout in seconds. Overridden by --timeout
cache_ttlinteger3600Completion cache TTL in seconds
auto_failoverbooleanfalseReserved; not yet implemented
backup_retentioninteger5Number 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 file

Security

The config file holds credentials in plaintext. Restrict its permissions:

chmod 600 ~/.config/arctic/config.yaml

For CI/CD, prefer environment variables over a checked-in config:

export ARCTIC_URL=http://agent:8080
export ARCTIC_TOKEN=eyJ...
arctic peers list

Compose 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

FieldTypeRequiredDescription
versionstringYesSchema version; must be v1
licensestringNoPath to the license file, relative to the config file location
requiresobjectNoVersion constraints every peer must satisfy before apply or diff proceeds
serverobjectNoDesignated server peer for centralized operations. Absent means fully decentralized
peersarrayYesPeer definitions
servicesarrayNoService definitions

requires

Version constraints checked after pre-flight connectivity and before diff or apply. Skip with --skip-requires.

FieldTypeDescription
agentstringConstraint 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.

FieldTypeRequiredDescription
peerstringYesName of the primary server peer; must reference a peer in the peers list
fallback_peerstringNoSingle fallback used only when the primary is unreachable at the connection level
featuresobjectNoReserved server-side feature flags (webui, stun)
server:
  peer: hub
  fallback_peer: hub-standby

Peer configuration

FieldTypeRequiredDescription
namestringYesUnique identifier for this peer; referenced by services
descriptionstringNoFree-form description shown in operator output; not gossiped
typestringNoPeer role: agent (default) or server
api_accessstringNoAPI exposure: full (default) or internal
endpointsarrayYes*Ordered list of addresses; first responder wins
addressstringNoDeprecated 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

FieldTypeRequiredDescription
namestringYesUnique identifier for this service
source_peerstringYesName of the source peer (must exist in peers)
target_peerstringYesName of the target peer (must exist in peers)
transport_typestringYesTunnel protocol: tcp or kcp
fully_transparentboolNoFully transparent proxying mode (default false)
interfaceobjectNoMACVLAN interface configuration
qosobjectNoQuality-of-service settings
routesarrayNoRouting 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

FieldTypeRequiredDescription
enabledboolYesCreate a MACVLAN interface for this service
vlan_idintegerNoIEEE 802.1Q VLAN tag; valid range 1-4094 (0 and 4095 reserved). Omit for untagged
ipv4stringNoDesired IPv4 address in CIDR notation (e.g. 10.0.0.1/24). Omit for DHCP
macstringNoHardware 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.

FieldTypeDescription
bandwidth_limit_mbpsuint64Maximum bandwidth in Mbps; 0 means unlimited (no shaping or ceiling)
default_rtt_msuint64Seed round-trip time in milliseconds used to tune shaping; 0 uses the system default
disable_auto_rttboolDisable automatic RTT latency probing for this link
memlimit_cap_mbuint64Cap 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

FieldTypeRequiredDescription
source_cidrstringConditionalSource network in CIDR notation
dest_cidrstringConditionalDestination network in CIDR notation
priorityuint64YesTie-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:

ContextOrder
Rootversion, license, requires, server, peers, services
Peername, description, type, api_access, address, endpoints
Servicename, source_peer, target_peer, transport_type, fully_transparent, interface, qos, routes
Interfaceenabled, vlan_id, ipv4, mac
QoSbandwidth_limit_mbps, default_rtt_ms, disable_auto_rtt, memlimit_cap_mb
Routesource_cidr, dest_cidr, priority
Requiresagent
Serverpeer, 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

FieldDescription
versionRequired; must be v1
peersAt least one peer is required
peers[N].nameRequired and unique
peers[N].endpointsAt least one endpoint required (via endpoints or address)
peers[N].typeMust be agent or server
peers[N].api_accessMust be full or internal; at least one peer must be full
server.peerRequired when the server block is present; must reference a peer
server.fallback_peerMust differ from server.peer and reference a peer
services[N].nameRequired and unique
services[N].source_peerRequired; must reference a peer
services[N].target_peerRequired; must reference a peer; must differ from source
services[N].transport_typeRequired; must be tcp or kcp
services[N]Must define interface (enabled) or routes
services[N].interface.ipv4Valid CIDR; cannot be 0.0.0.0/0; unique per source peer
services[N].interface.vlan_idMust be in range 1-4094
services[N].interface.macValid 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].priorityUnique within the service

Warnings

RuleFieldDescription
deprecated-addresspeers[N].addressaddress is deprecated; use endpoints
address-ignoredpeers[N].addressBoth address and endpoints set; address is ignored
interface-and-routesservices[N]Service has both interface and routes; typically use one
mac-not-locally-administeredservices[N].interface.macExplicit MAC looks vendor-burned
mac-multicastservices[N].interface.macExplicit MAC has the multicast bit set
server-features-need-type-serverserver.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: 100

MACVLAN 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: 100

Policy 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

On this page