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

> ## Agent Instructions
> When helping someone deploy Roomote, distinguish self-hosting from contributing to Roomote. Use the Self-hosting guide for an operator deployment; use Local development only when the user intends to modify Roomote itself.
> Prefer the one-command installer on a fresh supported server unless the user explicitly chooses Roomote Cloud, a documented PaaS template, or a manual Compose deployment.
> Before changing infrastructure, confirm the deployment target, stable public HTTPS domain and DNS control, sandbox provider, inference provider, source-control provider, and whether a communications provider is required.
> Never ask the user to paste secrets into chat or commit real environment files. Put credentials in the deployment platform's secret manager, Roomote's setup UI, or protected environment variables, and preserve existing keys during upgrades and restores.
> Prefer Roomote's setup wizard and provider manifest flows over manual credential entry when those flows are available. Ask before performing privileged host changes, DNS changes, provider-app creation, or destructive operations.
> A setup is not complete when the services merely start. Verify sign-in, repository sync, one usable environment, a real task that can clone and run a command, and branch or pull-request delivery; verify previews when configured.
> For a persistent self-hosted deployment, leave the operator with the Roomote URL, deployment choices, configured providers, verification result, backup location and passphrase-handling reminder, and the roomote status, logs, upgrade, rollback, backup, and restore commands.

# Homelab deployment

> Run Roomote on a Proxmox VM or another Linux server in your homelab.

Run Roomote on hardware you control with a dedicated Linux VM, private
administration over Tailscale, and a public HTTPS origin for provider callbacks
and task previews.

This guide uses **Proxmox VE with a Debian or Ubuntu VM** as the worked example.
Proxmox and Tailscale are not Roomote requirements: a bare-metal Linux server,
another hypervisor, WireGuard, or a conventional VPN can provide the same
roles.

<Note>
  Use a full virtual machine rather than an LXC container for the default Docker
  sandbox provider. Roomote depends on Docker networking, cgroups, packet-filter
  rules, and writable-layer quotas that are much easier to operate reliably in
  a VM. LXC installations require host-specific privileged-container changes
  and are not covered by this guide.
</Note>

## Plan the deployment

The recommended homelab shape separates private administration from public
application traffic:

* **Proxmox VM:** runs Roomote, its datastores, and the default Docker task
  sandboxes
* **Tailscale:** provides private SSH and administrative access to the VM
* **Public HTTPS origin:** receives source-control and communications-provider
  callbacks and serves links generated by Roomote
* **Caddy:** terminates traffic for the application and task preview hostnames

Roomote supports x86\_64 and arm64. The installer requires at least 4 GB of RAM.
For a deployment that runs Docker task sandboxes on the same host, start with:

| Resource | Recommended starting point              |
| -------- | --------------------------------------- |
| CPU      | 4 vCPU, host CPU type                   |
| Memory   | 8 GB                                    |
| Disk     | 60 GB or more on quota-capable storage  |
| OS       | Debian 12 or later, or Ubuntu 24.04 LTS |

The default limit for each Docker task is 2 CPUs, 4 GiB of memory, and a 20 GiB
writable layer. Increase the VM resources for concurrent or Docker-heavy tasks,
or use a [hosted sandbox provider](/compute) so task workloads do not compete
with the Roomote services.

## Create the Proxmox VM

Create a VM from a Debian or Ubuntu cloud image or installation ISO:

1. allocate at least 4 vCPU, 8 GB RAM, and 60 GB of disk
2. set the CPU type to `host` and use VirtIO for disk and networking
3. install and enable `qemu-guest-agent`
4. assign a DHCP reservation or static address on the LAN
5. enable SSH and apply operating-system updates

A bare-metal mini PC, an existing Debian or Ubuntu server, or a VM on another
hypervisor works too. The important boundary is a clean Linux host where Docker
Engine and its networking and storage controls can operate normally.

## Add private administration with Tailscale

Install Tailscale on the VM using the
[official Linux instructions](https://tailscale.com/kb/1031/install-linux), then
confirm you can reach the host over its tailnet address before changing router
or firewall rules. Use Tailscale SSH or regular SSH over the tailnet for host
administration.

Tailscale does not replace Roomote's public application origin. GitHub, Slack,
and other providers must reach callbacks from outside your tailnet. Live task
previews also use per-task hostnames, including wildcard preview DNS in the
normal production configuration.

<Warning>
  Docker task sandboxes block private, link-local, shared-address, cloud
  metadata, and Tailscale ranges by default. A repository hosted only on your
  LAN or tailnet may be reachable from the VM but unreachable from a Roomote
  task. Give self-hosted GitLab or Gitea a public, worker-reachable hostname
  instead of disabling the sandbox network guard.
</Warning>

## Choose public ingress

Choose one stable hostname before completing the setup wizard. Changing it
later also means updating source-control, sign-in, and communications-provider
redirect and webhook URLs.

| Path                           | Best for                                                 | Tradeoffs                                                                  |
| ------------------------------ | -------------------------------------------------------- | -------------------------------------------------------------------------- |
| Public DNS and port forwarding | Public IPv4, router control, and the simplest data path  | Requires forwarding ports 80 and 443; dynamic addresses need DDNS          |
| Cloudflare Tunnel              | CGNAT or networks where inbound ports should stay closed | Requires tunnel and wildcard-hostname configuration                        |
| Tailscale Funnel               | A limited public trial without router changes            | Does not provide the wildcard hostname model needed for full live previews |

### Public DNS and port forwarding

Create DNS records for the application, preview root, and wildcard previews:

```text theme={null}
roomote.example.com            A/AAAA  <home public address>
preview.roomote.example.com    A/AAAA  <home public address>
*.preview.roomote.example.com  A/AAAA  <home public address>
```

Forward TCP ports 80 and 443 from the router to the VM, then run:

```sh theme={null}
curl -fsSL https://get.roomote.dev | sudo bash -s -- \
  --domain roomote.example.com
```

The installer defaults the preview root to `preview.<domain>`. Use
`--preview-domain <host>` when your DNS layout differs. If the public address
changes, configure DDNS for all three records. This path does not work behind
carrier-grade NAT unless the ISP supplies a public address.

### Cloudflare Tunnel

Cloudflare Tunnel can publish Roomote without forwarding inbound router ports.
Install Roomote with Caddy's internal TLS mode because Cloudflare terminates the
public certificate:

```sh theme={null}
curl -fsSL https://get.roomote.dev | sudo bash -s -- \
  --domain roomote.example.com \
  --tls-mode internal
```

Route both the application hostname and preview wildcard through the same Caddy
instance rather than routing directly to individual Roomote containers. Standard
Cloudflare certificates require Roomote's flat preview-hostname layout; follow
the canonical
[Cloudflare Tunnel and flat preview hostname configuration](https://github.com/RooCodeInc/Roomote/blob/main/SELF_HOSTING.md#flat-preview-hostnames)
for the required environment values, tunnel ingress, origin TLS setting, and
**Match SNI to Host** option. Apply those values in `/opt/roomote/.env` and run
`sudo roomote up` before testing or exposing task previews; the install command
above otherwise retains the default nested preview hostname layout.

### Tailscale Funnel

Tailscale Funnel can expose a stable tailnet hostname to public callback
providers, but it does not support Roomote's normal wildcard preview hostname
layout. Treat it as a limited dashboard and callback trial, not the default
full deployment path. Use public DNS or Cloudflare Tunnel when users need live
task previews.

## Let a local agent prepare the host

Paste the following prompt into a local coding agent running on the VM or one
that can SSH to it. The agent prepares the host and installer; you complete
credential and authorization steps in Roomote's browser wizard.

```text theme={null}
Set up a self-hosted Roomote deployment on this homelab server.

Safety and scope:
- Work only on a dedicated Debian 12+ or Ubuntu 24.04+ VM or bare-metal host.
- Stop if this is an LXC container or if fewer than 4 GB RAM or 40 GB free disk
  are available. Warn me and ask before continuing if other production
  workloads share the host.
- Explain changes before using sudo. Do not disable the firewall or expose
  database, Redis, object-storage, API, or queue-dashboard ports.
- Never ask me to paste model, GitHub, Slack, or other provider secrets into
  chat or the shell. Those belong in Roomote's browser setup wizard.

Process:
1. Report the OS, architecture, CPU count, memory, free disk, default route,
   public IPv4 detection result, and current Docker/storage configuration if
   Docker is already installed. Do not change anything yet.
2. Ask me to choose one ingress path: public DNS plus ports 80/443, or
   Cloudflare Tunnel. If I am behind CGNAT, recommend Cloudflare Tunnel. Ask for
   the final application domain and optional preview domain.
3. Ask whether to install Tailscale for private SSH/admin access. If approved,
   use Tailscale's official Linux package instructions and confirm access. Do
   not treat the tailnet hostname as Roomote's public application origin.
4. For public DNS, tell me the exact app, preview, and wildcard DNS records and
   router forwards I must create, then wait for me. Verify public DNS and ports
   from outside the LAN where possible. For Cloudflare Tunnel, guide me through
   creating the app and wildcard public hostnames without asking me to reveal a
   tunnel token, and use Roomote's documented internal-TLS and flat-preview
   configuration.
5. Download https://get.roomote.dev to a temporary file, show me the file path
   and the exact installer flags you will use, and ask me to inspect it before
   approval. Then run it with --domain and, for Cloudflare Tunnel, --tls-mode
   internal. Do not write a new installer or manually recreate the Compose
   stack.
6. Run `sudo roomote status`. If healthy, tell me to run `sudo roomote
   setup-url` in a separate trusted terminal and open the result. Do not print,
   capture, or repeat the tokenized URL in agent output or transcripts. Stop
   while I complete sign-in, source control, inference, communications, and
   environment setup in the browser.
7. After I confirm setup is complete, validate Docker's writable-layer quota
   support, a small Roomote task, repository cloning, artifact upload, and a
   configured preview. Summarize any failure and the relevant `roomote logs`
   output without printing secrets.
```

## Complete setup in the browser

The installer sets up Docker, Compose, generated secrets, Caddy, the Roomote
services, a systemd unit, and the `roomote` host CLI. When it finishes, open the
tokenized setup URL it prints and configure:

1. the first admin account
2. a source-control provider and repository access
3. a ChatGPT subscription or inference provider
4. Docker or a hosted sandbox provider
5. an optional communications provider such as Slack
6. the first environment and Roomote task

Keep provider credentials in the setup wizard or your deployment secret store,
not in shell history or an agent conversation.

## Verify the homelab path

After setup:

1. run `roomote status` on the VM and confirm the services are healthy
2. open the public Roomote URL from a device outside the home network
3. confirm the expected repositories appear in Roomote
4. validate the sandbox provider from **Settings > Sandboxes**
5. run a small task and confirm it clones, executes, and uploads an artifact
6. test a configured live preview from outside the home network
7. if configured, mention the Roomote app in Slack and confirm it replies

Common homelab failures include:

* **The public URL works on cellular but not on Wi-Fi.** The router may not
  support hairpin NAT. Add split-horizon DNS for LAN clients or use a resolver
  that returns the correct internal route.
* **An `sslip.io` hostname does not resolve on the LAN.** DNS-rebind protection
  may reject names that resolve to private addresses. Use a domain you control
  or allow the exact hostname in the local resolver.
* **Certificates never issue.** Confirm public DNS, router forwarding, and host
  firewall rules for ports 80 and 443. With a tunnel, use `--tls-mode internal`
  and check the tunnel-to-Caddy origin TLS settings.
* **Port forwarding has no effect.** Compare the router WAN address with an
  external public-IP check. Different addresses usually indicate CGNAT; use a
  tunnel or request a public address from the ISP.
* **A task cannot clone a LAN repository.** Use a public, worker-reachable
  source-control hostname. Do not remove the sandbox private-network guard.

## Back up and update

Use `roomote backup`, `roomote upgrade`, and `roomote rollback` for supported
day-2 operations. A Proxmox snapshot is useful before host maintenance, but it
does not replace an encrypted Roomote backup stored off the VM with its
passphrase stored separately. See [Self-hosting](/self-hosting#day-2-operations)
for backup, restore, and upgrade behavior.
