Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"groups": [
{
"group": "Getting Started",
"pages": ["index", "self-hosting"]
"pages": ["index", "self-hosting", "homelab"]
},
{
"group": "Using Roomote",
Expand Down
252 changes: 252 additions & 0 deletions apps/docs/homelab.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
---
title: Homelab deployment
icon: house-plug
description: 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
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
curl -fsSL https://get.roomote.dev | 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
curl -fsSL https://get.roomote.dev | 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
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.
4 changes: 4 additions & 0 deletions apps/docs/self-hosting.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ communications, sandbox, and other tools Roomote needs to do useful work.
- **Your own server** gives you the most infrastructure control with the
one-command installer below.

Running Roomote on Proxmox or another server at home? Follow the
[Homelab deployment guide](/homelab) for VM sizing, Tailscale administration,
public ingress, and a prompt that a local agent can follow.

By the end of setup, you should have a reachable Roomote URL, sign-in, a
source-control provider, a ChatGPT subscription or inference provider, at least
one environment, and a first reviewable Roomote task.
Expand Down
Loading