A self-hostable deployment platform. Builds from a repo, managed databases, automatic HTTPS, opt-in pull request previews, running on your hardware, with no usage bill.
Website · Documentation · Quickstart · CLI · Issues · Security
Managed platforms are excellent right up to the point where the bill scales with your traffic, or the thing you need isn't on the menu. The usual escape route is a VPS, a Dockerfile, a reverse proxy, a certificate renewal cron, and a backup script you wrote once and never tested.
otterdeploy is the middle path: the control of running your own infrastructure with the ergonomics of a managed one. Point it at a supported Linux host, connect a repo, and you get builds, rollouts, routing, TLS, databases, backups, and logs: from a dashboard that stays calm, fast, and honest about what the system is actually doing.
Warning
Pre-1.0, under active development. Interfaces and schemas still change without migration paths, so otterdeploy isn't recommended for production workloads yet. Run it on something you'd be willing to rebuild.
One supported Linux box, one command:
curl -fsSL https://get.otterdeploy.com/install.sh | bashThe installer provisions the host, pulls the published images, puts Docker into Swarm mode, and brings the stack up: with the host firewall and CrowdSec on by default. It installs from prebuilt images, so no source checkout or build toolchain is needed on the server.
| Requirement | |
|---|---|
| Host | Debian/Ubuntu, RHEL/Fedora-family, or Arch Linux with root |
| Runtime | Docker 28+, installed and Swarm-enabled by the script if needed |
| Ports | 80 and 443 for the edge and ACME; dashboard port 3000 free by default |
Preview it without changing anything first:
curl -fsSL https://get.otterdeploy.com/install.sh | bash -s -- --dry-runThen open the dashboard on port 3000 and follow the first deploy guide. Tunables (data directory, version pin, optional ZFS pool, firewall opt-out) are documented in the install reference.
npm install -g @otterdeploy/cliShips as otterdeploy with an otd alias, with commands for deploys, logs, environments, and CI.
See the CLI reference.
curl -fsSL https://get.otterdeploy.com/uninstall.sh | sudo bashShows what's on the host, asks item by item what to remove, then requires you to type wipe.
Volumes, /data/otterdeploy, the ZFS pool, Swarm and Docker are each opt-out, but the defaults
do delete your data. Add -s -- --dry-run to preview. See the
uninstall reference.
|
Build & deploy Framework auto-detect · Dockerfile builds · Monorepo aware · Compose stacks · 90+ stack templates · Rollback · Crash reporting · Environments |
Edge & networking Multi-domain routing · Automatic TLS · Custom certificates · Layer-4 exposure · Deployment protection · Access logs · Edge events · CrowdSec |
Data Postgres · Redis · MariaDB · MongoDB · ClickHouse · Built-in data browser · Encrypted backups · Scheduled snapshots · Volumes & mounts |
|
Operate Live logs · CPU & memory metrics · Web terminal · Multi-node Swarm · Tailscale & NetBird node join · Host health alerts · Slack, Discord, PagerDuty · Raw Docker |
Access & security Org RBAC · Scoped API keys · Audit log · Sealed variables · Host firewall · SSH keys · Private registries · Anomaly alerts |
Automate
|
Enable previews per service and pull requests get their own deployment, with optional PostgreSQL branching and idle garbage collection. PostgreSQL branches currently use logical copies; the planned ZFS strategy falls back to a logical copy with a warning.
push → pending → building (railpack) → image pushed → rollout (swarm) → route (caddy) → tls issued
A commit lands, the API queues a build, and a BullMQ worker builds an image with Railpack and pushes it to your registry. Docker Swarm rolls the service out, Caddy picks up the route, and ACME issues the certificate. Each of those states is a real state in the schema, shown as-is in the dashboard, no spinner standing in for a failure.
Requirements: Bun, Docker (with compose), and portless for local HTTPS.
bun install
# one-time: local HTTPS proxy + CA trust
npm install -g portless
sudo portless trust
# each session
bun run proxy # portless proxy on :443
bun run infra # Postgres + supporting services via Docker Compose
bun run db:push # apply the schema
bun run dev # web + API (everything except the build worker)The dashboard comes up at https://web.otterdeploy.local, the API at
https://api.otterdeploy.local.
| Script | |
|---|---|
bun run dev |
All apps in dev mode (excludes the builder) |
bun run dev:web / dev:server |
A single app |
bun run build |
Build everything |
bun run test |
Run the test suites |
bun run typecheck |
TypeScript across the monorepo |
bun run lint / format |
Oxlint / Oxfmt |
bun run db:studio |
Database UI |
Before opening a pull request, run bun run typecheck, bun run lint, and bun run test. UI work
should be read against PRODUCT.md and DESIGN.md first. They are
the design system of record, and "Coming soon" is always preferred over seeded data.
Monorepo layout
otterdeploy/
├── apps/
│ ├── web/ # Dashboard (React, TanStack Router)
│ ├── server/ # API server (Hono + oRPC)
│ ├── builder/ # BullMQ build worker. Builds git-sourced services
│ ├── cli/ # End-user CLI (`otterdeploy` / `otd`)
│ └── www/ # Marketing site & docs (otterdeploy.com)
├── packages/
│ ├── api/ # oRPC contracts, handlers, manifest schema
│ ├── auth/ # Authentication (Better Auth)
│ ├── db/ # Postgres schema & migrations (Drizzle)
│ ├── email/ # Email client & templates (Resend)
│ ├── jobs/ # Job queue, workers, triggers, registry (BullMQ)
│ └── shared/ # Shared types & utilities
├── brand/ # Logo geometry + generated assets (build output. Don't hand-edit)
└── scripts/ # install.sh, uninstall.sh, maintenance scripts
TypeScript end to end: Bun, Turborepo, Hono, oRPC, Zod, Drizzle, PostgreSQL, TanStack Router/DB, Tailwind, BullMQ, and Pino/OpenTelemetry for observability. Deploys run on Docker Swarm behind Caddy.
Copyright © 2026 otterdeploy contributors.
Licensed under the GNU Affero General Public License v3.0. You can self-host, modify, and redistribute otterdeploy freely; if you offer a modified version as a network service, the AGPL requires you to make your modified source available to its users.