> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orcra.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# How Orcra Run reconciles your containers

> orun nodes poll your Git repository on a set interval, compare desired state to running containers, and apply changes autonomously — no push required.

Orcra Run operates on a pull-based reconciliation model. Instead of a central controller pushing commands to nodes, each node independently polls your manifest repository, determines what should be running, and converges toward that desired state. Nothing coordinates the node after bootstrap — the node drives itself.

<Note>
  orun is pre-release, experimental software. Use it at your own risk and expect breaking changes between versions.
</Note>

## The reconciliation loop

Every node runs a continuous loop: fetch the latest manifests from Git, compare them to the containers currently running on the host, then apply whatever changes are needed. This happens automatically on every poll tick without any external trigger.

The loop consists of five stages:

<Steps>
  <Step title="Commit your manifest changes">
    Edit your `deployments/`, `services/`, or `nodes/` manifests and push to the branch your node tracks. This is the only action you take — the rest is automatic.
  </Step>

  <Step title="Node polls the repository">
    orun runs a `git pull` against the `origin` remote on a configurable interval (default: `5s`). If the HEAD commit hash changes, a reconciliation pass is triggered immediately.
  </Step>

  <Step title="Agent loads and compares desired state">
    The agent parses all manifests from the local clone and builds a picture of the desired state: which containers should exist, with which images, ports, volumes, and environment variables. It then inspects the Docker daemon on the host to determine actual state.
  </Step>

  <Step title="Agent applies changes">
    For each difference between desired and actual state, the agent acts: pulling new or updated images, starting containers that should be running, stopping containers that have been removed, and updating port bindings or mounts as needed.
  </Step>

  <Step title="Health probes confirm readiness">
    Once a container is started, orun polls the configured `health.readiness.http` and `health.liveness.http` endpoints until the container reports healthy. Only then is the deployment considered reconciled.
  </Step>
</Steps>

## No push model

orun has no control plane and no inbound channel. Your laptop, your CI system, and your Git host never send commands to a node. The node initiates all communication — outbound to the Git remote, outbound to the container daemon.

This means:

* **No open ports for orchestration.** The node does not expose an API that accepts deployment commands.
* **No credentials to rotate on the node.** The node holds a read-only deploy key for the Git remote; that is its only secret.
* **No single point of failure.** Each node is independent. A network partition between nodes does not stop any of them from reconciling.

## Pull-based resilience

Because nodes pull their state rather than receive it, they keep running correctly even when your laptop is offline, your CI pipeline is broken, or the network between nodes is partitioned. The node continues running the last-known desired state and retries the Git poll on the next tick.

If a poll fails — for example, because the Git remote is temporarily unreachable — `gitsync` applies exponential backoff, doubling the poll interval on each consecutive failure up to a maximum of 5 minutes. Once the remote becomes reachable again, the backoff resets and the node returns to its configured `pollInterval`.

<Info>
  The default poll interval is `5s`. You can override it per node with the `pollInterval` field in your Node manifest. Changes pushed to Git are visible to the node within one poll cycle.
</Info>

## Agent startup

The orun agent is installed as a `systemd` service during `orun bootstrap`. It starts automatically on boot and restarts on failure without any manual intervention. After bootstrap, you do not need SSH access to the node for day-to-day operations.

```bash theme={null}
# Check agent status on the node
systemctl status orun
journalctl -u orun -f
```

## Observability

The agent exposes a lightweight status API on port `9100`. Use it to check sync health and overall node status without SSH access.

<Tabs>
  <Tab title="Status">
    ```bash theme={null}
    curl -X POST http://<node-ip>:9100/status
    ```

    Returns JSON describing the current sync state, HEAD commit, last sync time, and whether the agent is healthy.
  </Tab>

  <Tab title="Health check">
    ```bash theme={null}
    curl -X POST http://<node-ip>:9100/healthz
    ```

    Returns a simple liveness response. Use this in uptime monitors or load balancer health checks.
  </Tab>
</Tabs>

Structured JSON logs are written to `journald` and can be forwarded to any log aggregation system. For container-level monitoring, deploy a sidecar tool such as [Beszel](https://beszel.dev) or [Dozzle](https://dozzle.dev/) alongside your workloads.

<CardGroup cols={2}>
  <Card title="Manifest repository" icon="folder" href="/concepts/manifest-repository">
    Learn how to structure your nodes/, deployments/, and services/ directories.
  </Card>

  <Card title="Environments" icon="code-branch" href="/concepts/environments">
    Use Git branches and worktrees to separate production from non-production environments.
  </Card>
</CardGroup>
