Self-hosting
Ony.ai’s open-source core (AGPL-3.0) runs entirely on your own infrastructure, with your own domain, telephony carrier, models, and database. Nothing depends on ony.ai.
There are two supported ways to run the control plane. Pick by team size and durability needs, not by feature: the OSS core is fully featured in both.
One person, zero dependencies. Install from PyPI and start a full Ony.ai server on SQLite. No Docker,
Postgres, or Valkey is required (those stores fall back to in-memory), and ony up generates its own
signing secret on first run.
pip install onyony up # full server on SQLite; prints the local URLThen, from a project directory, enroll the machine and wire up your coding agent:
ony init # enrolls this machine and wires Claude CodeThis is the fastest path for a single developer. See the quickstart for the full
walkthrough, and the CLI reference for ony up, ony init, and ony doctor.
Team and production. The Docker Compose stack runs the API, the dashboard, Postgres 18, and Valkey
(a drop-in, BSD-licensed Redis replacement) behind one web origin. deploy/docker-compose.prod.yml is
the production path.
-
Configure. Copy the example env and set the required values.
Terminal window cp .env.example .envAt minimum set:
ONY_SIGNING_SECRET- a strong random value (e.g.openssl rand -hex 32); it signs decision tokens and the audit chain.ONY_DB_PASSWORD- the Postgres password for the stack (the in-network DB URL is derived from it).ONY_PUBLIC_BASE_URL- the publichttps://URL that fronts thewebservice (step 3).- A carrier, either here or from the dashboard later. See carrier setup.
-
Run it from the repo root:
Terminal window docker compose --project-directory . -f deploy/docker-compose.prod.yml up -d --build--project-directory .is required so Compose resolves${...}values against the root.env. The stack builds the images, starts Postgres and Valkey, applies database migrations on the API’s first start, and serves the dashboard onhttp://localhost:${ONY_WEB_PORT:-8080}. -
Expose it publicly so your carrier can reach the webhooks (see the edge options below), point
ONY_PUBLIC_BASE_URLat that hostname, and restart theapiservice. -
Create the first account at
/signup, verify your phone under Settings, then connect a coding agent.
What you still bring
Section titled “What you still bring”Self-hosting is bring-your-own for everything that costs money or touches a third party:
- Telephony carrier (required for real calls). SignalWire, Twilio, Telnyx, or Plivo. There is no bundled number - self-host means your carrier account. See carrier setup.
- A public domain or tunnel so the carrier can reach
${ONY_PUBLIC_BASE_URL}/webhooks/.... - Models (optional). The voice brain is OpenAI-compatible; with no key it falls back to deterministic intent matching, so inbound voice still works. See the configuration reference.
Only ONY_SIGNING_SECRET is truly required to boot; everything else is optional and can be added from
the dashboard later.
Two ways to configure providers
Section titled “Two ways to configure providers”You can mix these:
- From the dashboard (recommended, no restart). In Settings -> Integrations, an admin adds a
carrier and voice models with a built-in credential test. These are encrypted at rest (Fernet, keyed
from
ONY_SIGNING_SECRET) in the database and applied live. A dashboard-configured carrier takes precedence over the env value. - From the environment (config-as-code). Everything can be set in
.envfor reproducible deployments. See.env.exampleand the configuration reference.
Bring your own domain: three webhook-edge options
Section titled “Bring your own domain: three webhook-edge options”The carrier must reach ${ONY_PUBLIC_BASE_URL}/webhooks/.... Ony.ai only needs ONY_PUBLIC_BASE_URL
pointed at a publicly reachable address; how you get there is your choice.
- Reverse proxy (Caddy / nginx / Traefik) on your own server and domain, forwarding to the Ony.ai web origin. The standard production setup.
- Cloudflare Tunnel. Run
cloudflarednext to the stack; it dials out to Cloudflare, so there are no open inbound ports. Add-f deploy/docker-compose.cloudflared.ymland setONY_TRUST_CF_CONNECTING_IP=true. Runbook: CLOUDFLARE-TUNNEL.md. - Cloudflare Worker edge. Deploy the Worker in
deploy/cloudflare-worker/onhooks.yourdomain.com; it forwards/webhooks/*(and optionally/api/*) to your origin. Good when the backend sits on a private network. When the edge is webhook-only, setONY_WEB_BASE_URLto the host that actually serves the dashboard so user-facing links stay correct.
Deploy runbooks in the repo
Section titled “Deploy runbooks in the repo”The deploy/ directory holds the operational guides:
- README.md - stand the stack up.
- RUNBOOK.md - health checks, backups, migrations, and secret rotation.
- SCALING.md - multi-instance and DoS
tuning (a shared
ONY_REDIS_URLis required for cross-worker decision push). - BACKUP.md - nightly encrypted backups.
Before you expose it
Section titled “Before you expose it”Work through the hardening guide (secrets and rotation, per-channel webhook auth, trusted proxy hops, TLS, and a pre-deploy checklist) and read the threat model. Risk classification is server-authoritative: a call happens only when policy permits it.
License
Section titled “License”The core is AGPL-3.0. If you run a modified version as a network service, you must offer your modified source to its users. A hosted plan (no infrastructure to run) lives at ony.ai and is currently a waitlist.