Tillered Docs

CLI reference

Complete reference for the Arctic command-line interface

The Arctic CLI (arctic) is a command-line tool for managing Arctic agents and clusters. It follows the pattern arctic <command> [subcommand] [flags].

bootstrap

Initialize an Arctic agent with a license file.

Synopsis

arctic bootstrap --url <agent-url> --license-file <path> [flags]

Description

The bootstrap command initializes an Arctic agent with a license. This process:

  1. Uploads the license to the agent
  2. Generates a unique peer identity (Ed25519 key pair)
  3. Creates OAuth2 credentials for API access
  4. Saves the configuration to your CLI config file

Required flags

FlagDescription
--urlAgent URL (e.g., http://192.168.1.10:8080)
--license-filePath to the license JSON file

Optional flags

FlagDefaultDescription
--nameHuman-readable name for this peer

Output

On success, displays:

Peer ID:        01HXYZ...
Cluster ID:     01HABC...
Client ID:      cl_01HXYZ...
License ID:     lic_abc123...
Expires:        2025-12-31 23:59:59 UTC
Max Nodes:      10
Max Services:   100

Configuration saved to ~/.config/arctic/config.yaml
Set as current cluster: 01HABC...

Examples

# Basic bootstrap
arctic bootstrap \
  --url http://192.168.1.10:8080 \
  --license-file license.json

# With name
arctic bootstrap \
  --url http://192.168.1.10:8080 \
  --license-file license.json \
  --name "prod-svr-1"

Errors

ErrorDescription
--license-file is requiredMissing license file flag
--url is required for bootstrapMissing agent URL
failed to read license fileLicense file not found or invalid JSON
license has expiredLicense expiration date has passed
agent is already bootstrappedAgent was previously initialized

Notes

  • An agent can only be bootstrapped once. To re-bootstrap, you must reset the agent's database.
  • Credentials are saved automatically to your CLI config file.

cluster

Manage cluster operations.

Synopsis

arctic cluster <subcommand> [flags]

Subcommands

SubcommandDescription
initInitialize cluster
identityShow cluster identity
syncTrigger synchronization
statusShow gossip status for diagnostics

cluster init

Initialize a cluster for legacy upgraded agents.

arctic cluster init [--force]
FlagDescription
--forceForce reinitialize even if cluster exists

Required scope: urn:tillered:arctic:admin

Cluster initialized
Cluster ID:       01HABC...
Created By:       01HXYZ...
Oldest Peer:      01HXYZ...
Was Created:      true

Notes:

  • Only needed for agents upgraded from older versions
  • New agents have clusters initialized during bootstrap
  • Use --force to regenerate the cluster ID (destroys existing cluster state)

cluster identity

Show the cluster identity of a peer. No authentication required (public endpoint).

arctic cluster identity
Peer ID:     peer_01KBYMHC35F0N070F3XXMEZAZR
Public Key:  qnGyPtol7lqzLYU3989eaC+K4xda0w9KXlcEOM9cSBQ=
License ID:  lic_01KB45EYP1VJ1RZEGJDPKJQ9V4
Cluster ID:  clu_01KBYMHMRJ92E090P50VRKG4ZC
Version:     v0.1.0

Use -j for JSON output:

arctic cluster identity -j
{
  "peer_id": "peer_01KBYMHC35F0N070F3XXMEZAZR",
  "public_key": "qnGyPtol7lqzLYU3989eaC+K4xda0w9KXlcEOM9cSBQ=",
  "license_id": "lic_01KB45EYP1VJ1RZEGJDPKJQ9V4",
  "cluster_id": "clu_01KBYMHMRJ92E090P50VRKG4ZC",
  "version": "v0.1.0"
}

Use cases:

  • Verify peer identity before adding
  • Check license ID matches your cluster
  • Retrieve public key for verification

cluster sync

Trigger cluster synchronization. Required scope: urn:tillered:arctic:admin

arctic cluster sync

Triggers immediate:

  1. Gossip protocol heartbeats to all peers
  2. Configuration regeneration
  3. Subsystem processing (network, firewall, etc.)

Use cases:

  • Force configuration update after changes
  • Speed up propagation of new peers
  • Troubleshoot synchronization issues

cluster status

Show gossip status for cluster diagnostics. Required scope: urn:tillered:arctic:admin

arctic cluster status
Gossip Status
-------------
Local Peer:        peer_01KBYMHC35F0N070F3XXMEZAZR
Cluster ID:        clu_01KBYMHMRJ92E090P50VRKG4ZC

Peer Status:
  peer_01KBYMD32Z2RVDE3G5Y9M530QR:
    Last Seen:     2025-12-09 10:15:30 UTC
    Status:        healthy
    Registry Hash: a1b2c3d4...

Registry:
  Services:        5
  Routes:          12
  Hash:            e5f6g7h8...

Use -j for JSON output. Use cases:

  • Diagnose cluster synchronization issues
  • Verify peer connectivity and health
  • Check registry hash for drift detection
  • Monitor gossip protocol state

completion

Generate shell completion scripts for Arctic CLI.

Synopsis

arctic completion <shell>

Arguments

ArgumentDescription
shellShell type: bash, zsh, or fish

Supported shells

Bash:

# Add to ~/.bashrc
source <(arctic completion bash)

# Or save to completions directory
arctic completion bash > /etc/bash_completion.d/arctic

Zsh:

# Add to ~/.zshrc
source <(arctic completion zsh)

# Or for Oh My Zsh, save to completions directory
arctic completion zsh > ~/.oh-my-zsh/completions/_arctic

Fish:

# Save to Fish completions directory
arctic completion fish > ~/.config/fish/completions/arctic.fish

Features

Shell completion provides:

  • Command completion: Type arctic pe<TAB> to complete to peers
  • Subcommand completion: Type arctic peers l<TAB> to complete to list
  • Flag completion: Type arctic peers list --<TAB> to see available flags
  • Value completion: Peer IDs, service IDs, and other values are completed from cache

Example session

$ arctic <TAB>
bootstrap    cluster      completion   config
health       license      peers        routes
services

$ arctic peers <TAB>
add       delete    get       list      remove-self update

$ arctic peers list --<TAB>
--local         --remote        --client-id     --client-secret
--config        --context       --debug         --insecure
--json          --no-headers    --output        --quiet
--timeout       --token         --url           --yes
-c              -j              -o              -q              -y

Errors

ErrorDescription
shell type requiredMissing shell argument
unsupported shellShell not bash, zsh, or fish

compose

Manage Arctic clusters using declarative YAML configuration files.

Synopsis

arctic compose <subcommand> <config-file> [flags]

Description

The compose command is the recommended way to deploy and manage Arctic clusters. It provides Infrastructure as Code (IaC) capabilities, allowing you to define your cluster state in a YAML file and apply it declaratively.

Subcommands

SubcommandDescription
applyApply cluster configuration from YAML
diffShow differences between config and cluster state
exportExport cluster configuration to YAML
fmtFormat configuration files
initGenerate starter configuration template
validateValidate YAML syntax and schema

compose apply

Apply cluster configuration from a YAML file.

arctic compose apply <config-file> [flags]
FlagDescriptionDefault
--dry-runShow changes without applyingfalse
--pruneDelete resources not in configfalse
--ignore-unreachableSkip unreachable peersfalse
--license-fileLicense file for bootstrap
--credentials-fileWrite credentials to JSON file on bootstrap
--env-fileWrite credentials to .env file on bootstrap
--save-configSave cluster to CLI config and set as currenttrue
--skip-validateSkip pre-validation checks (not recommended)false
--strictTreat validation warnings as errorsfalse

Required scope: urn:tillered:arctic:admin

# Validate and apply configuration
arctic compose apply cluster.yaml

# Preview changes without applying
arctic compose apply cluster.yaml --dry-run

# Apply and prune resources not in config
arctic compose apply cluster.yaml --prune

# Apply with new license and save credentials
arctic compose apply cluster.yaml \
  --license-file license.json \
  --credentials-file creds.json

# Apply without saving to CLI config
arctic compose apply cluster.yaml --save-config=false

Example output:

Validating cluster.yaml...
OK - Configuration valid

Checking cluster state...
  peer-a: bootstrapped
  peer-b: bootstrapped

Planning changes...
  + Create service: web-tunnel (peer-a -> peer-b)
  + Create route: 0.0.0.0/0 -> 10.0.0.0/8

Applying changes...
  [OK] Created service web-tunnel
  [OK] Created route 10.0.0.0/8

Apply complete: 1 service created, 1 route created

compose diff

Show differences between configuration file and current cluster state.

arctic compose diff <config-file>

Required scope: urn:tillered:arctic:peers.read, urn:tillered:arctic:services.read, urn:tillered:arctic:routes.read

Example output:

Comparing cluster.yaml with cluster state...

Services:
  ~ web-tunnel: bandwidth_limit_mbps changed (0 -> 100)
  + new-tunnel: will be created
  - old-tunnel: will be deleted (with --prune)

Routes:
  + 10.0.0.0/8: will be added to web-tunnel

compose export

Export current cluster configuration to YAML format.

arctic compose export [flags]
FlagDescription
--fileOutput file path (defaults to stdout)

Required scope: urn:tillered:arctic:peers.read, urn:tillered:arctic:services.read, urn:tillered:arctic:routes.read

# Export to stdout
arctic compose export

# Export to file
arctic compose export --file cluster.yaml

compose fmt

Format a cluster configuration file with consistent formatting.

arctic compose fmt <config-file> [flags]
FlagDescriptionDefault
--writeWrite formatted output back to filefalse
--checkCheck if file is formatted (exit 1 if not)false

The fmt command normalizes YAML configuration files to a canonical format:

  • Reorders keys to canonical order (see Compose configuration)
  • Uses 2-space indentation
  • Preserves comments
# Output formatted config to stdout
arctic compose fmt cluster.yaml

# Format file in place
arctic compose fmt cluster.yaml --write

# Check if file is formatted (for CI)
arctic compose fmt cluster.yaml --check

compose init

Generate a starter cluster configuration template.

arctic compose init [flags]
FlagDescriptionDefault
--fileOutput file path (defaults to stdout)
--minimalGenerate minimal valid configfalse
--exampleGenerate full example with commentstrue
# Generate example config to stdout
arctic compose init

# Generate example config to file
arctic compose init --file cluster.yaml

# Generate minimal config
arctic compose init --minimal

Minimal output:

version: v1

peers:
  - name: peer-1
    address: 192.168.1.10:8080

services: []

compose validate

Validate cluster configuration YAML syntax and schema.

arctic compose validate <config-file> [flags]
FlagDescriptionDefault
--strictTreat warnings as errorsfalse

Valid output:

Validating cluster.yaml...
OK - Configuration valid

Schema version: v1
Peers: 2
Services: 1
Routes: 1

Invalid output:

Validating cluster.yaml...
ERROR - Configuration invalid

Errors:
  - services[0]: source_peer "unknown" not found in peers list
  - services[0].routes[0]: invalid source_cidr "invalid"

Configuration schema quick reference

version: v1                    # Schema version (required)
license: path/to/license.json  # License file path (optional)
peers:                         # Peer definitions (required)
  - name: string               # Unique peer name
    address: host:port         # Agent address
services:                      # Service definitions (optional)
  - name: string               # Unique service name
    source_peer: string        # Source peer name
    target_peer: string        # Target peer name
    transport_type: tcp|kcp    # Transport protocol
    fully_transparent: bool    # Full transparency mode (default: false)
    interface:                 # MACVLAN interface config (optional)
      enabled: bool
      ipv4: CIDR
    qos:                       # QoS settings (optional)
      bandwidth_limit_mbps: uint64
    routes:                    # Routing rules (optional)
      - source_cidr: CIDR
        dest_cidr: CIDR
        priority: uint64

A service requires either interface (enabled) or routes to be functional.

Exit codes

CodeCondition
0Success
1General error
2Validation error
3Configuration error
4Connection error

config

Manage Arctic CLI configuration.

Synopsis

arctic config <subcommand> [flags]

Subcommands

SubcommandDescription
listList all clusters and peers
viewView current configuration
currentShow current context
use-clusterSet current cluster
add-peerAdd peer to a cluster
delete-peerDelete peer from cluster configuration

config list

List all clusters and peers in the configuration.

arctic config list
ID                    NAME         URL                           LICENSE    CURRENT
01HXYZABC123...       agent-a      http://192.168.1.10:8080      lic_...    *
01HXYZDEF789...       agent-b      http://192.168.1.20:8080      lic_...

config view

View the full configuration file.

arctic config view

config current

Show the current context.

arctic config current
Cluster ID:      01HABC...
Name:            Production
Customer ID:     cust_...
Peer Count:      3
Default Peer:    01HXYZ...
Default URL:     http://192.168.1.10:8080
Format:          cluster

config use-cluster

Set the current cluster context.

arctic config use-cluster <cluster-id-or-name>
ArgumentDescription
cluster-id-or-nameCluster ID or name to set as current
arctic config use-cluster Production
arctic config use-cluster 01HABCDEF...

config add-peer

Add a peer configuration to a cluster.

arctic config add-peer --peer-id <id> --peer-url <url> [flags]

Required flags:

FlagDescription
--peer-idPeer ID
--peer-urlAgent URL

Optional flags:

FlagDescription
--clusterCluster ID or name (defaults to current cluster)
--nameHuman-readable name for the peer
arctic config add-peer \
  --peer-id 01HXYZ... \
  --peer-url http://192.168.1.30:8080 \
  --name "agent-c" \
  --cluster Production

config delete-peer

Delete a peer from the cluster configuration.

arctic config delete-peer <peer-id-or-name> [flags]
FlagDescription
--clusterCluster ID or name (defaults to current cluster)
arctic config delete-peer agent-c
arctic config delete-peer agent-c --cluster Production

Requires confirmation unless --yes is specified.


docs

Serve the embedded Arctic documentation locally in your browser.

Synopsis

arctic docs [flags]

Description

The docs command starts a local web server and serves the Arctic documentation. This allows you to browse the documentation offline or in environments without internet access.

Flags

FlagDescriptionDefault
--portPort to serve documentation on8888
--no-browserDo not open browser automaticallyfalse

Examples

# Start documentation server
arctic docs

# Custom port
arctic docs --port 9999

# Without opening browser
arctic docs --no-browser

Opens the documentation in your default browser at http://localhost:8888.

Notes

  • The documentation is embedded in the CLI binary
  • No internet connection required
  • Press Ctrl+C to stop the server
  • The server binds to localhost only by default

health

Check Arctic agent health status.

Synopsis

arctic health [flags]

Description

The health command checks the liveness or readiness of Arctic agents. It does not require authentication.

Flags

FlagDescription
--readyzCheck readiness instead of liveness

Examples

# Check current context
arctic health

# Check readiness
arctic health --readyz

# Check specific agent
arctic health --url http://192.168.1.30:8080

# JSON output
arctic health -j

Default output:

Peer ID:     peer_01KBYMHC35F0N070F3XXMEZAZR
Name:        agent-1
URL:         http://192.168.3.251:8080
Status:      ok
Timestamp:   2025-12-09 04:43:41 UTC

JSON output:

{
  "peer_id": "peer_01KBYMHC35F0N070F3XXMEZAZR",
  "name": "agent-1",
  "url": "http://192.168.3.251:8080",
  "status": "ok",
  "timestamp": "2025-12-09 04:43:41 UTC"
}

Exit codes

CodeCondition
0Agent healthy
4Agent unreachable

Scripting example

arctic health
exit_code=$?

case $exit_code in
    0)
        echo "Agent healthy"
        ;;
    4)
        echo "Agent down"
        send_alert "Arctic agent unreachable"
        ;;
    *)
        echo "Unexpected error: $exit_code"
        ;;
esac

Liveness vs readiness

Liveness (/livez) - Default check. Indicates the agent process is running. Returns ok if the agent can respond.

Readiness (/readyz) - Use --readyz flag. Indicates the agent is ready to serve requests. May return not ready during startup or maintenance.

Health checks do not require authentication. They are designed for use by load balancers, monitoring systems, health check scripts, and Kubernetes probes.


license

Manage the Arctic agent license.

Synopsis

arctic license <subcommand> [flags]

Subcommands

SubcommandDescription
statusShow license usage status
updateUpdate license

license status

Show license usage status. Required scope: urn:tillered:arctic:admin

arctic license status
License Information
-------------------
License ID:     lic_abc123...
Customer ID:    cust_xyz789...
Customer Name:  Acme Corp

Validity
--------
Issued:         2024-01-01 00:00:00 UTC
Expires:        2025-12-31 23:59:59 UTC
Status:         Valid (350 days remaining)

Limits
------
Max Nodes:      10
Max Services:   100

Metadata
--------
Issuer:         Tillered
Key ID:         2024Q4
Algorithm:      Ed25519

Use -o json for JSON output.

license update

Update the agent license with a new license file. Required scope: urn:tillered:arctic:admin

arctic license update --license-file <path>
FlagDescription
--license-filePath to new license file
arctic license update --license-file new-license.json
License updated
Customer ID:    cust_xyz789...
License ID:     lic_def456...
Expires:        2026-12-31 23:59:59 UTC
Max Nodes:      20
Max Services:   200

Errors:

ErrorDescription
--license-file is requiredMissing license file flag
failed to read license fileFile not found or invalid
license has expiredNew license is expired
license update failedAPI error

Notes:

  • The new license must be for the same customer
  • All connected peers receive the updated license via gossip
  • Existing services are not affected unless limits decrease

peers

Manage cluster peers.

Aliases: peer

Synopsis

arctic peers <subcommand> [flags]

Subcommands

SubcommandDescription
listList all peers
getGet peer details
addAdd a remote peer
updateUpdate peer metadata
deleteDelete a peer
remove-selfRemove local peer from cluster

peers list

List all peers in the cluster. Required scope: urn:tillered:arctic:peers.read

arctic peers list [flags]
FlagDescription
--localShow only local peers
--remoteShow only remote peers
# List all peers
arctic peers list

# List only remote peers
arctic peers list --remote

# List with detailed JSON output
arctic peers list -j

Default table output:

ID                              NAME                  ADDRESS
peer_01KBYMHC35F0N070F3XXMEZAZR  agent-1               192.168.3.251:8080
peer_01KBYMD32Z2RVDE3G5Y9M530QR  agent-2               10.10.40.95:8080

peers get

Get details of a specific peer. Required scope: urn:tillered:arctic:peers.read

arctic peers get <peer-id>
ID:          peer_01KBYMHC35F0N070F3XXMEZAZR
Name:        agent-1
Public Key:  qnGyPtol7lqzLYU3989eaC+K4xda0w9KXlcEOM9cSBQ=
Is Local:    Yes
Address:     192.168.3.251:8080
Created At:  2025-12-08 09:26:30 UTC

peers add

Add a remote peer to the cluster. Required scope: urn:tillered:arctic:peers.write

arctic peers add <peer-address> [flags]
FlagDescription
--nameHuman-readable name for the peer
# Add a peer
arctic peers add 192.168.1.20:8080

# Add with a name
arctic peers add 192.168.1.20:8080 --name "prod-svr"

# Add with debug output
arctic peers add 192.168.1.20:8080 --debug

Behavior:

  1. Contacts the remote peer's API
  2. Performs handshake (exchanges public keys)
  3. Both peers verify signatures against the license
  4. Peer is added to the local database
  5. Remote peer adds local peer via gossip

Errors:

ErrorDescription
peer URL requiredMissing address argument
peer already exists in clusterDuplicate peer
handshake failedPeer unreachable or validation failed
node limit exceededLicense node limit reached

peers update

Update a peer's metadata. Required scope: urn:tillered:arctic:peers.write

arctic peers update <peer-id> [flags]
FlagDescriptionDefault
--nameHuman-readable name for the peer
--qosEnable QoS for this peertrue
# Update peer name
arctic peers update 01HXYZDEF789... --name "prod-svr-2"

# Disable QoS for a peer
arctic peers update 01HXYZDEF789... --qos=false

peers delete

Delete a peer from the cluster. Required scope: urn:tillered:arctic:peers.write

arctic peers delete <peer-id> [--yes]
# Delete with confirmation prompt
arctic peers delete 01HXYZDEF789...

# Delete without confirmation
arctic peers delete 01HXYZDEF789... --yes

Errors:

ErrorDescription
peer ID requiredMissing peer ID
peer not foundPeer does not exist
cannot delete local peerUse remove-self instead

peers remove-self

Gracefully remove the local peer from the cluster. Required scope: urn:tillered:arctic:admin

arctic peers remove-self [--yes]

Behavior:

  1. Marks the local peer as deactivated
  2. Broadcasts deactivation announcement to cluster
  3. Other peers remove this peer from their databases
  4. Services involving this peer become inactive
arctic peers remove-self --yes
Peer removed from cluster
Peer ID:     01HXYZABC123...
Version:     2
Active:      false

routes

Manage CIDR-based routing rules for services.

Aliases: route

Synopsis

arctic routes <subcommand> --service <service-id> [flags]

Subcommands

SubcommandDescription
listList routes for a service
addAdd a route to a service
updateUpdate a route
deleteDelete a route

routes list

List routes for a service. Required scope: urn:tillered:arctic:services.read

arctic routes list --service <service-id>
ID      PRIORITY  SOURCE CIDR           DEST CIDR
6       100       10.0.0.0/8            192.168.100.0/24
7       200       10.1.0.0/16           192.168.200.0/24

routes add

Add a route to a service. Required scope: urn:tillered:arctic:services.write

arctic routes add --service <service-id> --priority <priority> [flags]
FlagDescription
--serviceService ID (required)
--priorityRoute priority - higher = more preferred (required)
--source-cidrSource CIDR (e.g., 10.0.0.0/8)
--dest-cidrDestination CIDR (e.g., 192.168.100.0/24)
# Source and destination CIDR
arctic routes add --service svc_01HSVCABC123... \
  --priority 100 \
  --source-cidr 10.0.0.0/8 \
  --dest-cidr 192.168.100.0/24

# Destination only
arctic routes add --service svc_01HSVCABC123... \
  --priority 100 \
  --dest-cidr 192.168.100.0/24

Errors:

ErrorDescription
--service is requiredMissing service flag
--priority is requiredMissing priority flag
invalid CIDR notationMalformed CIDR
service not foundService does not exist

routes update

Update a route. Required scope: urn:tillered:arctic:services.write

arctic routes update --service <service-id> --route <route-id> [flags]
FlagDescription
--serviceService ID (required)
--routeRoute ID (required)
--priorityNew priority
--source-cidrNew source CIDR
--dest-cidrNew destination CIDR
# Update priority
arctic routes update --service svc_01HSVCABC123... --route 6 --priority 200

# Update CIDRs
arctic routes update --service svc_01HSVCABC123... --route 6 \
  --source-cidr 10.1.0.0/16 \
  --dest-cidr 192.168.200.0/24

Errors:

ErrorDescription
--service is requiredMissing service flag
--route is requiredMissing route flag
invalid --route value: must be a numberNon-numeric route ID
no fields to updateNo update flags provided
route not foundRoute does not exist

routes delete

Delete a route. Required scope: urn:tillered:arctic:services.write

arctic routes delete --service <service-id> --route <route-id> [--yes]
# Delete with confirmation
arctic routes delete --service svc_01HSVCABC123... --route 6

# Delete without confirmation
arctic routes delete --service svc_01HSVCABC123... --route 6 --yes

Route priority

Routes are evaluated by specificity first, then priority:

  1. Specificity: More specific CIDRs (larger prefix) match first
  2. Priority: When specificity is equal, higher priority wins

Example evaluation order:

PrioritySource CIDRDest CIDROrder
20010.1.0.0/16192.168.100.0/241st (most specific)
10010.0.0.0/8192.168.100.0/242nd
10010.0.0.0/8192.168.0.0/163rd (less specific dest)

services

Manage services for network routing.

Aliases: service

Synopsis

arctic services <subcommand> [flags]

Subcommands

SubcommandDescription
listList services
getGet service details
createCreate a new service
updateUpdate service settings
deleteDelete a service

services list

List services. Required scope: urn:tillered:arctic:services.read

arctic services list [flags]
FlagDescription
--source-peerFilter by source peer ID
--target-peerFilter by target peer ID
--requires-interfaceFilter to services requiring MACVLAN
# List all services
arctic services list

# Filter by target peer
arctic services list --target-peer 01HXYZDEF789...

# JSON output (shorthand)
arctic services list -j

Table output shows a compact view with service configuration flags:

ID                              SOURCE          TARGET          TRANSPORT  FLAGS
svc_01KBYMNEVYN9NC4M3RB3ZGN4RZ  agent-1         agent-2         tcp        I
svc_01KBYMP2220REHB2MSPHT4XJGT  agent-2         agent-1         tcp        I
svc_01KBYMP88A7MBM1KTXBYSFA7VK  agent-2         agent-1         tcp        I
svc_01KBYMP8NZC6MSFBVE8C98AHBX  agent-2         agent-1         tcp        IT

FLAGS: I=interface, T=transparent, Q=qos, -=none

FLAGS Legend:

  • I: Service requires dedicated MACVLAN interface
  • T: Fully transparent mode enabled (no NAT)
  • Q: QoS bandwidth limiting configured
  • -: No special flags set

Use -j or -o json for full detailed output with all fields.

services get

Get details of a specific service. Required scope: urn:tillered:arctic:services.read

arctic services get <service-id>
ID:                     svc_01KBYMNEVYN9NC4M3RB3ZGN4RZ
Source Peer ID:         peer_01KBYMHC35F0N070F3XXMEZAZR
Source Peer Name:       agent-1
Target Peer ID:         peer_01KBYMD32Z2RVDE3G5Y9M530QR
Target Peer Name:       agent-2
Transport:              tcp
Requires Interface:     Yes
Interface MAC:          4A:CC:DB:76:CF:59
Actual Interface IPv4:  192.168.3.219
Fully Transparent:      No
Created At:             2025-12-08 09:28:44 UTC
Updated At:             2025-12-08 09:28:44 UTC
Data Source:            source

If the source peer is unreachable, the CLI queries the target peer for service data. In this case, interface details may be incomplete and Data Source: local will be shown.

services create

Create a new service. Required scope: urn:tillered:arctic:services.write

arctic services create --target-peer <id> [flags]
FlagDefaultDescription
--target-peerTarget peer ID (required)
--source-peerlocalSource peer ID
--transporttcpTransport type: tcp or kcp
--requires-interfacefalseCreate MACVLAN interface
--desired-ipv4IPv4 CIDR for interface
--fully-transparentfalseEnable fully transparent mode
--bandwidth-limit0Bandwidth limit in Mbps (0 = unlimited)
# Basic service
arctic services create --target-peer 01HXYZDEF789...

# With MACVLAN interface
arctic services create \
  --target-peer 01HXYZDEF789... \
  --requires-interface \
  --desired-ipv4 192.168.100.10/24

# With bandwidth limit
arctic services create \
  --target-peer 01HXYZDEF789... \
  --bandwidth-limit 1000

# Using KCP transport
arctic services create \
  --target-peer 01HXYZDEF789... \
  --transport kcp

Errors:

ErrorDescription
--target-peer is requiredMissing target peer
--transport must be 'tcp' or 'kcp'Invalid transport
peer not foundTarget peer does not exist
service limit exceededLicense service limit reached
service already existsDuplicate service between peers

services update

Update a service's settings. Required scope: urn:tillered:arctic:services.write

arctic services update <service-id> [flags]
FlagDescription
--requires-interface[=BOOL]Enable/disable MACVLAN interface
--fully-transparent[=BOOL]Enable/disable fully transparent mode
--bandwidth-limitBandwidth limit in Mbps (0 = unlimited)
--desired-ipv4IPv4 CIDR for interface
# Enable interface requirement
arctic services update 01HSVCABC123... --requires-interface

# Disable interface requirement
arctic services update 01HSVCABC123... --requires-interface=false

# Enable fully transparent mode
arctic services update 01HSVCABC123... --fully-transparent

# Set bandwidth limit
arctic services update 01HSVCABC123... --bandwidth-limit 500

# Remove bandwidth limit
arctic services update 01HSVCABC123... --bandwidth-limit 0

Errors:

ErrorDescription
service ID requiredMissing service ID
no fields to updateNo update flags provided
service not foundService does not exist

services delete

Delete a service. Required scope: urn:tillered:arctic:services.write

arctic services delete <service-id> [--yes]
# Delete with confirmation
arctic services delete 01HSVCABC123...

# Delete without confirmation
arctic services delete 01HSVCABC123... --yes

Deleting a service:

  1. Removes all associated routes
  2. Removes the MACVLAN interface (if created)
  3. Updates firewall rules
  4. Regenerates TProxy and IP tunnel configs

Global flags

These flags can be used with any Arctic CLI command.

Context selection

--context, -c - Specify a context (peer or cluster) to use for this command. Accepts peer ID, peer name, cluster ID, or cluster name.

arctic peers list --context my-cluster
arctic peers list -c prod-agent-01

Connection override

--url - Override the agent URL for this command.

arctic health --url http://192.168.1.10:8080

--token - Use a specific access token instead of the configured credentials.

arctic peers list --token "eyJ..."

--client-id - Override the OAuth client ID.

arctic peers list --client-id "cl_01HXYZ..."

--client-secret - Override the OAuth client secret.

arctic peers list --client-secret "sec_..."

--insecure - Skip TLS certificate validation. Only use for testing. Do not use in production.

arctic health --url https://agent.example.com --insecure

Output control

--output, -o - Set the output format. Options: table, json, yaml.

arctic peers list -o json
arctic peers list -o yaml

--json, -j - Output in JSON format. Shorthand for -o json.

arctic peers list -j

For list commands, table format shows compact tables with essential information. Use -j or -o json for full detailed output including all fields.

--no-headers - Omit column headers in table output. Useful for scripting.

arctic peers list --no-headers

--quiet, -q - Suppress non-error output.

arctic services delete SERVICE_ID --yes --quiet

Confirmation

--yes, -y - Skip confirmation prompts for destructive operations.

arctic peers delete PEER_ID --yes
arctic services delete SERVICE_ID -y

Debugging

--debug - Show debug information including operation progress and internal state.

arctic peers list --debug

--trace - Show full HTTP request and response traces, including headers and bodies.

arctic peers list --trace

Timeout

--timeout - Set request timeout. Accepts duration format (e.g., 30s, 1m30s). Default: 30s.

arctic peers add 192.168.1.20:8080 --timeout 60s

Configuration

--config - Path to configuration file. Default: ~/.config/arctic/config.yaml.

arctic peers list --config /path/to/config.yaml

Environment variables

Some flags have equivalent environment variables:

FlagEnvironment Variable
--configARCTIC_CONFIG
--contextARCTIC_CONTEXT
--urlARCTIC_URL
--tokenARCTIC_TOKEN
--client-idARCTIC_CLIENT_ID
--client-secretARCTIC_CLIENT_SECRET

Exit codes

The Arctic CLI uses exit codes to indicate the result of command execution.

Exit code reference

CodeNameDescription
0SuccessCommand completed successfully
1General ErrorUnspecified error occurred
2Usage ErrorInvalid arguments or flags
3Config ErrorMissing or invalid configuration
4Connection ErrorAgent could not be reached
5Auth ErrorInvalid or expired credentials
6Partial FailureSome operations succeeded, others failed

Detailed descriptions

0 - Success - The command completed without errors.

arctic peers list
echo $?  # Output: 0

1 - General Error - An unspecified error occurred during command execution.

arctic services create --target-peer nonexistent
# Error: peer not found
echo $?  # Output: 1

2 - Usage Error - The command was called with invalid arguments, unknown flags, or missing required parameters.

arctic services create
# Error: --target-peer is required
echo $?  # Output: 2

3 - Config Error - The CLI configuration is missing, invalid, or incomplete.

arctic peers list
# Error: no current cluster set
echo $?  # Output: 3

4 - Connection Error - Could not establish a connection to the agent.

arctic health --url http://unreachable:8080
# Error: connection refused
echo $?  # Output: 4

5 - Auth Error - Authentication failed due to invalid or expired credentials.

arctic peers list --token "invalid_token"
# Error: unauthorized
echo $?  # Output: 5

6 - Partial Failure - Some operations succeeded while others failed.

Using exit codes in scripts

if arctic peers list > /dev/null 2>&1; then
    echo "Command succeeded"
else
    echo "Command failed"
fi
arctic health --url http://192.168.1.10:8080
exit_code=$?

case $exit_code in
    0)
        echo "Agent is healthy"
        ;;
    4)
        echo "Agent is unreachable"
        ;;
    5)
        echo "Authentication failed"
        ;;
    *)
        echo "Unexpected error: $exit_code"
        ;;
esac

Exit codes are independent of output format. Error messages are always written to stderr, regardless of output format.