Self-hosting
DodoRouter is a standard Phoenix 1.8 application backed by PostgreSQL. Source: github.com/foxwise-ai/dodorouter. License terms are covered in License below — in short, free to self-host and modify, but you can't resell it as your own competing hosted service.
Prerequisites
- Elixir 1.15+ and a matching Erlang/OTP
- PostgreSQL 12+
- An Infisical project (free tier is fine) — see the callout below, this is currently required, not optional
⚠ Infisical is currently required
Every provider API key you add (OpenAI, Anthropic, z.ai, …) is stored via Infisical, a secrets manager — there is currently no local/plaintext fallback in the code. Without INFISICAL_TOKEN and INFISICAL_PROJECT_ID set, the app boots fine and the dashboard loads, but clicking Add Key on the Providers page will fail with "Failed to store API key securely" — so you won't be able to configure any provider, and no requests will succeed. Sign up at Infisical, create a project, create a Machine Identity with a Universal Auth client, and use that identity's access token as INFISICAL_TOKEN.
1. Clone and install
git clone https://github.com/foxwise-ai/dodorouter.git
cd dodorouter
mix deps.get
2. Configure environment variables
For local development, export these before starting the server (e.g. in .envrc with direnv, or a .env you source):
# Database — defaults match config/dev.exs; override if yours differs
export DB_USERNAME=postgres
export DB_PASSWORD=postgres
export DB_HOSTNAME=localhost
export DB_PORT=5432
export DB_NAME=dodo_router_dev
# Infisical — required, see callout above
export INFISICAL_TOKEN="<your machine identity access token>"
export INFISICAL_PROJECT_ID="<your infisical project id>"
export INFISICAL_ENVIRONMENT=dev # optional, defaults to "prod"
3. Set up the database
mix ecto.setup
4. Start the server
mix phx.server
Visit http://localhost:4000. Register an account, confirm via the magic-link email — in dev, DodoRouter uses Swoosh's local mailbox instead of sending real email, so open http://localhost:4000/dev/mailbox to read it. From there, follow the same steps as the Quickstart.
Verified: GET /health returns {"status":"ok"} once the DB connection is healthy, and GET /api/version returns the running app version, e.g. {"version":"0.1.75"} — handy for confirming the app booted and for health-check probes.
Production environment variables
| Variable | Required | Notes |
|---|---|---|
DATABASE_URL |
Yes | e.g. ecto://user:pass@host/dodo_router_prod |
SECRET_KEY_BASE |
Yes | Generate with mix phx.gen.secret |
PHX_HOST |
Yes | Your public domain |
PHX_SERVER |
Yes | Set to true to actually start the endpoint under a release |
PORT |
No | Defaults to 4000 |
INFISICAL_TOKEN |
Yes* | *Required for provider-key storage to work at all (see callout above) |
INFISICAL_PROJECT_ID |
Yes* | Paired with the token above |
INFISICAL_ENVIRONMENT |
No | Defaults to prod |
RESEND_API_KEY |
No | Transactional email (magic links). Without it in prod, mail simply won't send |
EMAIL_FROM |
No | Defaults to noreply@dodorouter.com |
STRIPE_SECRET_KEY |
No | Only set this if you want the $19/mo billing paywall enabled. Unset = billing disabled, everyone has full access |
STRIPE_WEBHOOK_SECRET |
No | Required only alongside STRIPE_SECRET_KEY |
ECTO_IPV6 |
No | Set to true to enable IPv6 for the DB socket |
POOL_SIZE |
No | Ecto pool size, defaults to 10 |
For deploy specifics (hot code upgrades, systemd, Castle release management), see the project's own AGENTS.md in the repo — those are maintainer-facing operational details rather than user-facing setup, so we won't duplicate them here. See also Deployment for a minimal production boot sequence.
License
DodoRouter is source-available under the O'Saasy License. In short: you're free to use, modify, self-host, and even sell copies of it — the one thing you can't do is turn around and offer it as a competing hosted/managed service where the software itself is the product. See the full license text in the repository for the exact terms.