Skip to content

Reference deploys — Docker / Fly.io / Render

If you followed the OSS Quick Start, you have a working ggui serve on localhost. This page walks through putting that same server on a public URL so your phone, teammates, or collaborators can reach it. Three drop-in manifests — generic Docker, Fly.io, Render.com — all shipped in the open @ggui-ai/build-templates package.

None of these deploys phone home. They run your code on your infrastructure. The Guuey app pairs with the public URL using the flow in Pair the Guuey app.

All three live at github.com/ggui-ai/ggui → packages/build-templates/templates/:

FilePurpose
oss-serve.dockerfileMulti-stage Node 22 image that boots ggui serve on $PORT.
fly.toml.exampleFly.io manifest — scales to zero, healthchecks /ggui/health.
render.yaml.exampleRender.com Blueprint — Docker runtime, healthchecks /ggui/health.

Copy whichever you need into your project root (renaming .example suffixes as indicated).

Works anywhere Docker runs: EC2, your homelab, a Raspberry Pi, a Coolify VPS.

Terminal window
# From your project root:
curl -O https://raw.githubusercontent.com/ggui-ai/ggui/main/packages/build-templates/templates/oss-serve.dockerfile
mv oss-serve.dockerfile Dockerfile
docker build -t my-ggui .
docker run --rm -p 6781:6781 -e PORT=6781 my-ggui

The image exposes /ggui/health, /mcp, /ws, /pair, /s/<shortCode>, and / (operator console) on $PORT. Once running, pair the Guuey app at http://<docker-host>:6781 and follow the Pairing guide.

ggui serve binds plaintext. Put a TLS-terminating reverse proxy in front for anything beyond a LAN (Caddy, nginx, Cloudflare Tunnel). A minimal Caddy example:

my-ggui.example.com {
reverse_proxy 127.0.0.1:6781
}

Fly gives you a free-tier region, HTTPS by default, and scale-to-zero. The fly.toml.example manifest wires all of that up:

Terminal window
# From your project root:
curl -O https://raw.githubusercontent.com/ggui-ai/ggui/main/packages/build-templates/templates/oss-serve.dockerfile
mv oss-serve.dockerfile Dockerfile
curl -O https://raw.githubusercontent.com/ggui-ai/ggui/main/packages/build-templates/templates/fly.toml.example
mv fly.toml.example fly.toml
# Edit the app name + region in fly.toml, then:
fly launch --no-deploy
fly deploy

The [http_service] block turns on force_https = true, so the URL you hand to the Guuey app is https://<app>.fly.dev — no proxy setup needed.

auto_stop_machines = true + min_machines_running = 0 means Fly freezes the machine when it’s idle and thaws it on the next request (~1-2 s cold start). Fine for a personal server; turn off if you need zero-latency persistence (e.g., mid-conversation).

Render is the simplest “click-a-button” story. Point Render at your repo, commit the manifest + Dockerfile, and it deploys on every push.

Terminal window
# From your project root:
curl -O https://raw.githubusercontent.com/ggui-ai/ggui/main/packages/build-templates/templates/oss-serve.dockerfile
mv oss-serve.dockerfile Dockerfile
curl -O https://raw.githubusercontent.com/ggui-ai/ggui/main/packages/build-templates/templates/render.yaml.example
mv render.yaml.example render.yaml
git add Dockerfile render.yaml
git commit -m "chore: add ggui serve reference deploy"
git push

Then in Render’s dashboard: New → Blueprint → connect your repo. Render reads render.yaml, provisions the service, and deploys on main pushes. You get a https://<name>.onrender.com URL.

Swap plan: starter for standard if your agent does heavier in-process work (embeddings, large prompts).

The default ggui serve auth is dev-mode — any non-empty bearer is accepted as builder. That’s fine on 127.0.0.1; it is NOT safe on a public URL. Before you hand a public URL to the Guuey app:

  1. Swap in a real AuthAdapter. Wrap your agent entrypoint with a custom createGguiServer({ auth }) that gates the /mcp and /ws endpoints. See @ggui-ai/mcp-server-core’s AuthAdapter interface.
  2. Set a production-grade bearer. The Dockerfile / manifests reference a placeholder GGUI_AUTH_BEARER env var. Replace it with a strong token and store it in your PaaS’s secret store (Fly secrets, Render environment groups).
  3. Firewall /admin/*. Only /admin/pair/init needs operator-level access — front it with a reverse-proxy rule that restricts the /admin/ prefix to an allow-list IP or a VPN.
  4. Rotate pairings. Revoke stale paired devices periodically from the operator console at /.

Ignoring these is how a “deployed ggui serve” becomes an open relay. Do the hardening pass; it’s ~15 minutes of work.

  • Managed deploys. These are reference assets — no auto-updates, no managed rollouts, no cloud-based dashboard beyond what the PaaS ships. If you want “push to main → zero-downtime rollout with observability,” Render + its built-in logs/metrics gets closer; real production SRE is out of scope.
  • Multi-region replication. Each deploy is a single instance. ggui serve is stateful-per-process today; replicas won’t share session state without a shared session store (the storage.sessions field in ggui.json supports sqlite; durable multi-instance storage is on the roadmap).
  • Guuey hosting. If you want us to run it for you — with builds, logs, quotas, BYOK, billing — the hosted path is guuey deploy.