Skip to content

Deployment templates

Example configuration files and systemd units for running the orchestrator and agent as services. Copy a template, then change the values your deployment requires. See the Getting Started guide for the full walkthrough.

agent.yaml.example

agent.yaml.example
# Ordo agent configuration — example.
#
# Every option is shown with its default value, all commented out: the defaults
# are sensible, so an agent runs with no configuration at all. Uncomment only
# what you want to change. The agent hot-reloads this file when started with
# `--config`, so changes apply without a restart.
#
# The orchestrator address is NOT set here — it is passed to the `connect`
# subcommand (e.g. `ordo-agent connect 192.168.40.243:4747`).
#
# Schema (editor autocompletion / CI validation):
# https://getordo.dev/schemas/agent-config/v1.json
# ── Remote terminal (defaults shown) ────────────────────────────────────────
# Lets operators open interactive PTY sessions on this machine through the
# orchestrator. Disabled by default.
# remote_terminal:
# enabled: false
# shell: "" # empty = platform default (/bin/bash, powershell.exe)
# allow_operator_shell_override: false # let the operator choose the shell per session
# max_sessions: 100 # max concurrent terminal sessions
# ── Metrics (defaults shown) ────────────────────────────────────────────────
# System health reporting (disk, memory, CPU) to the orchestrator.
# metrics:
# enabled: true
# collection_interval: 30 # seconds between samples

orchestrator.yaml.example

orchestrator.yaml.example
# Ordo orchestrator configuration — example.
#
# Every option is shown with its default value. Commented lines are defaults you
# can leave alone; uncomment and change only what you need. The uncommented
# settings below are the ones a real deployment must or should set.
#
# Schema (editor autocompletion / CI validation):
# https://getordo.dev/schemas/orchestrator-config/v1.json
# ── Must be set on first run ────────────────────────────────────────────────
# The bootstrap operator. Both are required the first time the orchestrator
# starts (when no operators exist yet) and ignored on every start afterwards.
# Get the public key from `ordo operator init` (or `ordo operator whoami`).
bootstrap_key: "PASTE_OPERATOR_PUBLIC_KEY_HEX"
# 1-64 letters/digits/-/_, must start with a letter.
bootstrap_username: "CHOOSE_A_USERNAME"
# ── Recommended ─────────────────────────────────────────────────────────────
# Interface the management API binds. The default (127.0.0.1) is reachable only
# from the orchestrator host itself — fine for a single-machine/dev setup. Bind
# all interfaces so the web UI and CLI work from other machines; choose a
# specific address for a more complex network.
api_host: "0.0.0.0"
# ── Networking (defaults shown) ─────────────────────────────────────────────
# TCP port on which the orchestrator accepts agent connections.
# agent_port: 4747
# HTTP port on which the management API is served.
# api_port: 4748
# Address advertised to agents during discovery; empty = auto-detect.
# advertised_host: ""
# ── TLS (defaults shown) ────────────────────────────────────────────────────
# TLS is enabled by default; a self-signed certificate is generated on first
# start and pinned by clients on first connection (trust-on-first-use).
# tls_enabled: true
# Provide both to use your own PEM certificate instead of the self-signed one.
# tls_cert: "/etc/ordo/tls/cert.pem"
# tls_key: "/etc/ordo/tls/key.pem"
# Assert that a TLS-terminating reverse proxy fronts the API. Only relevant when
# tls_enabled is false; permits secret writes over the (proxied) plaintext hop.
# trust_proxy_tls: false
# ── Capacity and sessions (defaults shown) ──────────────────────────────────
# Maximum number of simultaneously pending agents awaiting approval.
# pending_capacity: 100
# Seconds a web UI / API session token remains valid.
# session_token_expiry_secs: 3600
# ── Metrics (defaults shown) ────────────────────────────────────────────────
# metrics:
# poll_interval: 60 # seconds between polling each agent for metrics
# retention: 86400 # seconds to retain metric samples (24h)
# ── Audit log (defaults shown) ──────────────────────────────────────────────
# audit:
# retention_days: 90 # 0 disables automatic pruning
# ── Drift detection (defaults shown) ────────────────────────────────────────
# drift:
# enabled: true
# interval: 3600 # seconds between drift checks per agent
# max_concurrent: 8 # max in-flight drift checks across all agents
# skip_recently_applied: 300 # suppress checks for N seconds after an apply
# retention_days: 30 # how long to retain drift records

ordo-agent.service

ordo-agent.service
[Unit]
Description=Ordo agent
Documentation=https://docs.getordo.dev
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
# Top-level options (--config, --data-dir) come BEFORE the `connect` subcommand;
# replace the address with your orchestrator's host:agent_port.
ExecStart=/usr/local/bin/ordo-agent --config /etc/ordo/agent.yaml --data-dir /var/lib/ordo-agent connect ORCHESTRATOR_HOST:4747
Restart=on-failure
RestartSec=5
# The agent manages this machine — it writes files and controls services as
# declared state requires — so it runs as root WITHOUT the filesystem sandboxing
# used for the orchestrator. ProtectSystem/ProtectHome/DynamicUser would stop it
# doing its job. StateDirectory persists the agent's identity and pinned
# orchestrator key.
User=root
StateDirectory=ordo-agent
[Install]
WantedBy=multi-user.target

ordo-orchestrator.service

ordo-orchestrator.service
[Unit]
Description=Ordo orchestrator
Documentation=https://docs.getordo.dev
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/local/bin/ordo-orchestrator --config /etc/ordo/orchestrator.yaml --data-dir /var/lib/ordo-orchestrator
Restart=on-failure
RestartSec=5
# Isolated transient system user; StateDirectory gives a persistent, owned
# /var/lib/ordo-orchestrator for the identity key and the redb store. The
# orchestrator only talks over the network and reads its config, so it can run
# fully sandboxed (unlike the agent, which manages the host).
DynamicUser=yes
StateDirectory=ordo-orchestrator
StateDirectoryMode=0750
# Hardening
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
PrivateDevices=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
RestrictAddressFamilies=AF_INET AF_INET6
RestrictNamespaces=yes
LockPersonality=yes
SystemCallFilter=@system-service
SystemCallErrorNumber=EPERM
[Install]
WantedBy=multi-user.target