# fundeploy **Repository Path**: farfarfun/fundeploy ## Basic Information - **Project Name**: fundeploy - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-26 - **Last Updated**: 2026-10-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # fundeploy 一条命令管本机的开发环境、常驻服务、工具和镜像源。 单个静态二进制,不依赖 Python、Node 或任何运行时,装上就能跑。支持 macOS 与 Linux 的 x86_64 / arm64。 ```bash curl -fsSL https://raw.githubusercontent.com/farfarfun/fundeploy/HEAD/install.sh | sh ``` ## 安装 ### 装机脚本 ```bash curl -fsSL https://raw.githubusercontent.com/farfarfun/fundeploy/HEAD/install.sh | sh ``` 默认装到 `~/.local/bin/fundeploy`。脚本不会去动你的 shell 配置,该加的 PATH 那行它会打出来。 可选参数与环境变量: | 变量 | 作用 | 默认 | | --- | --- | --- | | `FUNDEPLOY_VERSION` / `--version` | 装哪一版 | `latest` | | `FUNDEPLOY_BIN_DIR` / `--bin-dir` | 装到哪儿 | `~/.local/bin` | | `FUNDEPLOY_RELEASE_REPO` | 从哪个仓库的 release 取 | `farfarfun/fundeploy` | | `FUNDEPLOY_RELEASE_SOURCE` | 从 `github` 还是 `gitee` 取 | 先 GitHub,不通换 Gitee | | `FUNDEPLOY_GITHUB_HUB_PROXY_PREFIX` | GitHub 直连不通时的加速前缀 | 空 | ### 国内网络 GitHub 连不上时脚本会自动改用 Gitee 上的镜像,不用额外设置。嫌那一次探测(8 秒) 慢就直接点名: ```bash FUNDEPLOY_RELEASE_SOURCE=gitee \ curl -fsSL https://gitee.com/farfarfun/fundeploy/raw/master/install.sh | sh ``` 连 `raw.githubusercontent.com` 都拿不到脚本本身时,就用上面这个 Gitee 的地址 (Gitee 的 raw 路径要写分支名 `master`,没有 `HEAD` 这种写法)。 镜像由 CI 从 GitHub 整仓同步过去,release 附件一并搬,两边的包字节一致、校验和 是同一份。装完之后 `fundeploy upgrade` 认同一个变量,行为也一样。 ### Homebrew ```bash brew tap farfarfun/packages https://github.com/farfarfun/packages brew trust farfarfun/packages brew install fundeploy ``` `tap` 那行要带 URL:`brew tap a/b` 默认去找 `github.com/a/homebrew-b`,而这个仓库还 兼着 apt 源。`trust` 那行也不能省:Homebrew 6.0 起第三方 tap 默认不可信,不信任的话 装会被拒。两步都只做一次。 GitHub 连不上就把 tap 的 URL 换成 `https://gitee.com/farfarfun/packages`,后面两行 照旧。下包那一步不用管:formula 里每个 `url` 都带了 Gitee `mirror`,brew 自己会回落。 ### APT ```bash curl -fsSL https://farfarfun.github.io/packages/farfarfun.gpg \ | sudo tee /usr/share/keyrings/farfarfun.gpg >/dev/null echo "deb [signed-by=/usr/share/keyrings/farfarfun.gpg] https://farfarfun.github.io/packages/deb stable main" \ | sudo tee /etc/apt/sources.list.d/farfarfun.list sudo apt update && sudo apt install fundeploy ``` 这是 farfarfun 所有项目共用的源,加一次以后别的包也直接 `apt install`,见 [farfarfun/packages](https://github.com/farfarfun/packages)。 apt 这条路没有 Gitee 备份:deb 树是 Actions 部署到 GitHub Pages 的,不在 git 里, 镜像仓库带不走它。`farfarfun.github.io` 连不上就用上面的装机脚本。 ### 直接下二进制 [Releases](https://github.com/farfarfun/fundeploy/releases) 里每个平台一个 `fundeploy-.tar.gz`, 解开把 `fundeploy` 丢进 PATH 即可。同目录下的 `SHA256SUMS` 可以校验。 ### cargo ```bash cargo install fundeploy ``` 要本地有 Rust 工具链,而且是从源码编,比上面几种慢得多。手上已经有工具链的话这条最省事, 否则不建议——用它装工具链反而要求你先有工具链,顺序是反的。 ## 升级与卸载 ```bash fundeploy upgrade # 升到最新版 fundeploy upgrade --check # 只看有没有新版本,什么都不动 fundeploy upgrade --version 0.2.0 # 装指定版本,比当前旧也照做(这是回退的用法) ``` 不管当初是怎么装的,升级都是这一条命令,它会先认出这份二进制归谁管,再走对应的路: | 装法 | `fundeploy upgrade` 做什么 | | --- | --- | | 装机脚本 / 直接下二进制 | 从 Release 下对应平台的 tar.gz,原子替换掉自己 | | Homebrew | 进 tap 仓库 `git pull --ff-only`,再 `brew upgrade /fundeploy` | | APT | `apt-get update` 后 `apt-get install fundeploy`(按需加 sudo) | | cargo | `cargo install fundeploy --force --locked`(从源码编,慢) | 自己管的那条路:换下来的新二进制会先跑一次 `--version` 确认能起来,再原子替换掉自己; 跑不起来就原样不动。 交给包管理器的那几条路,跑完会再问一次它那边现在装着哪一版再下结论——`brew upgrade` 和 `apt install` 在「没有更新可升」时也退出 0,光看退出码会把没升上去当成升成功了。 发版之后这几条渠道要等几分钟(apt 索引和 formula 等 farfarfun/packages 重建,cargo 等 crates.io 发布),所以刚看到 GitHub 上有新版时这边可能还是旧的,过一会儿再试。 `--version` 只有自己管的安装和 cargo 支持:brew 的 tap 里只有一个跟着最新版走的 formula,apt 源也只放最新一版,点了版本会直接报错并给出路,不会假装装上了。 卸载就是删掉那个文件。用 Homebrew / APT 装的交给对应包管理器:`brew uninstall fundeploy`、 `sudo apt remove fundeploy`。 ## 能管什么 ```bash fundeploy # 不带参数:打开菜单(可输入过滤) fundeploy list # 列出所有能管的东西 fundeploy about # 这是什么、谁做的 ``` 输出按「一张卡片说完一件事」排:框宽跟着终端走,窄终端下长路径中间省略而不是把框 撑破;`NO_COLOR=1` 或输出被重定向时自动退回无框的纯文本,不往日志里塞框线和色码。 等端口监听这种最长半分钟的干等会转一个 spinner(进度画在 stderr,不混进重定向的结果)。 ### 服务 `fundeploy service` ```bash fundeploy service # 列出所有服务 fundeploy service status # 所有服务的状态总览(在跑 / 没在跑 / 部分) fundeploy service funread-web install fundeploy service funread-web start fundeploy service funread-web status ``` 每个服务都是这套动作:`install`、`upgrade`、`rollback <版本>`、`start`、`run`(前台)、 `stop`、`restart`、`status`、`uninstall`。 | 服务 | 说明 | | --- | --- | | `funfluid-web` | funfluid 前后端(18806 / 8806) | | `funlesson-web` | funlesson 前后端(18812 / 8814) | | `fungame-web` | fungame 后端 + 管理端 + 用户端(8809 / 8807 / 8808);后端包为 `fungame-api`,前端包为 `@farfarfun/fungame-admin`、`@farfarfun/fungame-web` | | `funflix-web` | funflix 前后端(18810 / 8810) | | `funread-web` | funread 前后端(18811 / 8811) | | `funmill` | funmill 任务执行 API(8813 / 8812) | | `new-api` | new-api 中转网关(8801) | | `code-server` | 浏览器里的 VS Code(8080) | | `sub2api` | sub2api 订阅转 API(8802) | | `airflow` | Apache Airflow standalone(8815) | | `celery` | Celery worker / beat / flower(8816) | | `paperclip` | Paperclip 本机服务(8804) | 服务默认只监听回环地址。要对外暴露就显式设对应的 `*_HOST` / `*_ADDRESS` 环境变量。 多进程的服务(前后端一体的那几个)只提供合并命令:一条 `start` 把该起的都起来, 一条 `stop` 全停掉。换包前会先停服、装完按原状态起回来——在跑着的进程底下换全局包, Node 还开着那棵树里的文件。 `stop` 走完还有人占着端口时,会按端口反查出占用者,问一声再强停(SIGTERM,5 秒不走 上 SIGKILL)。端口不腾出来,紧接着的 `start` 会跳过那个组件,于是 `stop` 和 `start` 都报成功、跑的却还是旧进程——`restart` 卡住多半就是这么来的。 ``` 警告: new-api 的端口 8801 停完还占着,占用者是 PID 2593874(python3) ? 强制停掉它,腾出端口 8801 吗 (Y/n) ``` 回车就是停。没有终端时(cron、CI、输出被重定向)不问直接停,`restart` 因此不会断在 半路;盯着终端但不想每次都按回车的,设 `FUNDEPLOY_STOP_KILL_PORT_YES=1`。 `init` 和 fundeploy 自己这两个 PID 永远不动。 `paperclip` 额外转发官方 CLI 的动作:`install-canary`、`check`、`backup`、`channels`、 `doctor`、`health`、`onboard`、`logs`、`plugin`、`service-install`。 `fundeploy service paperclip install` 和 `fundeploy service paperclip install-canary` 在 新安装时默认从 npm 镜像下载,安装到用户目录; 无需设置环境变量。`upgrade` 跟随安装时选择的通道和实际成功使用的源;镜像失败时会 自动改用官方 npm 源。已有 managed install 继续走原安装路径,避免暗中切换;该模式 可用 `PAPERCLIP_HTTPS_PROXY=http://127.0.0.1:7890` 加速官方源。npm 全局安装不保留 managed payload,因此不支持 `rollback`。 ### 开发工具链 `fundeploy dev` ```bash fundeploy dev # 列出全部的当前状态 fundeploy dev uv install fundeploy dev go upgrade fundeploy dev python status # Python 多版本虚拟环境 ``` 覆盖 `go`、`nodejs`、`pnpm`、`rust`、`uv`,动作是 `status`、`install`、`upgrade`、 `uninstall`。`status` 会把「官方包装在哪儿」和「PATH 上实际用的是哪个」分开列—— 这两者不一致是最常见的「我明明装了」。 `fundeploy dev python` 管的是 `~/opt` 下按版本号分开的 Python 虚拟环境。 ### 换源 `fundeploy source` ```bash fundeploy source # 看全部工具当前配的是哪个源 fundeploy source pip test # 测所有源的延迟 fundeploy source pip use # 不给名字就自动选最快的 fundeploy source pip use tuna fundeploy source pip reset # 恢复官方源 fundeploy source pip add 自己的源 https://... ``` 覆盖 `pip`(pip / uv / poetry / pdm 共用这份配置)、`npm`(pnpm / yarn / bun 共用)、 `brew`(配方 API、bottle 二进制、brew 仓库三处一起换)、`cargo`、`go`。 ### 工具 `fundeploy tool` `brew`(Homebrew 本身)、`cockpit-tools`(AI IDE 账号管理桌面应用)、 `open-pencil`(CLI + MCP 服务器,额外有 `install-desktop`、`mcp-config`)。 ### AI 命令行 `fundeploy ai` ```bash fundeploy ai # 三样的当前状态 fundeploy ai claude install fundeploy ai all upgrade ``` 覆盖 `claude`、`codex`、`cursor`。官方安装器优先,装不上再退到包管理器那条路。 ### 诊断 `fundeploy doctor` ```bash fundeploy doctor github # 网页打得开、git clone 却卡住的那类问题 fundeploy doctor github --fix # 按诊断结果自动挑一条通道改过去 fundeploy doctor github --undo # 撤掉写进 git / ssh 配置里的东西 ``` ### 其它 ```bash fundeploy port-kill 8080 8081 # 查出谁占着端口,停掉它 fundeploy port-kill 8080 --list # 只看不动手 fundeploy skills sync # 同步 Gitee 上的 farfarfun-skills 仓库 ``` ### 网络 查版本、取安装包都要走 GitHub。相关的环境变量: | 变量 | 作用 | | --- | --- | | `FUNDEPLOY_RELEASE_SOURCE` | `github` 或 `gitee`;只管 fundeploy 自己的升级 | | `FUNDEPLOY_GITHUB_HUB_PROXY_PREFIX` | 直连慢或不通时的加速前缀,必须 `https://` | | `GITHUB_TOKEN` / `GH_TOKEN` | 调 GitHub API 时带上 | 匿名调 API 是每小时 60 次、按出口 IP 算,公司网和校园网很容易共用一个出口撞上限, 症状是「查不到最新版本」。`gh auth login` 过的机器通常已经有 `GH_TOKEN` 了。 token 只发往 `api.github.com`——配了加速前缀时不会跟着请求递给那个代理。 `fundeploy upgrade` 默认先试 GitHub,连不上再换 Gitee 镜像,换的时候会出声。 `FUNDEPLOY_RELEASE_SOURCE` 点了名就只用那一个,失败直接报错而不背着你换源。 它只对 fundeploy 自己生效:装别的工具时取的是上游仓库的 release,那些我们没有 镜像,一律直连 GitHub。加速前缀也只往 GitHub 的地址上套,不会拿去绕 Gitee。 ## 开发 ```bash cargo build cargo test cargo fmt --all --check cargo clippy --all-targets -- -D warnings ``` 目录结构: ```text src/ common/ 外部命令、下载、解包、平台探测等公共件 service/ 服务域:spec 声明 + 三族通用生命周期 dev/ 开发工具链 tool/ 非常驻工具 source/ 换源 ai/ AI 命令行 doctor/ 诊断 cli.rs 命令行解析与分发 packaging/ .deb 打包脚本 install.sh 装机脚本 ``` 核心约定是**差异是数据,不是逻辑**:生命周期只写一遍,每个具体的服务/工具退化成一份 声明。加一个 PyPI + npm 的前后端服务通常只需要往 `src/service/registry.rs` 里加十几行。 装不进这套形状的(Paperclip 要直驱上游 CLI)才单独实现 trait。 发布:改 `Cargo.toml` 里的 `version`,提交,推同版本的 tag(`v0.3.1`)。CI 会核对 tag 与版本号、构建四个平台、生成校验和与安装包、发 Release,用装机脚本真装一遍验证,然后 发 crates.io 并通知 [farfarfun/packages](https://github.com/farfarfun/packages) 重建 apt 索引和 Homebrew formula。 ## 详细文档 - [packaging/README.md](packaging/README.md) —— 打包与发布 - [CHANGELOG.md](CHANGELOG.md) --- ## 关于 farfarfun [farfarfun](https://github.com/farfarfun) 是一个专注于实用工具库的开源组织, 涵盖云存储、数据处理、AI、多媒体与开发工具链等方向。 - 🏠 组织主页: - 📧 联系:farfarfun@qq.com 本项目基于 [MIT](LICENSE) 协议开源。