Ambit CLI
What Ambit Is
Ambit deploys apps to the cloud in a way that makes them completely unreachable from the public internet. Only devices enrolled in the user's private Tailscale network can connect to them. From the outside world's perspective, the app does not exist — there is no IP address to find, no port to scan.
This matters because putting a database, dashboard, or internal tool on the normal internet forces you to build login pages, configure firewalls, and harden the app against strangers. Ambit skips all of that. Access control is handled at the network level: if a device is on the Tailscale network, it can reach the app; if it isn't, the connection is refused before the app ever sees it.
Each private network you create is called an ambit. Every app deployed to it gets a human-readable address under that network's name — so http://my-app.lab means the my-app application on the lab ambit. These addresses work automatically for any device enrolled in the user's Tailscale account.
Installation
If ambit is not already installed, run it directly via Nix:
CODEBLOCK0
How It Works
CODEBLOCK1
Ambit creates a router on Fly.io that joins the user's Tailscale network and advertises the private IPv6 subnet for that ambit. It also sets up split DNS so that *.<network> queries resolve to the right app. Apps deployed with ambit deploy get a private Flycast address on the network and never receive a public IP.
Prerequisites
- -
flyctl installed and authenticated (fly auth login) - Tailscale installed and connected (
tailscale up) - Accept-routes enabled (
sudo tailscale set --accept-routes) - A Tailscale API access token (
tskey-api-...) — create one at https://login.tailscale.com/admin/settings/keys
Commands
ambit create <network>
Creates a new private network. This is the first command to run when setting up a new ambit. It deploys a router on Fly.io, connects it to the user's Tailscale network, and configures split DNS so apps on the network are reachable by name.
CODEBLOCK2
Flags:
- -
--org <org> — Fly.io organization slug - INLINECODE13 — Fly.io region (default:
iad) - INLINECODE15 — Tailscale API access token (prompted interactively if omitted)
- INLINECODE16 — Tailscale ACL tag for the router (default:
tag:ambit-<network>) - INLINECODE18 — Approve subnet routes via Tailscale API instead of requiring autoApprovers in the ACL policy
- INLINECODE19 — Skip confirmation prompts
- INLINECODE20 — Output as JSON
What it does:
- 1. Validates Fly.io auth and the Tailscale API key
- Checks that the tag (default
tag:ambit-<network>, or custom via --tag) exists in Tailscale ACL tagOwners - Checks autoApprovers config (unless
--self-approve) - Creates a Fly.io app on the custom network
- Sets secrets:
TAILSCALE_API_TOKEN, NETWORK_NAME, INLINECODE26 - Deploys the router container
- Waits for the device to join the tailnet
- Configures split DNS (
*.<network> → router) - Enables accept-routes locally if possible
Before running, the user must add the router's tag in their Tailscale ACL settings at https://login.tailscale.com/admin/acls/visual/tags. The tag defaults to tag:ambit-<network> but can be overridden with --tag.
And optionally (or use --self-approve to skip this):
CODEBLOCK3
ambit deploy <app> --network <name>
Deploys an app onto a private network. This is the safe alternative to fly deploy: it always passes --no-public-ips and --flycast, runs pre-flight checks on the fly.toml for dangerous settings, and audits the result to verify no public IPs were allocated.
There are three mutually exclusive deployment modes:
Config mode (default) — uses a local fly.toml:
CODEBLOCK4
Image mode — deploys a Docker image without fly.toml:
CODEBLOCK5
Template mode — fetches a template from a GitHub repository and deploys it:
CODEBLOCK6
Flags:
- -
--network <name> — Target network (required) - INLINECODE37 — Fly.io organization
- INLINECODE38 — Primary region
- INLINECODE39 — Explicit path to fly.toml (config mode)
- INLINECODE40 — Docker image to deploy (image mode)
- INLINECODE41 — Internal port for HTTP service in image mode (default: 80, "none" to skip)
- INLINECODE42 — GitHub template reference (template mode)
- INLINECODE43 — Skip confirmation
- INLINECODE44 — Output as JSON
Template reference format:
CODEBLOCK7
The template must contain a fly.toml (and typically a Dockerfile). The template is fetched from GitHub's tarball API, the target subdirectory is extracted, pre-flight scanned, and deployed. The temp directory is cleaned up automatically.
ambit list
Lists all discovered routers across all networks.
CODEBLOCK8
Shows: network name, app name, region, machine state, private IP, subnet, and Tailscale device status.
ambit status
Shows detailed router status. Run without --network to see all routers, or with --network to focus on one.
CODEBLOCK9
Detailed view includes: machine state, SOCKS5 proxy address, Tailscale IP, online status, advertised routes, and split DNS config.
ambit destroy --network <name>
Tears down a router and cleans up all associated resources. Apps deployed on the network are NOT deleted — only the router is removed. The user will need to manually remove ACL policy entries for the network tag.
CODEBLOCK10
What it does:
- 1. Finds the router app for the network
- Clears split DNS configuration
- Removes the Tailscale device
- Destroys the Fly.io app
ambit doctor
Health check for the local environment and router infrastructure. Run this whenever something seems wrong — it checks the most common failure points and gives remediation hints.
CODEBLOCK11
Checks:
- - Tailscale CLI installed
- Tailscale connected (BackendState = Running)
- Accept-routes enabled
- Router(s) exist and machines are running
- Router(s) visible in tailnet
Templates
Ready-to-deploy templates are available at ToxicPine/ambit-templates:
| Template | Description |
|---|
| INLINECODE53 | Headless Chrome exposing Chrome DevTools Protocol on port 9222 — for AI agents or scripts that need a browser on the private network. |
| INLINECODE54 |
A cloud devshell with a web terminal, persistent home directory, passwordless sudo, and auto start/stop. |
|
ToxicPine/ambit-templates/opencode | A private OpenCode web workspace — Nix-based environment with persistent home and auto start/stop. |
CODEBLOCK12
Common Workflows
First-Time Setup
CODEBLOCK13
Deploy from a Template
CODEBLOCK14
Debugging Connectivity
CODEBLOCK15
Tearing Down
CODEBLOCK16
Troubleshooting
| Symptom | Fix |
|---|
| "Tag not configured in tagOwners" | Add "tag:ambit-<network>": ["autogroup:admin"] to Tailscale ACL tagOwners. |
| "autoApprovers not configured" |
Either configure autoApprovers in the ACL or re-run with
--self-approve. |
| Router deployed but not reachable | Run
ambit doctor. Check that accept-routes is enabled locally. |
| "Timeout waiting for device" | Check router logs. Most common cause: expired or invalid Tailscale API key. |
| Apps not resolving as
<app>.<network> | Verify split DNS is configured:
ambit status --network <name>. Check the router is online in the tailnet. |
| "Flyctl not found" | Install from https://fly.io/docs/flyctl/install/ |
Ambit CLI
Ambit 是什么
Ambit 以完全无法从公共互联网访问的方式将应用部署到云端。只有注册到用户私有 Tailscale 网络的设备才能连接到这些应用。从外部世界的角度来看,这个应用并不存在——没有可查找的 IP 地址,没有可扫描的端口。
这一点很重要,因为将数据库、仪表盘或内部工具放在普通互联网上,会迫使你构建登录页面、配置防火墙,并加固应用以抵御陌生人。Ambit 跳过了所有这些步骤。访问控制是在网络层面处理的:如果设备在 Tailscale 网络上,它就能访问应用;如果不在,连接在应用看到之前就被拒绝了。
你创建的每个私有网络都称为一个 ambit。部署到该网络的每个应用都会获得该网络名称下的人类可读地址——因此 http://my-app.lab 表示 lab ambit 上的 my-app 应用。这些地址对注册到用户 Tailscale 账户的任何设备都自动生效。
安装
如果尚未安装 ambit,可以通过 Nix 直接运行:
bash
npx @cardelli/ambit
工作原理
mermaid
graph LR
A[你的设备
在 Tailscale 上] -->|Tailscale 隧道| B[Ambit 路由器
Fly.io 虚拟机]
B -->|Flycast / 私有 IPv6| C[你的应用
无公网 IP]
Ambit 在 Fly.io 上创建一个路由器,该路由器加入用户的 Tailscale 网络,并通告该 ambit 的私有 IPv6 子网。它还设置拆分 DNS,使得 *. 查询解析到正确的应用。使用 ambit deploy 部署的应用会获得网络上的私有 Flycast 地址,且永远不会获得公网 IP。
前提条件
- - flyctl 已安装并认证(fly auth login)
- Tailscale 已安装并连接(tailscale up)
- 已启用接受路由(sudo tailscale set --accept-routes)
- Tailscale API 访问令牌(tskey-api-...)——在 https://login.tailscale.com/admin/settings/keys 创建
命令
ambit create
创建一个新的私有网络。这是设置新 ambit 时要运行的第一个命令。它在 Fly.io 上部署一个路由器,将其连接到用户的 Tailscale 网络,并配置拆分 DNS,使得网络上的应用可以通过名称访问。
bash
ambit create lab
ambit create lab --org my-org --region sea
ambit create lab --self-approve
标志:
- - --org — Fly.io 组织标识
- --region — Fly.io 区域(默认:iad)
- --api-key — Tailscale API 访问令牌(如果省略则交互式提示)
- --tag — 路由器的 Tailscale ACL 标签(默认:tag:ambit-)
- --self-approve — 通过 Tailscale API 批准子网路由,而不是在 ACL 策略中要求 autoApprovers
- -y, --yes — 跳过确认提示
- --json — 以 JSON 格式输出
功能说明:
- 1. 验证 Fly.io 认证和 Tailscale API 密钥
- 检查标签(默认 tag:ambit-,或通过 --tag 自定义)是否存在于 Tailscale ACL tagOwners 中
- 检查 autoApprovers 配置(除非使用 --self-approve)
- 在自定义网络上创建 Fly.io 应用
- 设置密钥:TAILSCALEAPITOKEN、NETWORKNAME、TAILSCALETAGS
- 部署路由器容器
- 等待设备加入 tailnet
- 配置拆分 DNS(*. → 路由器)
- 如果可能,在本地启用接受路由
运行之前,用户必须在 https://login.tailscale.com/admin/acls/visual/tags 的 Tailscale ACL 设置中添加路由器的标签。标签默认为 tag:ambit-,但可以通过 --tag 覆盖。
并且可选地(或使用 --self-approve 跳过此步骤):
json
autoApprovers: { routes: { fdaa:X:XXXX::/48: [tag:ambit-] } }
ambit deploy --network
将应用部署到私有网络上。这是 fly deploy 的安全替代方案:它始终传递 --no-public-ips 和 --flycast,对 fly.toml 进行预检以检查危险设置,并审计结果以验证未分配公网 IP。
有三种互斥的部署模式:
配置模式(默认)——使用本地 fly.toml:
bash
ambit deploy my-app --network lab
ambit deploy my-app --network lab --config ./custom.toml
镜像模式——无需 fly.toml 部署 Docker 镜像:
bash
ambit deploy my-app --network lab --image registry.fly.io/my-app:latest
ambit deploy my-app --network lab --image registry.fly.io/my-app:latest --main-port 3000
模板模式——从 GitHub 仓库获取模板并部署:
bash
ambit deploy my-browser --network lab --template ToxicPine/ambit-templates/chromatic
ambit deploy my-browser --network lab --template ToxicPine/ambit-templates/chromatic@v1.0
ambit deploy my-shell --network lab --template ToxicPine/ambit-templates/wetty
标志:
- - --network — 目标网络(必需)
- --org — Fly.io 组织
- --region — 主要区域
- --config — fly.toml 的显式路径(配置模式)
- --image
— 要部署的 Docker 镜像(镜像模式) - --main-port — 镜像模式下 HTTP 服务的内部端口(默认:80,none 跳过)
- --template
[ — GitHub 模板引用(模板模式)] - -y, --yes — 跳过确认
- --json — 以 JSON 格式输出
模板引用格式:
owner/repo/path 从默认分支获取
owner/repo/path@tag 获取标记的发布版本
owner/repo/path@branch 获取特定分支
owner/repo/path@commit 获取特定提交
模板必须包含 fly.toml(通常还有 Dockerfile)。模板从 GitHub 的 tarball API 获取,提取目标子目录,进行预检扫描,然后部署。临时目录会自动清理。
ambit list
列出所有网络中发现的所有路由器。
bash
ambit list
ambit list --org my-org --json
显示:网络名称、应用名称、区域、机器状态、私有 IP、子网和 Tailscale 设备状态。
ambit status
显示详细的路由器状态。不带 --network 运行可查看所有路由器,带 --network 可聚焦于一个。
bash
ambit status
ambit status --network lab
详细视图包括:机器状态、SOCKS5 代理地址、Tailscale IP、在线状态、通告路由和拆分 DNS 配置。
ambit destroy --network
拆除路由器并清理所有相关资源。部署在网络上的应用不会被删除——仅移除路由器。用户需要手动删除网络标签的 ACL 策略条目。
bash
ambit destroy --network lab
ambit destroy --network lab --yes
功能说明:
- 1. 查找网络的路由器应用
- 清除拆分 DNS 配置
- 移除 Tailscale 设备
- 销毁 Fly.io 应用
ambit doctor
本地环境和路由器基础设施的健康检查。当出现问题时运行此命令——它会检查最常见的故障点并给出修复提示。
bash
ambit doctor
ambit doctor --network lab
检查项:
- - Tailscale CLI 已安装
- Tailscale 已连接(BackendState = Running)
- 接受路由已启用
- 路由器存在且机器正在运行
- 路由器在 tailnet 中可见
模板
可在 ToxicPine/ambit-templates 获取的即用型部署模板:
| 模板 | 描述 |
|---|
| ToxicPine/ambit-templates/chromatic | 无头 Chrome,在端口 9222 上暴露 Chrome DevTools 协议——适用于需要在私有网络上使用浏览器的 AI 代理或脚本。 |
| ToxicPine/ambit-templates/wetty |
带有 Web 终端、持久化主目录、无密码 sudo 和自动启动/停止的云开发 shell。 |
| ToxicPine/ambit-templates/opencode