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

> ## Agent Instructions
> Start new users at /index to choose Roomote Cloud or self-hosting. Use /cloud for managed hosting and /self-hosting for an operator deployment, including home networks at /homelab. Both paths continue through /first-task. Use Local development only when the user intends to modify Roomote itself.
> When an agent is asked to follow /self-hosting or install Roomote autonomously, read and follow /self-hosting/agent-installation as the normative automation contract even though it is intentionally hidden from side navigation.
> Use the one-command Linux installer for both evaluation and production. On macOS or Windows, create or reuse a full Ubuntu VM and run the same installer inside it; do not replace the installer with the repository's development Compose files.
> For a local VM, prepare a stable public HTTPS domain before connecting providers. Use a named tunnel with internal origin TLS or public DNS with ports 80/443 forwarded to the Linux host. Cloudflare Quick Tunnels do not support the Server-Sent Events Roomote uses; do not use them for the complete setup path.
> Run automated installs with --no-setup-url so the bootstrap token is not captured in the agent transcript. Let the user obtain the setup URL in a trusted terminal, enter credentials, and complete browser authorization.
> Proceed through safe, reversible setup and pause for privileged host or VM changes, public tunnel creation, credentials or browser authorization, durable external-account changes, destructive operations, existing-state conflicts, or when no documented safe default applies.
> A setup is not complete when the services merely start. Follow /first-task to verify sign-in, repository sync, and a real Roomote task that can clone and run a command. A saved environment is optional for a repository task. Verify branch or pull-request delivery and previews when configured; Slack and other communications providers are optional.

# Operate a self-hosted deployment

> Back up, restore, update, and troubleshoot Roomote after your first task.

Use this guide after [installing Roomote](/self-hosting) and
[completing your first task](/first-task). These commands apply to deployments
created with the Linux installer. For a hosting platform, follow its
[deployment guide](/self-hosting/platforms) for lifecycle operations.

Run host commands on the Linux machine running Roomote. Use `sudo` if your
account needs it to access the deployment.

## Day-2 operations

The installer also sets up the `roomote` host CLI for common operations:

```sh theme={null}
roomote upgrade   # pull and roll out newer images
roomote rollback  # return to the release before the last upgrade
roomote backup    # create an encrypted deployment recovery bundle
roomote logs      # tail service logs
```

`roomote backup` prompts for a passphrase and writes a versioned `.roomote`
bundle under `/opt/roomote/backups`. The bundle contains PostgreSQL, the
deployment configuration and encryption/signing keys, local MinIO artifacts,
schema metadata, the exact deployed image identities, and both the Memory volume
and isolated Memory database when the `brain` profile is enabled. Store the
passphrase separately in your secret manager; the backup cannot be restored
without it.

Webhook and delivery lifecycle entries in `roomote logs` use single-line JSON
with an `event` field plus safe correlation fields such as provider, delivery,
session, task, run, and job IDs. Search these entries to follow Telegram
messages and GitHub pull-request review activity from receipt through
persistence, dispatch, and final delivery. Message bodies, raw payloads,
credentials, signatures, and token-bearing URLs are excluded.

Use `roomote backup --include-redis` when queued work, BullMQ schedules,
sessions, and other transient Redis state must survive. Backups briefly stop
application writers (and active Docker task workers) so the included stores
share a documented consistency point. If object storage is external, the
bundle records its endpoint and bucket but does not copy its objects; keep a
provider-level backup of that bucket.

Roomote exposes `/health/bullmq` for queue-processing health. It returns healthy
only when the background worker has recently processed its heartbeat job and no
session event has remained queued for more than five minutes. Any overdue event
makes the check fail; authenticated error responses report the overdue count,
while unauthenticated responses omit diagnostics. Use it alongside container
liveness and `roomote logs`: a stale heartbeat or growing backlog can reveal a
worker process that is still running but no longer draining jobs.

Restore only after installing Roomote on the replacement host:

```sh theme={null}
roomote restore /path/to/backup.roomote --yes
```

Restore verifies the encrypted bundle and checksums before replacing any
state, restores the original `.env` (including `ENCRYPTION_KEY`), repopulates
empty PostgreSQL/MinIO/Redis volumes, and starts the recorded Roomote release.

## Upgrades and rollback

`roomote upgrade` is designed so a bad release cannot strand your deployment:

* **A backup comes first.** Every upgrade creates an encrypted pre-upgrade
  bundle under `/opt/roomote/backups` before anything changes. Pass a
  passphrase with `--backup-passphrase-file` (or `ROOMOTE_BACKUP_PASSPHRASE`);
  otherwise one is generated and stored next to the bundle. Use
  `--skip-backup` to opt out.
* **Migrations run before services are replaced.** Database migrations apply
  in a single transaction while the previous release keeps serving. The bundled
  migration runner makes up to three total attempts after a transient Postgres
  connection failure: the initial run plus at most two retries. If migration
  still fails, the schema rolls back, the previous configuration is restored,
  and the previous release stays up.
* **Rollback is one command.** Every release's schema keeps the previous
  release working, so `roomote rollback` re-deploys the prior release without
  touching the database. `roomote upgrade <tag>` does the same for any
  retained tag, and restoring the pre-upgrade bundle is the last-resort path
  that also rewinds data.

Use `roomote upgrade` instead of updating application image references alone.
The command refreshes the release's Compose and Caddy configuration together;
mixing newer application images with an older Caddyfile can leave routes used
by the new controller unavailable until the deployment configuration is also
updated.

The supported rollback target is the release immediately before the current
one. Check the running application version and applied schema migration at any
time under **Settings → Deployment → Diagnostics**; both are also recorded in
every backup bundle's manifest.

Roomote surfaces release history and available updates in the web app:

* **Admins** on self-hosted deployments see an update notice in the sidenav when
  a newer GitHub release is available. The update dialog keeps that target and
  its GitHub link visible even when the running image does not yet contain the
  newer release's notes. Use `roomote upgrade` (or your image roll-forward
  process) to install it.
* **Everyone** can open **About Roomote** and select **See all Roomote releases**
  to browse the current and previous release notes bundled in the running
  image, with the latest release expanded. After an upgrade, Roomote also shows
  the latest "what's new" notice once.

## Common issues

* **Callbacks fail.** For providers that use callbacks or webhooks, confirm the
  deployment has a public HTTPS URL and that the provider is using that exact
  URL. Discord uses its Gateway service instead of a public callback.
* **The first task cannot clone a repository.** Workers authenticate git with a
  short-lived GitHub App installation token created when the run starts — they
  do not read a `GH_TOKEN`/`GITHUB_TOKEN` from the container environment. If a
  task fails with "No GitHub credentials are available", verify the GitHub App
  is installed for the repository owner, the installation covers the
  repository, and the repository appears in the source-control settings after a
  sync.
* **The agent cannot run useful commands.** Add missing services, environment
  variables, setup commands, or tool versions to the environment.
* **Chat messages do not reach Roomote.** Confirm the app is installed, invited
  to the channel, and using the current callback URL.
* **Roomote reports that local working storage is full.** Clean up container
  storage, then recreate the affected application containers. Installer-managed
  Compose deployments can raise `ROOMOTE_APP_TMPFS_SIZE` above its `512m`
  default before recreating them; keep the limit within the host's available
  memory.
* **Memory climbs for hours, or a service is OOM-killed under a container
  memory limit.** Node sizes its heap from the memory it can see (the host's,
  not the container's), so it defers garbage collection and lets memory drift
  well above what the service needs; a container memory cap then kills the
  process before Node ever feels pressure. Current app images cap each Node
  service's heap by default (768 MB for web and api, 512 MB for controller and
  bullmq, reduced to \~75% of the container's memory when a cgroup limit is
  set). Set `NODE_OPTIONS=--max-old-space-size=<MB>` on a service to override
  the default, or on older images to add the cap manually.

## Decision model on CPU (optional)

Roomote asks a decision model small typed questions: whether a turn is worth
remembering, who a thread reply is for, when a running task has news for the
user, which model a delegated task should use. With a TypeSafe key, Jev
answers them. Without one, the `judgment` profile runs a CPU decision model
beside the stack, so these features work with no external decision API and no
GPU.

Add these to `.env`:

```sh theme={null}
COMPOSE_PROFILES=judgment                          # or append to an existing list
R_JUDGMENT_UPSTREAM_URL=http://judgment:8080
R_JUDGMENT_MODEL=roomote                           # or choose it in Settings > Models
```

The sidecar serves
[`roomote/roomote-judgment-gliner`](https://huggingface.co/roomote/roomote-judgment-gliner),
a GLiNER 2.5 model fine-tuned on Roomote's decisions and trained only on
synthetic data. It downloads the model on first start and keeps it in the
`roomote_judgment_models` volume. Its model card lists the decisions it covers
and its accuracy; on real decisions it trails Jev by a few points, and Roomote
acts on a decision only when the model is confident and the decision is in its
evaluated policy. Unsupported decisions keep their existing safe fallback. To
serve a different checkpoint, set `JUDGMENT_MODEL` to a Hugging Face id or path
(and `JUDGMENT_HF_TOKEN` if it is private).

The sidecar is reachable only on the stack's internal network; set
`R_JUDGMENT_UPSTREAM_API_KEY` as well to require a bearer token.

Sizing: the container is capped at `JUDGMENT_MEMORY_LIMIT` (default `4g`) and
`JUDGMENT_CPUS` (default `4`). It uses about 1.5 GB, and on 4 cores a decision
takes about 0.3 to 1 second (p90 about 2 seconds). Decisions run one at a
time, so a burst of them queues and more cores make each one faster.

The production install (`install.sh`) and the Railway, Render, and Coolify
templates carry the same service, opt-in like Memory: in the production
install it is the `judgment` profile, and in the templates it idles without
loading its model until `R_JUDGMENT_UPSTREAM_URL` points at it and the
Roomote judgment model is selected. Each template's README has the steps.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.