← 返回文章列表

不爽飞牛NSA中vaultwarden版本低,一上午用AI打包了一个

前言:我遇到了什么问题

最近我的 Vaultwarden 突然出问题了:浏览器插件无法验证登录。 可以链接,就是不能使用!!!

查了插件商店留言板才知道,插件升级到 2026.7 版本后,要求服务端不低于 1.37.0网友解读什么情况

而我手里的 NAS 呢?群晖套件是 1.36.0,飞牛应用中心是 1.32.0,全都不达标。等官方更新遥遥无期,我决定自己动手——用 AI 辅助,把官方最新的 1.37.1 打包成飞牛可安装的 fpk 应用。 群晖套件中心版本1.36.0

飞牛应用中心版本1.32.4

下面就是完整过程,全程可在飞牛 NAS 上复现。

准备工作

  • 一台飞牛 fnOS 设备(x86 或 ARM 都可以,本文以 x86 为例)
  • 设备上已安装 docker(用于从官方镜像提取二进制)
  • 设备上已安装打包工具 fnpack(在 https://developer.fnnas.com/docs/cli/fnpack/ 下载,放到 /usr/local/bin
  • 一个能上网的终端(root 权限)

第一步:先读官方打包文档

飞牛的开发者文档讲得很清楚,直接让AI通读这几页:

  • 快速开始:developer.fnnas.com/docs/quick-started/prerequisites/
  • 应用框架(目录结构、生命周期脚本):/docs/core-concepts/framework/
  • Manifest 规范:/docs/core-concepts/manifest/
  • fnpack 使用:/docs/cli/fnpack/

重点记住几个关键点:

  1. fpk 本质是一个 gzip 压缩的 tar 包,里面有一个 app.tgz(你的应用文件)+ manifest(元信息)+ cmd/(生命周期脚本)+ config/(权限和资源)+ wizard/(安装向导)+ 图标;
  2. 生命周期脚本里最核心的是 cmd/main,负责 start / stop / status
  3. 安装时系统会提供 TRIM_APPDESTTRIM_PKGVAR 等环境变量告诉你文件装在哪、数据放哪,不要硬编码路径

第二步:获取 1.37.1 二进制(这里有个大坑)

Vaultwarden 官方仓库(github.com/dani-garcia/vaultwarden)的 1.37.1 release 只发布容器镜像,没有直接的二进制下载。所以我的做法是:从官方 Docker 镜像里把二进制"抠"出来。

# 拉取官方镜像(先试默认版本)
docker pull vaultwarden/server:1.37.1
docker create --name vw vaultwarden/server:1.37.1
docker cp vw:/vaultwarden ./vaultwarden
docker rm vw

试运行一下:./vaultwarden --version——结果报错:

./vaultwarden: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.39' not found

这就是第一个坑:官方默认镜像编译的二进制要求 GLIBC 2.39,而飞牛系统基于 Debian 12,只有 GLIBC 2.36,跑不起来。

解决办法:改用官方 Alpine 变体镜像,它的二进制是静态编译(musl),不依赖系统库,任何 Linux 都能直接运行:

docker pull vaultwarden/server:1.37.1-alpine
docker create --name vw vaultwarden/server:1.37.1-alpine
docker cp vw:/vaultwarden ./vaultwarden
docker cp vw:/web-vault ./web-vault   # 网页版前端资源,也要一起
docker rm vw
chmod +x ./vaultwarden
./vaultwarden --version   # 输出:Vaultwarden 1.37.1 ✓

顺便提醒:如果以后要打 ARM 版,把第一步换成 docker pull --platform linux/arm64 vaultwarden/server:1.37.1-alpine 即可。

第三步:创建应用项目骨架

用 fnpack 生成标准项目结构:

fnpack create vaultwarden

会得到这样的目录:

vaultwarden/
├── app/            # 放你的二进制和 web 资源
├── cmd/            # 生命周期脚本
├── config/         # privilege / resource
├── wizard/         # 安装向导
├── manifest        # 应用元信息
├── ICON.PNG
└── ICON_256.PNG

把上一步提取的二进制和前端资源放进去:

mv ./vaultwarden vaultwarden/app/vaultwarden
mv ./web-vault vaultwarden/app/web-vault

第四步:配置 manifest

编辑 manifest,关键字段如下:

appname               = vaultwarden
version               = 1.37.1
display_name          = Vaultwarden
desc                  = 开源的 Bitwarden 兼容密码管理器服务器
maintainer            = dani-garcia
distributor           = 你自己的名字
distributor_url       = https://你的主页
arch                  = x86_64          # ARM 设备写 arm
platform              = x86             # 飞牛叫法:x86=amd64、arm=aarch64
source                = thirdparty
desktop_uidir         = ui
ctl_stop              = true
service_port          = 8080
checkport             = true

注意:飞牛的架构叫法和平时不一样,x86 = amd64,arm = aarch64

第五步:编写生命周期脚本

cmd/main 是整个应用的控制核心。我的写法是:从配置文件读端口(安装向导收集的),然后启动二进制:

#!/bin/bash
CONFIG_FILE="${TRIM_PKGETC}/config.conf"
PID_FILE="${TRIM_PKGVAR}/app.pid"
LOG_FILE="${TRIM_PKGVAR}/info.log"
BIN="${TRIM_APPDEST}/vaultwarden"

PORT=8080
[ -r "${CONFIG_FILE}" ] && . "${CONFIG_FILE}" && [ -n "${web_port}" ] && PORT="${web_port}"

start_process() {
    CMD="cd '${TRIM_APPDEST}' && ROCKET_ADDRESS=0.0.0.0 ROCKET_PORT='${PORT}' \
DATA_FOLDER='${TRIM_PKGVAR}' WEB_VAULT_FOLDER='${TRIM_APPDEST}/web-vault' '${BIN}'"
    bash -c "${CMD}" >> "${LOG_FILE}" 2>&1 &
    echo $! > "${PID_FILE}"
}

case $1 in
  start) start_process ;;
  stop)  [ -r "${PID_FILE}" ] && kill -TERM $(head -1 "${PID_FILE}"); rm -f "${PID_FILE}" ;;
  status) pgrep -f "${BIN}" >/dev/null && exit 0 || exit 3 ;;
  *) exit 1 ;;
esac

几个要点:

  • 数据必须放 TRIM_PKGVAR(对应 @appdata 目录),这样重启、升级都不会丢;
  • status 返回 0 表示运行中,3 表示未运行(这是飞牛的约定,不能写错);
  • 安装向导收集的端口先由 install_callback 写入 $TRIM_PKGETC/config.conf,启动时再读出来,这样用户在向导里改的端口才有效。

第六步:安装向导 + 入口 + 图标

向导(wizard/install):让用户安装时能选端口:

[
  {
    "stepTitle": "服务配置",
    "items": [
      {
        "type": "text",
        "field": "wizard_port",
        "label": "Web 服务端口",
        "initValue": "8080",
        "rules": [
          { "required": true, "message": "请输入端口号" },
          { "pattern": "^[0-9]+$", "message": "端口只能包含数字" }
        ]
      }
    ]
  }
]

桌面入口(app/ui/config):这里有个坑,我一开始写成 iframe 类型,结果打开被浏览器拒绝。原因有两个:一是桌面是 https,内嵌 http 的 iframe 会被混合内容拦截;二是 Vaultwarden 响应头里带了 frame-ancestors 'self',禁止跨源嵌入。端口服务类应用一律用 type: "url"

{
  ".url": {
    "vaultwarden.Application": {
      "title": "Vaultwarden",
      "icon": "images/icon_{0}.png",
      "type": "url",
      "protocol": "http",
      "port": "${wizard_port}",
      "url": "/",
      "allUsers": true
    }
  }
}

图标:用官方仓库 resources/ 里的 SVG,NAS 上没有 PS 也没有 ImageMagick?装个 librsvg 转一下就行:

apt-get install -y librsvg2-bin
rsvg-convert --background-color='#175DDC' -w 64  -h 64  -o ICON.PNG  vaultwarden-icon-white.svg
rsvg-convert --background-color='#175DDC' -w 256 -h 256 -o ICON_256.PNG vaultwarden-icon-white.svg

第七步:打包

cd vaultwarden
fnpack build

生成 vaultwarden.fpk,搞定。

第八步:安装实测

把 fpk 传到飞牛上,用命令行安装(-v 是存储卷索引,从 1 开始;-e 是向导字段,可以预先提供端口):

echo "wizard_port=8080" > /tmp/install.env
appcenter-cli install-fpk vaultwarden.fpk -v 1 -e /tmp/install.env
appcenter-cli start vaultwarden
appcenter-cli status vaultwarden   # 输出 running

验证几个点:

curl http://127.0.0.1:8080/        # 返回 Vaultwarden Web 页面
curl http://127.0.0.1:8080/alive   # 健康检查 OK

再试试改端口:在应用中心设置里把端口改成 8081,确认服务自动重启并监听新端口。全通过,就可以放心用了。

总结:这次踩的坑

表现解法
默认镜像二进制要 GLIBC 2.39version 'GLIBC_2.39' not found改用 -alpine 变体(静态 musl)
桌面入口被拒打开报"拒绝访问"typeurl,别用 iframe
安装后列表里看不到应用应用中心找不到已启用的应用别绕过应用中心手动启停,用 appcenter-cli stop/start 正规流程
改 manifest 展示信息不变发布者/描述还是旧的应用中心的展示信息在系统数据库里,不只是 manifest 文件

结尾

2FA不用再掏手机了

整个过程,从查文档、踩坑、打包到实测,我基本都是靠 AI完成的——把飞牛官方文档丢给它,让它按规范生成清单和脚本,遇到报错直接把错误贴给它分析。以前这种"差一点点就能用"的事情,可能要折腾一晚上,现在一个上午就能交付。

如果你也在飞牛/群晖上跑 Vaultwarden,遇到了插件无法验证的问题,直接照着这篇把服务端升到 1.37.x 就行。需要 ARM 版安装包、或者想让我把某个应用也打包成 fpk 的,评论区留言,我尽量帮大家安排。