Skip to main content
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.
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.

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: 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 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, 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.
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.

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.

Public DNS and port forwarding

Create DNS records for the application, preview root, and wildcard previews:
Forward TCP ports 80 and 443 from the router to the VM, then run:
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:
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 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.

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 for backup, restore, and upgrade behavior.