Skip to main content
This guide deploys Comis to Render.com using the prebuilt Docker Hub image. You get a managed Linux host (so the exec sandbox is fully active — unlike Docker Desktop on macOS), automatic HTTPS, a persistent volume for memory and configuration, and a public URL within ~5 minutes. No Docker installed locally, no server to provision, no kernel to manage.
You don’t need to understand the technical details to use this feature. The configuration examples below are copy-paste ready.
Why Render specifically: It’s the simplest “click-deploy a Docker Hub image with a persistent disk and an HTTPS endpoint” PaaS. The same general pattern works on Fly.io, Railway, DigitalOcean App Platform, and AWS ECS — adjust the service-creation flow but keep the environment variables and disk mount the same.

Before you start

You don’t need Docker, Node.js, or anything else installed on your machine. Render pulls the image directly from Docker Hub.
Plan choice. Render’s free plan has no persistent disk and sleeps after 15 minutes of inactivity. Comis needs both — without a disk every restart wipes your agent’s memory and conversations; without always-on the agent can’t respond to channel events. Use the $7/mo Starter plan or higher.

Quick deploy (dashboard, ~5 minutes)

1

Create a new Web Service

Log into Render → click New + in the top right → Web Service.On the next screen, look for the “Existing Image” option (not “Public Git Repository” — we’re deploying a prebuilt image, not source). Click it.
2

Point at the Comis Docker Hub image

In the Image URL field, paste:
For production, pin to an immutable version tag instead of latest-slim so your service doesn’t update under you. Find the latest version on the Comis Docker Hub page and use e.g. docker.io/comisai/comis:1.0.53-slim.
Click Connect (or “Next” depending on your Render UI version).
3

Configure the service

Fill in:Render will detect the image’s exposed port. Comis exposes 4766.
4

Add environment variables

Scroll down to Environment Variables and add each of these. Use the “Add Secret File” / “Add” button for each row. Mark each as a Secret (lock icon) so the values stay hidden in logs and the dashboard.Required:
Optional channel tokens — add only those you’ll use:
Never store API keys, tokens, or passwords directly in config.yaml. Use the .env file or Secret Manager for credential management.
The encrypted secrets store is enabled by default. On first boot, Comis auto-generates a master key and writes it to ~/.comis/.env (mode 0600). Back up this file — losing SECRETS_MASTER_KEY makes secrets.db permanently unreadable. To disable the encrypted store, set security.storage: env (or file) in config.yaml.
5

Add a persistent disk

Still on the create-service screen, scroll to Advanced → expand it → look for Add Disk. Configure:This is where your agent’s memory database, logs, secrets store, and workspace live. Without this disk, every redeploy wipes your data.
6

Set the health check

Scroll to Health Check Path and enter:
Render uses this to decide when traffic should start flowing to your container after a deploy. Comis’s daemon serves a JSON {"status":"ok",...} on this endpoint as soon as the gateway is up.
7

Deploy

Click Create Web Service at the bottom. Render starts pulling the image, attaching the disk, and starting the container. The deploy takes about 2–3 minutes for the first time (image pull + initial filesystem setup).Watch the Logs tab — you should eventually see:
When the service status switches to Live at the top of the page, you’re done.

Verify the deployment

Render gives your service a public URL like https://comis-XXXX.onrender.com. Find it on the service’s dashboard page (top of the screen, next to the green “Live” badge). Run these from any terminal — they need no Docker or Comis CLI locally:
If all three of those work, you have a fully functional Comis deployment.

Open the dashboard

In your browser, go to:
It redirects to /app/ and prompts for your gateway token. Paste the same COMIS_GATEWAY_TOKEN you set in the env vars. From here you can:
  • Add agents, configure their model and policies
  • Connect channels (Telegram, Discord, Slack, etc.) — paste each bot token
  • Watch live logs, traces, and memory contents
  • Edit configuration through the UI (writes to /home/comis/.comis/config.yaml on the persistent disk)
Bringing an existing config from local testing. If you’ve been testing Comis locally, you already have a ~/.comis/config.yaml with agents and channels configured. The simplest way to seed your Render deployment with that config is via Render’s Secret Files feature — see below.

Reproducible deploys with render.yaml

If you’d rather declare the deployment in code (so you can recreate it from scratch, version it, or share it with teammates), drop this render.yaml at the root of any GitHub repo and link Render to it. Render watches the file and applies changes automatically.
Render’s docs on this file format: render.com/docs/blueprint-spec.

Using Render Secret Files for config

If you have an existing config.yaml (e.g. from a local install) and want to seed it on Render rather than configure through the dashboard:
1

Open Render dashboard for your service

Go to your service’s page → Environment tab in the left sidebar.
2

Add a Secret File

Scroll to Secret Files → click Add Secret File. Enter:Click Save.
3

Patch the config for the container

Two changes are needed in the version you paste, compared to a typical local-install config:1. Remove any dataDir: line at the top. Local configs from the install wizard usually have dataDir: /Users/yourname/.comis (a host absolute path that doesn’t exist inside the container). The image already sets COMIS_DATA_DIR=/home/comis/.comis and the persistent disk mounts there — drop the line and the daemon does the right thing.2. Set gateway.host: 0.0.0.0 (a typical install has 127.0.0.1, which means “loopback only” — Render’s load balancer can’t reach it).Example before / after:
4

Redeploy

Render auto-restarts the service when you save a Secret File. Watch the Logs tab — you should see your existing channels and agents register on boot.

Updating to a new Comis version

If you pinned a version tag (recommended), updating is a 30-second job:
1

Find the latest version

2

Update the image URL

On Render → your service → Settings → scroll to Image URL → change comisai/comis:1.0.53-slim to the new version → Save Changes.(Or, if you used render.yaml, edit the file in your repo and push — Render picks up the change.)
3

Render redeploys automatically

The service goes through a brief downtime (~30s) while Render pulls the new image, runs the health check, and switches traffic over. Your persistent disk is reattached unchanged, so all memory and config carry over.
If you’re on latest-slim instead, click Manual DeployDeploy latest commit.

Custom domain

Render gives every service a *.onrender.com URL with HTTPS for free. To use your own domain:
1

Add the domain in Render

Service page → SettingsCustom DomainsAdd Custom Domain → enter your domain (e.g. comis.example.com). Render shows you a CNAME target.
2

Set the DNS record

At your DNS provider, create a CNAME record pointing comis.example.com → the Render-provided target. Wait for DNS to propagate (usually a few minutes).
3

Render provisions TLS

Render auto-issues a Let’s Encrypt cert once the CNAME resolves. The custom-domains panel on Render shows the cert status.
No Comis-side configuration is needed for custom domains. Render terminates TLS at the edge and forwards plain HTTP to your container on port 4766.

Cost

Most personal Comis deployments run comfortably on Starter — the daemon’s baseline memory is around 200–400 MB and CPU is low except during LLM calls. The bulk of your spend is LLM API costs, not Render. A medium-traffic single-user agent typically runs 0.500.50–5/mo in Anthropic charges (see Context Engine & Cost Optimization for cache savings) — much more than Render’s $7.

Common issues

Open the Logs tab and look near the start of the most recent boot. Most common causes:
  • FATAL: Bootstrap failed: Config validation failed: gateway.tokens.0.secret: Too small You provided a COMIS_GATEWAY_TOKEN shorter than 32 characters. Generate a fresh one with openssl rand -hex 32 (which produces 64 hex chars, well over the 32-char minimum) and update the env var in Render.
  • FATAL: EACCES: permission denied, mkdir '/Users/...' Your config.yaml has a dataDir: line pointing at a host absolute path from a local machine. Remove that line — see Patch the config for the container.
  • Health check timing out Render’s default health check timeout is 30s, and Comis’s first boot can take 10–25s while it initializes the SQLite databases on the newly-attached disk. If it consistently times out, bump the health-check timeout in service settings.
Render’s load balancer returns 502 when it can’t reach your container. Almost always: the gateway is bound to 127.0.0.1 (loopback inside the container) instead of 0.0.0.0 (all interfaces).Fix: Verify both of these are set:
  • Env var COMIS_GATEWAY_HOST=0.0.0.0 (Settings → Environment)
  • Your config.yaml (if you uploaded one) has gateway.host: 0.0.0.0 — not 127.0.0.1. Config-file value wins over env var.
After fixing, click Manual Deploy → Deploy latest commit to restart.
You forgot to add the persistent disk, or its mount path is wrong.Fix: Service → Settings → scroll to Disks → confirm:
  • There is a disk attached
  • Mount Path is exactly /home/comis/.comis (this is the path the daemon reads — anything else gets ignored)
If you previously deployed without the disk and lost data, that’s unrecoverable — but adding the disk now will preserve everything from this point forward.
Yes. Render runs containers on real Linux kernels, so the bubblewrap exec sandbox is fully active — you’ll see "Exec sandbox provider detected" provider=bwrap at startup, with no Exec sandbox DISABLED warning.This is the major difference from Docker Desktop on macOS, where the linuxkit kernel forces the daemon into auto-disabled-sandbox mode. On Render, agent-issued shell commands run in a per-command sandbox that excludes /home/comis/.comis from its mount set — prompt-injected exec cannot read your .env, secrets.db, or config tokens.
Render’s Logs tab shows everything the container writes to stdout, which is full Pino JSON. To make it readable in your browser, use Render’s built-in filter box at the top of the tab — for example, type "level":50 to see only ERROR-level lines.For richer log analysis (cost summaries, cache hit rates, request timings), download the logs and run them through jq:
The structured fields include durationMs, tokensIn, tokensOut, cacheHitRate, costUsd per LLM call.
Common causes, in order of likelihood:
  1. TELEGRAM_BOT_TOKEN env var not set — the daemon logs "Channel telegram disabled" at startup if the token is missing or invalid. Add the var, redeploy.
  2. config.yaml doesn’t have channels.telegram.enabled: true — even if the token is set, the channel must be enabled in config.
  3. Telegram bot username collision / wrong token — easy to mix up tokens between bots if you have several. Test by hitting https://api.telegram.org/bot<YOUR_TOKEN>/getMe — that endpoint returns the bot’s identity, so you can confirm the token belongs to the bot you expect.
  4. allowFrom filtering — your config may have channels.telegram.allowFrom set to a Telegram user ID that doesn’t include the sender. The daemon logs the rejected sender at DEBUG level — search the logs for not in allowFrom.
Render → service page → Shell tab in the left sidebar. This opens an interactive shell inside the running container, running as the comis user. From there you can:
The shell is read-write on the persistent disk, so be careful — anything you change here lasts across deploys.
  1. Generate a new one: openssl rand -hex 32
  2. Render → service → Environment → update COMIS_GATEWAY_TOKEN with the new value
  3. Click Save Changes — Render auto-restarts the container
  4. Update any clients (the dashboard prompt, your scripts, etc.) to use the new token
The old token stops working immediately on restart. There’s no overlap window — for zero-downtime token rotation you’d need two tokens configured simultaneously (gateway.tokens is an array in config.yaml), use the new one in clients, then remove the old entry.

Next steps

Configuration Guide

Add agents, set policies, configure prompt caching, define channels.

Verify Installation

Diagnostic commands and expected outputs for a healthy install.

Operations: Docker

The full Docker reference — multi-stage build, security model, sandbox behavior, secrets management.

Docker Hub Tags

Tag scheme, version pinning, image variants (default vs slim).