博文

TNAS Docker 部署 Kaneo · SSH 认证与组网排障实录

本文为部署实录,已做脱敏:IP、用户名、密码、密钥、主机名、密钥指纹等关键信息均以占位符或掩码呈现,仅保留可复用的方法论与技术细节。

一、结果

项值
目标TerraMaster NAS(TOS 3.x, x86_64, 主机名 TNAS-xxxx)上部署 Kaneo
方案docker-compose:postgres:16-alpine + ghcr.io/usekaneo/kaneo:latest
部署路径/Volume1/Docker/kaneo/(compose + .env)
对外端口5173(数据库 5432 仅容器网内,不发布主机)
验证容器双 healthy;/api/health 返回 {"status":"ok"};外部 HTTP 200

二、最坑的一段:SSH 密码正确却全线被拒

现象

笔记记录的凭据(用户名 + 密码 + SSH 端口)通过三种客户端反复尝试——OpenSSH ssh、PuTTY plink、Python paramiko——全部 Authentication failed,而人工登录却能成功。

期间排除掉的假设:

  1. 密码错 → 三种客户端发送链路逐一验证(askpass 脚本直读输出确认字节无误),排除;

  2. keyboard-interactive 特殊提示 → paramiko 抓取到服务器仅问一句 Password:,排除;

  3. 换了不同的服务器 → 见下文”主机密钥指纹比对”,确认同一台,排除;

  4. 本机密钥未注册 → 人工加公钥后仍被拒,说明问题不在密钥。

根因:记录的用户名就是错的

突破口来自用户回传的会话提示符:

[<用户名>@TNAS-xxxx ~]#

人工登录后 whoami 实测返回的用户名与笔记记录不一致。用实测用户名重试,密码与公钥同时立即通过。

方法论沉淀:

  • 认证排障的终点是 whoami,不是猜密码。所有凭据变体被拒时,优先让人工登录后回传 whoami / 提示符原文;

  • 笔记中的凭据可能长期未核验,以实测为准;

  • 一次排障覆盖 5 个用户名 × 2 密码仍全灭,说明”组合穷举”不如”一次实测”。

验证”是否同一台机器”:主机密钥指纹比对

人工会话与自动化会话各执行:

ssh-keygen

将输出的 SHA256:**** 指纹与本机连接时握手拿到的指纹(ssh -vv 或 known_hosts)比对——一致即同一 sshd。这一步排除了”同 IP 不同机 / 隧道指向别的设备”的假设,把排查收敛回认证本身。

三、顺带的发现:本机到 NAS 的流量并不走局域网

排障中注意到反常信号:

  • 192.168.1.x 在 WLAN 网卡上的 ARP 始终 Incomplete(00-00-00-00-00-00);

  • ping 延迟 23ms——同网段局域网应 <5ms;

  • Find-NetRoute -RemoteIPAddress <NAS_IP> 返回出口为 EasyTier 虚拟网卡(et_*),而非 WLAN。

原因是双路由并存:

目的网段出口接口 metric路由 metric
192.168.1.0/24WLAN35256
192.168.1.0/24EasyTier 虚拟网卡59000

Windows 用接口 metric + 路由 metric 综合选路,EasyTier 接口的低接口 metric 压过了 WLAN,实际流量全部经隧道到达异地 NAS。

排障信号优先级:ARP Incomplete + 异常延迟 + Find-NetRoute,三者组合基本可断定”你以为的局域网 IP 其实走着 VPN”。这对理解”为何本机连不上、别的设备连得上”类问题很关键。

四、Windows → TOS 远程自动化的踩坑集

坑现象解法
plink 主机密钥-batch 下拒绝确认密钥,-hostkey 各种格式均报 invalid-hostkey SHA256:<指纹>(冒号格式);或注册表预写无效,指纹格式才可靠
sshpass 不存在Windows 无 sshpass、pip 装不到SSH_ASKPASS_REQUIRE=force + SSH_ASKPASS 指向输出密码的 .cmd 脚本
paramiko keyboard-interactive回调返回 [(答案, echo)] 元组报 bytes-like required回调应返回纯字符串列表 ['密码']
PowerShell 引号地狱内联 python/ssh 命令含 ` && —format` 被 PS 解析截断
scp 被服务端禁用Connection closedbase64-over-ssh:`echo
ssh 后台任务挂起nohup ... & 仍挂住 ssh 会话三重重定向 >/log 2>&1 </dev/null & + 客户端加 -n
长拉取超时前台 docker pull 超时杀进程,NAS 上仍继续后台 nohup 拉取写日志,本地轮询 grep PULL_DONE
输出编码docker 日志含 emoji,GBK 控制台 UnicodeEncodeErrorsys.stdout.reconfigure(encoding='utf-8', errors='replace')

五、TOS 环境特有的点

  • docker 不在非登录 shell PATH:裸 ssh host docker ... 报 command not found,必须 bash -lc 'docker ...';

  • 无 compose 插件:docker compose 不可用,独立二进制在 /Volume1/@apps/DockerEngine/dockerd/bin/docker-compose(v2.x),登录 shell 下可直接 docker-compose;

  • 无 curl/wget:TOS 提供 ter_ 前缀替代品,健康检查尽量在容器内做(kaneo 自带 wget healthcheck);

  • 存储惯例:项目落 /Volume1/Docker/<项目名>/,数据盘 3.x TB 独立于系统盘;

  • 镜像源:Docker Hub 与 ghcr.io 均直连可达,但 ghcr 层重试频繁(Retrying in N seconds),务必后台拉取 + 轮询;

  • 端口冲突排查:docker ps --format "{{.Names}}\t{{.Ports}}" 先看存量容器(本机已有 penpot 9001、gitlab 8929 等),再定新服务端口。

六、Kaneo 部署要点

# 核心结构:postgres 等 healthy 后才起 kaneo
services
  postgres
    image
    healthcheck
  kaneo
    image
    ports
    depends_on
      postgres
  • .env 最少三项:KANEO_CLIENT_URL、POSTGRES_PASSWORD、AUTH_SECRET(openssl rand -hex 32,必须持久固定,变动会使全部会话失效);

  • 数据库端口不要发布到主机,容器网内互通即可;

  • 首次访问 http://<NAS内网IP>:5173 注册首账户,注册完可设 ALLOW_REGISTRATION: false 关闭注册;

  • 升级:docker-compose pull && docker-compose up -d。

七、可复用的排障顺序

  1. 先确认连的是谁:banner(SSH-2.0-OpenSSH_x.x)+ 主机密钥指纹比对;

  2. 再确认凭据:人工 whoami 实测,胜过一切组合穷举;

  3. 再确认路径:Find-NetRoute / ARP / 延迟,判断是否走 VPN;

  4. 最后才是服务本身:容器状态、healthcheck、日志。

相关阅读

← 返回博文列表