doable-cli: Operator TUI¶
doable is a Rust terminal UI that operators run from their own machine to
provision fresh Doable servers and manage existing ones. It is the interactive
replacement for running server-setup.sh by hand over SSH.
Screenshot:
(TODO)
What it is¶
| Mode | Command | When to use |
|---|---|---|
| Interactive picker | doable (no subcommand) |
First time; lets you choose a mode with arrow keys |
| Fresh server install | doable install ... |
Provisioning a brand-new VPS |
| Manage local server | doable admin |
On the server itself, or via SSH + --database-url |
| Manage remote server | doable admin --remote user@host |
From your laptop, tunnelling DB access over SSH |
The binary is named doable and ships at doable-cli/ in the monorepo
(version 0.3.0, MIT licensed).
Install¶
Pre-built binary (recommended)¶
Download the latest release for your OS from the
GitHub Releases page and put
it somewhere on your PATH:
# example: adjust OS/arch and version
curl -L https://github.com/doable-me/doable/releases/latest/download/doable-linux-x86_64 \
-o ~/.local/bin/doable
chmod +x ~/.local/bin/doable
Build from source¶
You need Rust >= 1.80 and a working ssh binary on
PATH (macOS/Linux ship one; Windows users can use Git for Windows or WSL).
Demo mode (no real server needed)¶
This replays a canned provisioning session so you can explore the TUI without touching a server.
Provision a fresh server¶
Prerequisites¶
- A clean Ubuntu 22.04 or 24.04 VPS with SSH access.
- Your SSH public key installed on the server (
~/.ssh/authorized_keys). - A Cloudflare account + a domain pointed at Cloudflare (for the tunnel step).
Interactive launch (recommended)¶
doable install \
--host 203.0.113.10 \
--user ubuntu \
--env-name myorg \
--ssh-key ~/.ssh/id_ed25519
The TUI opens and walks through 15 phases, showing live streaming output on the right and a colour-coded phase list on the left:
┌──────────────────────────────────────────────────────────────────────┐
│ Doable Installer │ host: 203.0.113.10 user: ubuntu env: myorg │
│ │ elapsed: 03:21 │
├────────────────────┬─────────────────────────────────────────────────┤
│ Phases (4/15) │ Setup output │
│ ✅ 1 Preflight │ ════════ Phase 4/15: PostgreSQL 16 + ext. │
│ ✅ 2 System pkgs │ apt-get update │
│ ✅ 3 Node 22+pnpm │ installing postgresql-16 ... │
│ 🔄 4 PostgreSQL │ creating role doable ... │
│ ⏳ 5 Caddy │ running migrations ... │
│ ⏳ 6 Puppeteer │ │
│ ⏳ 7 Repo clone │ │
│ ⏳ ... 15 │ │
├────────────────────┴─────────────────────────────────────────────────┤
│ q=quit l=toggle log filter r=retry phase p=pause │
└──────────────────────────────────────────────────────────────────────┘
The 15 phases (mirrors setup-server-v3.sh):
- Preflight checks (OS version, disk space, SSH connectivity)
- System packages (curl, git, build-essential, tmux, fail2ban, ufw)
- Node.js 22 + pnpm
- PostgreSQL 16 + pgvector + pgcrypto + pg_trgm extensions + migrations
- Caddy (reverse proxy, auto-SSL, binds to
127.0.0.1) - Puppeteer / Chromium dependencies (thumbnail generation)
- Repo clone / pull to
/root/doable - pnpm install + initial build
.envgeneration (JWT_SECRET, ENCRYPTION_KEY, DB password; all random)- UFW firewall (deny-all + allow SSH)
- Swap file (2 GB)
- Cloudflare Tunnel login + tunnel creation
- Cloudflare DNS records + Caddyfile
- systemd units (
doable.service,cloudflared.service) - tmux session (
api,web,wswindows) + smoke test
Unattended / CI mode¶
DOABLE_HOST=203.0.113.10 \
DOABLE_USER=ubuntu \
DOABLE_ENV_NAME=myorg \
DOABLE_SSH_KEY=$HOME/.ssh/id_ed25519 \
DOABLE_NON_INTERACTIVE=1 \
doable install
Key bindings during install¶
| Key | Action |
|---|---|
q / Esc / Ctrl-C |
Quit |
| l | Toggle log filter (errors only) |
| r | Flag current phase for retry |
| p | Pause auto-scroll |
Manage an existing host¶
Local (run on the server)¶
Reads DATABASE_URL from /opt/doable/.env automatically.
Remote (from your laptop)¶
doable admin --remote [email protected] --ssh-key ~/.ssh/id_ed25519
The TUI opens an SSH tunnel to the server and proxies the PostgreSQL connection through it; no extra port needs to be open.
Print credentials (non-interactive)¶
doable admin --remote [email protected] --print-db-url # full postgres URL
doable admin --remote [email protected] --print-db-pass # password only
Useful for piping into psql, DBeaver, or other tools.
Admin screens¶
Once in doable admin you get a full-screen management TUI with these sections:
- Users & Admins: toggle platform-admin flag, view last login, force logout
- Feature Flags: flip feature flags on/off per workspace or globally
- Members & Roles: manage workspace membership and roles, reset MFA
- AI Settings: per-workspace model enforcement and provider configuration
- Server Config: edit live server files (Linux only):
- Squid allowlist (
/etc/squid/squid.conf): add/remove egress hostnames - cloudflared ingress (
/etc/cloudflared/config.yml): manage tunnel routes - API
.env: editDOABLE_*/ proxy /NODE_ENVknobs - systemd hardening (read-only view)
- Squid allowlist (
Inside Server Config: 1-4 switch tabs, Enter edits, a adds, d
deletes, A applies pending changes (with confirmation), R reloads from
disk.
sudoers fragment required for Server Config writes
File writes and service reloads are mediated through sudo. Install the
bundled fragment once on each server:
Comparison with the /admin web panel¶
doable admin TUI |
/admin web panel |
|
|---|---|---|
| Who uses it | Server operators (SSH access) | Platform admins (browser, admin role in the app) |
| Connection | SSH / local process | HTTPS via Cloudflare Tunnel |
| Can edit server files | Yes | No |
| Can manage users/roles | Yes | Yes |
| Requires DB access | Yes (direct) | No (uses app API) |
| Works when app is down | Yes | No |
Use the TUI when you need low-level server control or when the web app is
unreachable. Use the /admin panel for day-to-day user and workspace
management.
Network safety¶
The installer uploads setup-server-v3.sh, which binds all services to
127.0.0.1 and exposes them only via Cloudflare Tunnel. No port is reachable
from the public internet after provisioning completes. See
Bare-metal deployment for the full network diagram.
(TODO)