> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://rivet.chrisboulton.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://rivet.chrisboulton.com/_mcp/server.

# Choosing how to run Rivet

> Compare local, SSH, source-release, and compile-service deployments.

Every mode ends the same way: a verified bundle reaches the host, and the host's runner plans or applies it with the same journal, lock, and reports. The modes differ in where compilation happens and how the bundle gets to the host.

| Mode            | Compiles on                  | Bundle reaches the host by                            | The host needs                                             |
| --------------- | ---------------------------- | ----------------------------------------------------- | ---------------------------------------------------------- |
| Local           | The host, or any machine     | Being there, or being copied there                    | Rivet installed                                            |
| SSH             | Your controller              | `rivet apply --target` over SSH                       | SSH access; Rivet is uploaded on first use                 |
| Source release  | The host, during `rivet run` | Reading a release from S3, GCS, or a shared directory | Rivet, an agent config, and storage read access            |
| Compile service | `rivet-server`               | HTTPS from the service, during `rivet run`            | Rivet, an agent config, and an identity the service trusts |

## Local

Compile and apply on the host itself, or compile elsewhere and copy the bundle across. Nothing else is involved, so this is the simplest way to start. Follow [your first configuration](/getting-started/quickstart).

## SSH from a controller

Run `rivet facts`, `plan`, `apply`, and `journal` from your laptop or CI with `--target HOST`. Rivet uses your normal OpenSSH configuration. On first contact it reuses a compatible installed runner or uploads one to a private cache. Nothing runs on the host between your commands: no daemon, no open port.

Choose this to push changes to a handful of hosts on demand, or when you want CI to be the only thing that changes hosts. See [SSH from a controller](/operations/ssh).

## Agent with source releases

Publish your configuration directory to S3, GCS, or a local directory as an immutable release, then point an environment such as `production` at it. Each host runs `rivet run`, usually from a [systemd timer](/operations/scheduling): it reads the environment's release, compiles locally against fresh facts, and applies.

Choose this when hosts should pull changes on a schedule without a central server. Each host's storage identity can read every object in the release, so don't rely on HCL conditions to keep one host's secrets from another. See [releases and environments](/operations/distribution) and [agent runs](/operations/agent).

## Agent with the compile service

Run `rivet-server`, an HTTPS service that reads releases from storage. Hosts authenticate with a GCP instance identity token, an mTLS client certificate, or an OIDC token. The service checks allow rules, compiles a catalog for that host, and returns it. Configuration can read verified identity as [`trusted` claims](/language/trusted-facts), for example to choose a role from a certificate extension. With signed asset delivery, hosts can fetch files without any storage credentials.

Choose this to keep compilation and source access off the hosts, or to classify hosts by an identity they can't forge. See [compile service](/operations/compile-service).

## Feature differences

| Feature                                                     | Local and SSH                          | Source release and compile service                                  |
| ----------------------------------------------------------- | -------------------------------------- | ------------------------------------------------------------------- |
| Modules, `file()` and `templatefile()` reads of other files | Yes                                    | No: releases stage only top-level `*.hcl` files and resource assets |
| `--vars-file` and data hierarchies, including SOPS          | Yes                                    | No: variables need defaults                                         |
| `trusted` identity claims                                   | No                                     | Compile service only                                                |
| Applying without network access                             | Yes: a bundle is a self-contained file | Yes, from the last prepared catalog with `rivet run --offline`      |

You can mix modes. For example, use SSH to bootstrap a host, then install an agent for scheduled runs. Root applies in every mode share the host's journal in `/var/lib/rivet`, so recovery works the same way whichever mode started an interrupted run.