# @arthuroabrantes/maestro 中文文档

规范地址：https://npmcn.com/package/%40arthuroabrantes/maestro/

版本：0\.1\.2
npm 元数据更新时间：2026-06-12T20:22:12.881Z
中文译文更新时间：2026-11-08T05:59:47.414Z
软件包许可：未声明

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40arthuroabrantes/maestro
原文对照：https://npmcn.com/package/%40arthuroabrantes/maestro/?lang=original
项目主页：https://github.com/instrutoria/maestro#readme
源码仓库：https://github.com/instrutoria/maestro

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：241 kB，65 个文件
- 模块格式：ES Module
- TypeScript 类型：未声明
- 运行依赖：7 个
- 首次发布：2026-06-12T19:05:33.138Z
- 最新版本发布：2026-06-12T20:22:12.782Z
- 近 30 天下载量：1885（2026-10-07 至 2026-11-05，npm 官方下载统计）
- 已发布版本数：3（近 12 个月 3 个）

## 中文简介

由单一的maestro.yaml(Pulumi + Ansible)提供数字海洋基础设施

## 安装

```sh
npm install @arthuroabrantes/maestro
```

也可以使用：`pnpm add @arthuroabrantes/maestro`、`yarn add @arthuroabrantes/maestro`、`bun add @arthuroabrantes/maestro`

## README

# 大师

Maestro从一个单一的YAML文件中为生产部署一个网络应用程序. 指着一个 `maestro.yaml` 描述您的域名、 服务器和应用程序容器, 它提供云基础设施( DNS、 液滴、 隧道、 管理过的 Postgres) , 并配置服务器( nginx、 Docker、 您的后端) —— 以一个命令结束.

盖子下面是结合的 [普鲁米](https://www.pulumi.com/) 用于云资源及 [可解药](https://www.ansible.com/) 用于服务器配置,所以你不必将两者连接在一起.

一个 `maestro.yaml` 让你:

-   **DNS 和 TLS 数据** —— Cloudflare DNS 记录,区域 TLS 设置,以及您的域名的 Origin CA 证书.
-   **服务器** - 数字海洋液滴/环境(`dev` 编号 : `staging` 编号 : `prod`),每个环境在自己的子域上完全隔离.
-   **私人 SSH 访问** ——通过Cloudflare Zero Trust隧道到达服务器(`ssh0.example.com`),从未通过生IP.
-   **网络级别** —— nginx服务于您的静态网站或倒置的网络容器.
-   **后端分级** ——您应用的多克图像部署出蓝/绿色,并附有健康检查和可选的部署前数据库迁移,所以部署是零下架时间.
-   **数据库分级( 可选)** – 数字海洋管理 Postgres 集成每条环境,仅能覆盖于一个私有的VPC上,拥有最不优惠的应用用户.

Maestro是一个有CLI的版本npm包. 您的应用程序仓库拥有 `maestro.yaml` (在文件描述的应用代码旁边) 并运行大师反对它—— `bunx @arthuroabrantes/maestro`,或被钉入 `devDependency`升级Maestro是一个版本 在您的Repo; 没有关于您的应用 住在Maestro的仓库.

* * *

## 使用大师

### 1\. 安装主机要求

大师继续前进 [阿宝](https://bun.sh/) 并管理一些主机工具( 所有工具在启动时都得到验证) :

| 工具 | 用于 |
| --- | --- |
| `docker` | 运行容器化的Ansible执行环境并提取图像源网站资产. |
| `pulumi` | 普鲁米CLI. Maestro通过自动化API在进程中驱动;你从未自己运行过. 州住普鲁米云(无) `pulumi login` 需要 -- -- `PULUMI_ACCESS_TOKEN` 认证). |
| `bws` | Bitwarden Secrets Manager CLI——所有秘密的来源. |
| `cloudflared` | 通过Cloudflare SSH隧道到达服务器. |
| `pip`/Python | 大师自动安装 `ansible-navigator` (和 `ansible-builder`)通过 `pip install --user` 如果他们失踪了 `PATH`。 。 。 . |

### 2\. 设置账户(一次)

**云浮华.** 基础 `domain` 内 `maestro.yaml` 必须已经存在作为一个 **活动区域** 在您的 Cloudflare 账户中 : 在 Cloudflare 中添加域名, 并在 Cloudflare 指派的域名中标注您的注册员名服务员 。 大师在运行时按名称查看区域并失败 `Cloudflare zone for <domain> not found.` 如果它不见了——它从不创建区或验证所有权.

区域也必须是 **没有相冲突的 DNS 记录**大师创建自己的记录(apex) `A`, (中文(简体) ), `www` `A`,以及 `api`编号 :`ssh*` `CNAME`如果不同类型的记录已经占有其中之一,则Cloudflare以 `A CNAME record with that host already exists` (错误) `81054`),运行部分失效. 删除( 或导入到 Pulumi) 顶端的任何相冲突记录, `www`, (中文(简体) ), `api`,以及 `ssh*` 名字第一个.

**数字海洋.** 添加 SSH **公开** 用于数字海洋账户的密钥。 大师的药水滴 但不为您注册钥匙.

**Bitwarden 机密管理器 .** 在您机器账户可读的 BWS 项目中创建下面的秘密 。 大师在启动时取出它们并注入它自己的环境——它们从未被写入你的Repo.

| 秘诀 | 目的 | 所需范围 |
| --- | --- | --- |
| `VPS_SSH_KEY` | SSH 服务器 **私营** 键匹配在数字海洋注册的公钥. | 非 API 令牌; 不适用范围 . |
| `GHCR_TOKEN` | GitHub Control Register Register 标记用于调取您的应用图像的服务器 . | GitHub 个人访问符( 经典) **`read:packages`**。不需要其他只读拉出. |
| `GHCR_USERNAME` | 拥有的 GitHub 用户名 `GHCR_TOKEN`。 。 。 . | 非 API 令牌; 不适用范围 . |
| `PULUMI_ACCESS_TOKEN` | Pulumi Cloud 访问符 (基础设施状态所在). | 标准个人准入标志;需要进入正在部署的组织/仓库. |
| `CLOUDFLARE_API_TOKEN` | Cloudflare API 代币. | 区 □ **区:读取**, (中文(简体) ), **区设置: 编辑**, (中文(简体) ), **DNS: 编辑**页:1 **SSL 和证书: 编辑** (欧里金 CA 证书—— a) _用户级别_ 权限; 没有权限创建失败 `401 / code 1016`(c) 账户 **云浮隧道: 编辑**. 范围扩大到正在管理的账户/区. |
| `DIGITALOCEAN_ACCESS_TOKEN` | DigitalOcean API 代币. | `droplet:create/read/update/delete`· ; `ssh_key:read`· ; `tag:create/read/delete`。一个完整的读出+写出符号也有效。 启用了数据库层级,另外 `database:create/read/update/delete` 和 VPC 读取/写入. |

启用数据库级( E)`pulumi.database.enabled: true`),还需要两个秘密——您选择的稳定识别符,由Pulumi(创建用户/数据库)和您的后端阅读:

| 秘诀 | 目的 |
| --- | --- |
| `POSTGRES_USER` | 专用最不优惠的应用程序数据库用户名(由普鲁米创建). |
| `POSTGRES_DB` | 应用程序数据库名称(由Pulumi创建). |

> `POSTGRES_HOST`, (中文(简体) ), `POSTGRES_PORT`,以及 `POSTGRES_PASSWORD` 为: **没有** Bitwarden secrets——它们来源于 DigitalOcean,表面为 Pulumi 堆栈输出,并自动注入到您的后端. 永远不要犯法.

### 3\. 写你 `maestro.yaml`

在您的应用程序仓库中创建 `maestro.yaml`。一个最小的完整实例:

```yaml
domain: example.com

pulumi:
  enabled: true
  command: up
  projectName: example
  cloudflareAccountId: "<your-cloudflare-account-id>"
  sshPort: 22
  stacks:
    prod:
      servers:
        - roles: [backend, web]

ansible:
  enabled: true
  web:
    static:
      source: local
      dir: ./website # relative paths resolve against this file's directory
      dist: dist
  backend:
    image: ghcr.io/your-org/your-app
    tag: latest
    port: 3000

secrets:
  provider: bws
```

见 [`example.maestro.yaml`](https://npmcn.com/package/%40arthuroabrantes/maestro/example.maestro.yaml) 用于包含每个选项的完整文件模板,以及 [配置参考](https://npmcn.com/package/%40arthuroabrantes/maestro/#readme-configuration-reference) 见下文.

### 运行它

```bash
export BWS_ACCESS_TOKEN="your_bws_machine_account_token"

bunx @arthuroabrantes/maestro --dry-run   # validate the config and preview settings
bunx @arthuroabrantes/maestro             # provision everything
```

`BWS_ACCESS_TOKEN` 是您手动设定的唯一环境变量—— Bitwarden 机账符 **读取** 进入拥有上述机密的项目。 其他一切从比特华登来.

或者,针大师作为一个 `devDependency` 并运行它通过 `bun run maestro`. 一个在合并上运行大师的瘦CI工作流程同样工作——CLI是非交互的.

### CLI 参考

```
maestro [--config <path>] [--dry-run]
```

| 旗帜 | 目的 |
| --- | --- |
| `--config <path>` | 路径 `maestro.yaml`默认 : `./maestro.yaml` 在当前工作目录中. |
| `--dry-run` | 验证配置并显示解析的设置, 不提供任何条件 . |
| `--help` | 显示用法 . |

配置内部的相对路径( 如 . `ansible.web.static.dir: ./website`总是决心反对 **配置文件目录**,而不是引用目录的maestro 从,所以同样的配置在本地,在CI,并通过 `--config` 从任何地方.

* * *

## 配置参考

所有配置都生活在一个YAML文件中. 整个结构:

```yaml
domain: example.com # Base domain for DNS and nginx

pulumi:
  enabled: true # Enable/disable cloud provisioning
  command: up # up | refresh | cancel | output | destroy (destroy skips Ansible)
  projectName: your-project-name # Pulumi project name
  cloudflareAccountId: "" # Your Cloudflare account ID
  sshPort: 22 # SSH port for tunnels
  database: # Optional: Managed Postgres tier (global defaults)
    enabled: false # Provision a DigitalOcean Managed Postgres cluster per stack
    version: "16" # Postgres major version: "15", "16", or "17"
    size: db-s-1vcpu-1gb # DigitalOcean DB node size
    nodeCount: 1 # Node count (region always co-locates with the stack's droplets)
  stacks: # One or more environments: dev, staging, prod
    prod:
      servers:
        - roles: [backend, web] # Roles determine what gets provisioned/configured
          # groups: [devops]    # Optional: override global ansible.groups
          # size: s-1vcpu-1gb   # Optional: DigitalOcean droplet size
          # region: nyc1        # Optional: DigitalOcean region
      # database:               # Optional: per-stack sizing override (override wins)
      #   size: db-s-2vcpu-4gb

ansible:
  enabled: true # Enable/disable all server configuration
  groups: [devops] # System groups (can be overridden per-server)
  web: # Required if any server has the "web" role
    static: # ...serve static files with nginx, or:
      source: local # local | image
      dir: ./website # Website source (relative to this config file)
      build: bun run build # Optional build command
      dist: dist # Subdirectory with built assets
    # docker:               # ...or reverse-proxy a web container
    #   image: ghcr.io/org/web
    #   tag: latest
    #   port: 3000
  backend: # Required if any server has the "backend" role
    image: ghcr.io/org/app # Container image
    tag: latest # Image tag
    port: 3000 # Backend port
    env: # Non-sensitive environment variables for the container
      SOME_VAR: value
    secretEnv: # Sensitive vars: names of Bitwarden secrets, values injected at runtime
      - STRIPE_SECRET_KEY # container var STRIPE_SECRET_KEY ← BWS secret of the same name
      - BWS_ACCESS_TOKEN: APP_BWS_ACCESS_TOKEN # rename on inject: container var ← BWS secret
    migrate: # Optional: DB migration before each deploy (omit = none)
      command: ["npm", "run", "migrate"] # argv run inside the backend image
    healthCheck: # Optional: blue/green readiness probe
      path: /health # Polled for 200 before cutover (default: /health)

secrets:
  provider: bws # Secrets provider (bws = Bitwarden Secrets Manager)
  projectId: "" # Optional BWS project ID to scope the fetch
  requiredVars: [] # Extra secrets to validate and forward to Ansible
```

### 服务器角色

供给是 **基于角色**:每个 Ansible 游戏本只运行在持有相应角色的服务器上,并且在没有服务器时完全跳过.

| 作用 | 游戏本 | 目的 |
| --- | --- | --- |
| `backend` | `backend.yml` | Docker + 后端容器部署 |
| `web` | `web.yml` | nginx( 静态文件或反向代理) |

**加强安全** (单位:千美元)`security.yml`) 总是运行在所有服务器上: UFW 防火墙规则(默认接收次数少,允许SSH,特定角色的开口)和系统组管理(英语:`ansible.groups`) (中文(简体) ).

### 环境(垃圾)

每个堆放在下面 `pulumi.stacks` 是一个孤立的环境,有自己的Pulumi状态、服务器和(可选的)数据库。 Maestro提供每个被定义的堆栈相继,然后为Ansible相位汇总所有主机. 服务器同时被标记为堆栈名和角色,因此游戏本可以根据环境瞄准. 见 [`ansible/README.md`](https://npmcn.com/package/%40arthuroabrantes/maestro/ansible/README.md) 用于主机目标细节.

非生产堆栈活在基部的前缀子域上 `domain`,用于每种资源:

| 资源 | `dev` | `staging` | `prod` |
| --- | --- | --- | --- |
| 网络域 | `dev.example.com` | `staging.example.com` | `example.com` |
| WWW 域名 | `www.dev.example.com` | `www.staging.example.com` | `www.example.com` |
| API 终点 | `api.dev.example.com` | `api.staging.example.com` | `api.example.com` |
| SSH 隧道 | `ssh0.dev.example.com` | `ssh0.staging.example.com` | `ssh0.example.com` |

DNS记录是在基域Cloudflare区下创建的;TLS证书是每个有效域签发的.

### 数据库(管理中的邮政)

何时 `pulumi.database.enabled` 实值 `true`,硕士规定a **数字海洋管理邮政** 分组作为专门的数据库级别。 指导原则: _后端是牛; 数据库是皇冠珠宝_ ——数据库存在于自有管理的故障域中,与可支配后端滴入相分离.

-   **环境相互隔离.** 每个启用的堆栈设置 **拥有** 集群、应用程序数据库和应用程序用户。 A 类 `dev` 部署绝不触及 `prod` 数据库.
-   **私人 VPC 端点 + TLS.** 每个堆栈都得到一个由后端滴入和集群组成的专用VPC. 后端连接到数据库的 **私营** 终点——交通从不穿越公共互联网——仍然使用 `sslmode=require` (单位:千美元) `PGSSLMODE=require` 为libpq客户端服务.
-   **起码的特权.** Pulumi 创建专用数据库用户(来自 `POSTGRES_USER`和数据库(来自 `POSTGRES_DB`) (中文(简体) ). 应用程序从不使用集群管理员( E)`doadmin`) (中文(简体) ).
-   **防火墙通过标签.** A 类 `DatabaseFirewall` 相信后端的小滴 以他们的每桶 **标签**,不是"滴"ID,所以它能活过"滴"重建. 没有 `0.0.0.0/0` 规则.
-   **生命周期保障.** 组装 `retainOnDelete: true` **财务报告和审定财务报表** `protect: true`; 应用程序数据库、用户和 VPC 携带 `retainOnDelete`A级 `pulumi destroy` 可支配后端在离开云数据库及其数据完好无损的情况下成功; 故意撕毁需要故意不保护并移除资源.
-   **杜尔比特.** DigitalOcean的内置日备份外加点入时恢复(PITR)覆盖耐久性——PITR防止操作员/应用程序出错(不良迁移,意外) `DELETE`不仅仅是基础设施的损失.

> **一次性地更换水滴.** VPC成员在一款"数字海洋"(DigitalOcean droplet)上是不可改变的,因此允许数据库在首次应用时替换了已存在的后端droplet. 后端为牛;Ansible重接替换.

**连接线.** `POSTGRES_USER`编号 :`POSTGRES_DB` 来源于 Bitwarden(您选择的稳定值); `POSTGRES_HOST`, (中文(简体) ), `POSTGRES_PORT`,以及 `POSTGRES_PASSWORD` 来源于 DigitalOcean并读取已键入的 Pulumi 堆栈输出(密码为 Pulumi 密件)。 Maestro在堆栈后端主机上线程显示每个堆栈的值,因此多堆部署从不交叉连接一个堆栈后端到另一个堆栈的数据库. 后端容器最后会 `POSTGRES_HOST`, (中文(简体) ), `POSTGRES_PORT`, (中文(简体) ), `POSTGRES_USER`, (中文(简体) ), `POSTGRES_DB`, (中文(简体) ), `POSTGRES_PASSWORD`,以及 `POSTGRES_SSLMODE=require` 在环境.

### 零下限后端部署迁移( M)

后端部署为 **零关闭时间** 默认情况下:nginx作为稳定的倒置代理保持上行,而Maestro将容器取而代之的是蓝色/绿色.

后端作为两个集装箱之一运行—— `backend-blue` 联 合 国 `ansible.backend.port`和 `backend-green` 联 合 国 `port + 1`——两者都有义务 `127.0.0.1`。每次部署在闲置的端口启动新图像,而活的端口则继续服务,等待其通过健康检查,在新端口点出nginx并重新装入(`nginx -s reload` (b) 飞行中排水请求)。 直到那时,旧集装箱才停止。 如果新容器永远没有健康,老容器继续服务,部署失败——没有半部署状态.

-   **`ansible.backend.healthCheck.path`** (可选): HTTP 路径为 `200` 在新容器上,在切换前。 默认为 `/health`。重试/超时预算是固定的.
-   **`ansible.backend.migrate.command`** (可选):一个 argv 阵列(例如. `["npm", "run", "migrate"]`,而不是外壳行)在后端图像中运行一次 **在新容器开始前**,基于实时数据库,环境与应用程序相同(包括每集) `POSTGRES_*` 页:1 非零退出在应用容器被触碰前中止部署. 关闭块 跳过迁移。 DB 密码和其他机密都保留在 `no_log`\- 守护的路径,从来没有印刷.

### 转发额外机密

大师从来不在其中存储秘密值 `maestro.yaml` ——此文件意在被版本控制. 通过敏感度和目的地,有三种方式使配置进入系统:

-   **`ansible.backend.env`** ——非敏感的后端-容器变量,作为字形键/值对(例如. `NODE_ENV: production`) (中文(简体) ).
-   **`ansible.backend.secretEnv`** —— 说 **敏感** 后端- 容器变量 。 列出 _名称_ b. 存储在 Bitwarden 中的秘密; 要以不同的名称注入,请使用绘图条目—— `CONTAINER_VAR: BWS_SECRET_NAME` (例如:. `BWS_ACCESS_TOKEN: APP_BWS_ACCESS_TOKEN` 手持应用程序在一个不相冲突的 Bitwarden 名下存储的令牌。 启动时验证源代码密钥( 一个缺失的秘密在任何云调时前失败运行), 值运行相同 `no_log`\- 守护路径作为数据库密码 - 它们永远不会被写入您的 repo 或打印 。 集装箱 var 可能也不出现在 `env`,以及 `PORT` 保留(自动从 `ansible.backend.port`) (中文(简体) ).
-   **`secrets.requiredVars`** - Ansible公司需要的秘密 _游戏本_ (不是应用容器). 它们在启动时被验证,并被传送到Ansible执行环境,游戏本通过该环境读取 `lookup('env', 'VAR_NAME')`。 。 。 .

> **永远不要向前 `BWS_ACCESS_TOKEN` 给您的应用程序.** Maestro的部署符可以读取所有部署的秘密(Cloudflare, DigitalOcean, Pulumi);一个受损后端容器会继承你的全部基础设施. 大师拒绝它 `secretEnv` _来源_。 如果您的应用程序本身需要 Bitwarden 访问, 请创建一个单独的机器账户符号, 范围为应用程序机密项目, 在 Bitwarden 中以不同的名称存储( 例如 。). `APP_BWS_ACCESS_TOKEN`),并使用映射表将其以所期望的名称交给应用程序: `BWS_ACCESS_TOKEN: APP_BWS_ACCESS_TOKEN`。 。 。 .

* * *

## 如何运作

### 输油管

`index.ts` (单位:千美元) `maestro` bin) 管线管线:

1.  **解析 CLI 旗** 并对照当前工作目录解决配置路径.
2.  **校验 `maestro.yaml`** 对照一个打入的计数器(io-ts codecs外加语义检查:角色/web一致性,区域混合,数据库先决条件,路径存在). `--dry-run` 在此停止并打印解析的设置 .
3.  **获取机密** 从 Bitwarden 保密管理器( R)`bws secret list`)并注入过程环境;要求的秘密在前面被断言,因此在任何云调之前都会发生故障.
4.  **写入 SSH 密钥** 改为 `0600` 临时文件(stable path ——它被插入了普鲁米资源,因此每个运行的随机路径都会在每次部署时将它们抖出).
5.  **运行 Pulumi 每堆** 正在通过 [自动化 API](https://www.pulumi.com/docs/iac/automation-api/)没有Pulumi Docker的形象,也没有炮击到 `pulumi up`下方的类型脚本程序 `pulumi/` 提供 Cloudflare DNS 记录、 区 TLS 设置、 Origin CA 证书、 Zero Trust SSH 隧道、 Digital Ocean 液滴和(可选) VPC + 管理 Postgres 级。 州住普贤云.
6.  **总主机** 从所有堆栈的打出输出——主机名,角色,堆栈标记,以及每个堆栈的数据库端点.
7.  **等待隧道准备** ——民意调查 SSH-over-cloudflailed 直到每个主机接受连接.
8.  **运行解析器** 与主敌: `web.yml`, (中文(简体) ), `backend.yml`,则 `security.yml` 最后(它可能会收紧防火墙规则,从而阻碍早先的剧情).

### Ansible 执行环境

游戏本不运行在你的主人的Ansible上——它们运行在一个集装箱内 **执行环境** (EE) 驱动由 `ansible-navigator`。大师用 `ansible-builder` 从装有货包的船舶的定义(`ansible/execution_environment/`) (中文(简体) ). 已建图像被标记为定义的内容散列,因此之后运行再使用并完全跳过该构建,直到定义发生变化(比如在maestro升级上).

图像是 **应用不可知论** ——所有特定应用程序在运行时到达容器,在图像构建时从不:

-   **网站资产** 编成临时目录(从 `ansible.web.static.dir`,或从容器图像中取出)和卷载只读于 `/opt/website`。 。 。 .
-   **SSH 密钥** 临时文件是卷载只读的 .
-   **配置和秘密** 作为环境变量转发(`--penv`),包括主机列表(`SSH_HOSTS`),这是一个动态目录脚本(`ansible/inventory/hosts.py`)变为Ansible主机,按角色和堆栈分组.

这就是让一个EE图像服务于每一个消耗性应用.

Maestro的安装目录在运行时被作为只读处理:网站中转,EE构建上下文,导航日志,以及秘密文件都活在系统临时目录中(带有 `maestro_` 前缀, `0600` 机密文件, 并清理出口, 加上启动时的 stale 扫描 .

### 软件包布局

| 路径 | 这是什么 |
| --- | --- |
| `index.ts` | CLI 切入点`bin`),上面的输油管. |
| `lib/` | 管弦乐团:配置装入/验证,秘密,普鲁米司机,Ansible司机,隧道准备. |
| `pulumi/` | Pulumi方案(进口入厂):DNS,证书,地道,液滴,VPC,管理Postgres. |
| `ansible/` | 执行环境定义,动态库存,以及用于nginx, Docker,UFW,蓝色/绿色部署的游戏本/角色. |

### 释放

重放大师版是 `version` 突然间 `package.json` 加号 `npm publish` ——EE图像定义,游戏本,普鲁米程序都在包内出行,所以没有第二件文物可以保持同步.

## 发展大师

这个寄存器本身只是另一个消耗性应用 `maestro.yaml` 恰好坐在工具旁边:

```bash
bun index.ts --dry-run   # or: bun run maestro:dry-run
bun index.ts             # full run against the repo's own maestro.yaml
bun test                 # unit tests
```

## 路线图

-   **独立逻辑备份流到数字海洋空间**:除了DO的日常备份+PITR,一个自有的 `pg_dump`\- 系统备份在日程安排上的空间桶,有寿命周期/保留规则和经过测试的恢复钻头——针对账户或提供者一级的问题进行深入的防御,以及便携式副本.
-   **数据库赠款紧缩**: 应用程序用户为非超级用户且从未 `doadmin`,但将其权限范围限定为自身数据库(超越了DigitalOcean的默认值)内仅需要的,是后续.
-   **多云提供者支持**: DigitalOcean是目前唯一的提供商;AWS/GCP/Azure可能跟随.
-   **自动SSH 密钥提供**:今天的公用密钥必须在第一次运行前手动添加到 DigitalOcean.
-   **每个环境有多个网络/后端服务器** 包含负载平衡;今天每个角色映射到每个堆栈的单个服务器.
-   **通过 SDK 可解析**:通过库界面驱动 Ansible ,而不是炮击到 `ansible-navigator` (Pulumi已经运行在进程中).
-   **强化安保后续行动**:避免在主机文件系统中实现SSH密钥,从Pulumi输出中隐藏服务器IP地址.

## 常见问题

### @arthuroabrantes/maestro 是什么？

由单一的maestro\.yaml\(Pulumi \+ Ansible\)提供数字海洋基础设施

### 如何安装 @arthuroabrantes/maestro？

在项目目录运行 npm install @arthuroabrantes/maestro，或使用 pnpm add / yarn add / bun add。它还提供命令行工具 maestro，可以用 npx maestro 直接运行。

### @arthuroabrantes/maestro 支持 TypeScript 吗？

该包的 package\.json 没有声明类型入口。需要类型提示时，可以在 npm 上查找社区维护的 @types/arthuroabrantes\_\_maestro 是否存在。

### @arthuroabrantes/maestro 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @arthuroabrantes/maestro 可以商用吗？

@arthuroabrantes/maestro 使用 未声明 许可。package\.json 没有声明许可证。没有许可证的代码默认保留全部权利，商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括，不构成法律意见，请以许可原文为准。

### @arthuroabrantes/maestro 的下载量有多少？

根据 npm 官方下载统计，@arthuroabrantes/maestro 在 2026/10/07 – 2026/11/05 这 30 天内被下载 1,885 次，日均约 63 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @arthuroabrantes/maestro 还在维护吗？

最新版本 0\.1\.2 发布于 2026/06/13（4 个月前）；至今共发布 3 个版本，其中过去 12 个月发布了 3 个；首次发布于 2026/06/13。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

