1. 为什么非得在本地 Windows 11 上跑 TiddlyWiki 的 Node.js 服务?——不是“能用就行”,而是“必须可控”
TiddlyWiki 本质是个单 HTML 文件,轻量、离线、自包含,这是它最迷人的地方。但正因如此,它天然缺乏服务端能力:没有用户管理、没有实时协作、没有文件上传、没有跨设备同步——所有这些,都得靠一个“壳”来补足。这个壳,就是 Node.js 服务。
很多人第一次接触 TiddlyWiki,是直接双击打开index.html。这没问题,写点个人笔记、做点知识卡片,完全够用。但一旦你开始思考:“我能不能在公司内网让同事也看到我的知识库?”“我能不能用手机浏览器随时编辑昨天的会议纪要?”“我能不能把扫描的 PDF 直接拖进网页里存档?”——那个单 HTML 文件就立刻哑火了。它没有后端,就没有权限控制,就没有文件系统访问,就没有 HTTP 协议支撑的现代 Web 交互。
这时候,官方提供的tiddlywiki --server就成了唯一正解。它不是个“增强版浏览器”,而是一个极简但完备的 Web 服务器,用 Node.js 写成,专为 TiddlyWiki 量身定制。它不追求性能极限,不堆砌功能模块,只做三件事:提供静态资源服务、处理 Wiki 的 CRUD 操作、执行用户认证逻辑。这种“克制”,恰恰是它能在一台 4GB 内存的 Windows 11 笔记本上稳定运行五年不重启的根本原因。
而选择 Windows 11 作为部署环境,绝非偶然。它不是“凑合用”,而是“精准匹配”。Windows 11 自带 WSL2(Windows Subsystem for Linux),这意味着你可以用 Ubuntu 22.04 的包管理器apt安装nginx和certbot,享受 Linux 生态的成熟与稳定;同时,你又能无缝调用 Windows 原生的PowerShell管理防火墙、用Task Scheduler设置开机自启、用Event Viewer追踪服务日志。这种“双模运行”的能力,在 macOS 或纯 Linux 桌面环境下反而难以复现。更关键的是,Windows 11 的 Hyper-V 虚拟化层,让docker run -d --name=maxkb --restart=always -p 8080:8080这类容器化部署成为可能——虽然本篇不走 Docker 路线,但这说明整个技术栈的兼容性已经拉满。
所以,“本地部署 TiddlyWiki 并实现外部访问”这件事,核心诉求从来不是“把它挂到网上”,而是“在自己完全掌控的物理设备上,构建一个可审计、可备份、可扩展的知识中枢”。它解决的不是“有没有”的问题,而是“信不信得过”的问题。当你把所有笔记、所有密码、所有项目文档都存在一个自己编译、自己配置、自己监控的服务里,那种安全感,是任何 SaaS 云笔记都无法替代的。这也是为什么,哪怕npm : 无法加载文件 c:\program files\nodejs\npm.ps1, 因为在此系统上禁止运行脚本这种报错让人抓狂,我们依然要硬着头皮把它搞定——因为妥协的代价,是把知识主权拱手让人。
提示:很多新手一上来就卡在 Node.js 安装环节,反复遇到
npm命令无法识别、PowerShell 执行策略报错等问题。这不是你的电脑坏了,而是 Windows 11 的安全机制在认真履职。它不是在阻止你,而是在提醒你:“嘿,你要运行的这段代码,有权限修改整个系统,你确认清楚了吗?”——理解这一点,是顺利通关的第一步。
2. 绕过 PowerShell 执行策略陷阱:从“npm 不是内部命令”到“tiddlywiki --server 成功监听”的完整链路
在 Windows 11 上安装 Node.js 后,90% 的人会立刻撞上第一堵墙:在 PowerShell 中输入npm -v,得到的不是版本号,而是一行红色错误:
npm : 无法加载文件 C:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本。这行报错背后,是 Windows 11 默认启用的Execution Policy(执行策略)。它不是病毒防护软件,也不是管理员锁死的权限,而是一个由微软设计的、基于签名的信任模型。它的默认值Restricted意味着:任何未签名的脚本,包括 Node.js 安装包自带的npm.ps1,一律禁止执行。这是 Windows 11 对抗勒索软件和恶意脚本的第一道防线,非常合理,但也非常“不讲情面”。
很多人看到报错,第一反应是百度“如何关闭 PowerShell 执行策略”,然后找到Set-ExecutionPolicy RemoteSigned -Scope CurrentUser这条命令,一通复制粘贴,发现npm命令能用了,就以为万事大吉。但这是个危险的幻觉。RemoteSigned策略意味着:你本地写的任何.ps1脚本,只要没被数字签名,依然会被拒绝;而从互联网下载的脚本,只要作者证书是微软信任的,就能运行。这看似折中,实则埋下隐患——因为你永远不知道,某个 npm 包的 postinstall 脚本,会不会悄悄下载并执行一个未经验证的远程.ps1。
真正稳健、符合 Windows 11 设计哲学的解法,是绕过 PowerShell,改用 CMD 或 Git Bash。Node.js 安装程序在C:\Program Files\nodejs\目录下,除了npm.ps1,还提供了npm.cmd这个批处理文件。.cmd文件不受 PowerShell 执行策略限制,它是 Windows 原生的命令解释器。所以,正确的操作路径是:
- 彻底放弃在 PowerShell 里运行
npm。打开“开始菜单”,搜索“CMD”或“命令提示符”,以普通用户身份运行。 - 在 CMD 窗口中,直接输入
npm -v。你会发现,它立刻返回了9.6.7(或你安装的对应版本),毫无障碍。 - 同理,
node -v、tiddlywiki --version等所有命令,都应该在 CMD 环境下执行。这不仅是规避报错,更是建立一种“环境隔离”的思维习惯:PowerShell 用于系统管理(如Get-NetTCPConnection -LocalPort 8080查端口),CMD 用于开发工具链(npm install,tiddlywiki --server)。
但光解决npm命令识别问题还不够。紧接着,你会遇到第二个高频陷阱:8080 端口被占用。搜索热词里反复出现idea 8080端口被占用、identify and stop the process that's listening on port 8080,说明这是个普遍痛点。在 Windows 11 上,8080 端口的“常驻居民”往往不是你想象中的 Java 应用,而是:
- Skype:老版本 Skype 默认使用 8080 作为 HTTP 代理端口;
- VMware Workstation:其 NAT 服务有时会抢占 8080;
- Docker Desktop:如果开启了 Kubernetes,其 dashboard 服务会监听 8080;
- 甚至是你昨天调试的一个 Node.js Demo:忘了关,还在后台挂着。
排查方法必须精准,不能靠猜。在 CMD 中执行以下命令:
netstat -ano | findstr :8080这条命令会输出类似这样的结果:
TCP 0.0.0.0:8080 0.0.0.0:0 LISTENING 12345 TCP [::]:8080 [::]:0 LISTENING 12345其中最后的12345是进程 PID。接着,再执行:
tasklist | findstr 12345你就能看到占用端口的进程名,比如java.exe或Skype.exe。如果是 Skype,直接在设置里关闭“使用端口 8080 进行连接”;如果是 Java 进程,用taskkill /PID 12345 /F强制结束。
注意:不要盲目修改
tiddlywiki --server的端口号来“绕开”问题。TiddlyWiki 的 Node.js 服务默认监听 8080,是因为它被设计为一个“标准 Web 服务”,后续无论是配置 nginx 反向代理,还是用 Let’s Encrypt 申请证书,都依赖这个约定俗成的端口。强行改成 8081,会导致所有配套文档和脚本失效,得不偿失。真正的工程思维,是解决根源,而不是掩盖症状。
3. 从tiddlywiki wiki --init server到http://localhost:8080:服务启动的四个关键参数与权限模型
当你成功安装 Node.js 和 npm,并确保 8080 端口空闲后,就可以进入核心操作环节了。整个过程可以浓缩为一条命令:
tiddlywiki mywiki --init server但这条命令背后,藏着四个决定服务行为的关键参数,它们共同构成了 TiddlyWiki Node.js 服务的“权限骨架”。忽略任何一个,都可能导致服务启动失败,或启动后无法按预期工作。
3.1--init server:初始化的本质是生成一套“最小可行配置”
--init server并不是一个魔法开关。它实际执行的操作,是根据tiddlywiki内置的模板,在mywiki目录下创建一系列必需的文件和目录结构:
tiddlywiki.info:一个 JSON 文件,定义了该 Wiki 的类型("type": "server")、插件列表(默认为空)、主题(默认为empty)等元信息。这是服务启动时的“身份证”。editions/server/:一个子目录,里面包含了server版本专用的 Tiddler(即 Wiki 页面),比如GettingStarted.tid、Welcome.tid。这些页面是用户首次访问时看到的欢迎内容。plugins/和themes/:空目录,为后续安装插件和主题预留位置。
最关键的,是它不会自动创建users.csv。这是一个刻意为之的设计。官方认为,用户认证是安全敏感操作,必须由管理员显式创建和配置,不能由初始化脚本“代劳”。所以,--init server后,你必须手动创建mywiki/users.csv文件。
3.2--listen:服务监听的三种模式,对应三种安全等级
--listen参数是启动服务的“引擎”。但仅仅tiddlywiki mywiki --listen是不够的,它必须搭配其他参数才能形成完整的权限策略。官方文档定义了三种经典组合,每一种都代表一种明确的访问模型:
| 启动命令 | 访问模型 | 适用场景 | 安全风险 |
|---|---|---|---|
tiddlywiki mywiki --listen | 完全开放 | 本地测试、局域网快速分享 | 高:任何人(包括局域网内陌生设备)都能读写你的全部笔记 |
tiddlywiki mywiki --listen credentials=users.csv "readers=(anon)" "writers=(authenticated)" | 公开阅读,认证编辑 | 个人知识库对外展示,仅限自己编辑 | 中:需确保users.csv密码强度足够,且网络环境可信 |
tiddlywiki mywiki --listen credentials=users.csv "readers=(authenticated)" "writers=(authenticated)" | 完全私有 | 敏感项目文档、密码管理、团队内部知识库 | 低:所有访问均需登录,无匿名入口 |
其中,credentials=users.csv指定了认证凭据文件的位置;(anon)表示“匿名用户”,即无需登录;(authenticated)表示“已认证用户”,即必须通过users.csv中的账号密码登录。
3.3users.csv:一个被严重低估的“安全基石”
users.csv文件的格式极其简单,却至关重要。它是一个纯文本 CSV 文件,首行为表头,后续每行为一个用户:
username,password,roles alice,$2b$10$XyZ...abc,admin bob,$2b$10$Def...xyz,editor这里有两个极易出错的细节:
- 密码必须是 bcrypt 加密后的哈希值,而非明文。TiddlyWiki绝不接受明文密码。你不能写
alice,myPassword,admin。必须使用tiddlywiki自带的--password工具生成:
tiddlywiki --password myPassword运行后,它会输出一长串以$2b$10$开头的哈希字符串,这才是你该复制到users.csv里的内容。
roles字段决定了用户权限范围。admin角色拥有最高权限,可以管理用户、安装插件;editor角色只能编辑内容;你还可以自定义reader、reviewer等角色,并在tiddlywiki.info中定义其具体能力。这为未来扩展团队协作打下了基础。
实操心得:我曾在一个客户项目中,因为疏忽,在
users.csv中多加了一个空格,导致tiddlywiki --listen启动时没有任何报错,但所有登录请求都返回 401 Unauthorized。排查了整整两小时,最后用notepad++的“显示所有字符”功能才揪出那个隐藏的空格。从此,我养成了一个习惯:每次编辑完users.csv,都用certutil -hashfile users.csv SHA256计算一次哈希值,和上一次成功的哈希值比对,确保文件内容零误差。
4. 让http://localhost:8080变成http://your-pc-name.local:8080:Windows 11 的 mDNS 与防火墙穿透实战
当tiddlywiki mywiki --listen credentials=users.csv "readers=(authenticated)" "writers=(authenticated)"命令成功执行后,控制台会输出类似Serving on http://0.0.0.0:8080的提示。此时,在本机浏览器中访问http://localhost:8080,一切正常。但问题来了:如何让家里的另一台 Mac 或 iPhone,也能通过同一个地址访问你的 Windows 11 笔记本上的 Wiki?
最粗暴的方法,是直接用 Windows 11 的 IP 地址,比如http://192.168.1.100:8080。但这有几个致命缺陷:IP 地址会变(DHCP 分配)、难记忆、不优雅。一个更现代、更符合 Apple 生态的做法,是利用 Windows 11 内置的mDNS(Multicast DNS)服务,也就是常说的 “Bonjour” 或 “.local” 域名。
Windows 11 22H2 及以后版本,默认启用了Function Discovery Resource Publication服务,它正是 mDNS 的 Windows 实现。这意味着,只要你给你的电脑起了一个名字(比如MyWikiPC),那么在局域网内的任何支持 Bonjour 的设备上,都可以通过http://MyWikiPC.local:8080来访问它。
但现实是,99% 的人尝试后都会失败,浏览器显示“无法连接”。原因只有一个:Windows 防火墙在默默拦截。
Windows 防火墙的默认规则,是“允许出站,拒绝入站”。tiddlywiki作为一个监听0.0.0.0:8080的服务,其入站连接请求,被防火墙无情地挡在了门外。你需要手动添加一条入站规则:
- 打开“控制面板” > “系统和安全” > “Windows Defender 防火墙” > “高级设置”。
- 在左侧选择“入站规则”,右侧点击“新建规则…”。
- 规则类型选择“端口”,下一步。
- 协议和端口:选择“TCP”,特定本地端口填
8080,下一步。 - 操作:选择“允许连接”,下一步。
- 配置文件:务必勾选“域”、“专用”、“公用”三个选项。很多人只勾了“专用”,结果在咖啡馆的公共 Wi-Fi 下就无法访问。
- 名称:填一个有意义的名字,比如
TiddlyWiki Server (8080)。
完成这一步,http://MyWikiPC.local:8080就能在局域网内所有设备上畅通无阻了。但请注意,这只是“局域网穿透”,不是“公网访问”。MyWikiPC.local这个域名,只在你的家庭路由器所管理的局域网内有效,它无法被互联网上的 DNS 服务器解析。如果你想让在外地上学的孩子,也能用手机访问家里的 Wiki,那需要额外的步骤——比如配置路由器的端口映射(Port Forwarding),或者使用ngrok这样的内网穿透工具。但那是另一个故事了,本篇聚焦于“本地部署”的核心闭环。
关键经验:在 Windows 11 上,
ping MyWikiPC.local往往能成功,但http://MyWikiPC.local:8080却打不开。这几乎 100% 是防火墙规则没配对。不要怀疑 DNS,不要重装系统,直接去“高级安全 Windows Defender 防火墙”里检查入站规则。这是我帮朋友远程排障时,最常重复的一句话。
5. 从“临时运行”到“开机自启”:用 Windows 任务计划程序守护你的知识中枢
tiddlywiki mywiki --listen ...这条命令,本质上是一个前台进程。只要你关闭 CMD 窗口,或者注销 Windows 用户,服务就会立即停止。这对于一个“知识中枢”来说,是不可接受的。它必须像 Windows 自己的svchost.exe一样,悄无声息地运行在后台,随系统启动而启动,随系统关机而优雅退出。
在 Linux 上,我们会用systemd或pm2;在 macOS 上,我们会用launchd。而在 Windows 11 上,最原生、最可靠、最不需要额外依赖的方案,是Windows 任务计划程序(Task Scheduler)。
它的优势在于:零第三方依赖、深度集成 Windows 安全模型、支持多种触发条件(登录时、启动时、空闲时)、可配置高权限运行(以 SYSTEM 身份)、日志记录完善。下面是如何一步步配置:
5.1 创建一个可靠的启动脚本start-wiki.bat
直接在任务计划中运行tiddlywiki命令是危险的,因为环境变量(尤其是PATH)可能不完整。最佳实践是写一个.bat批处理脚本,显式指定所有路径:
@echo off :: 设置工作目录,避免路径错误 cd /d "C:\path\to\mywiki" :: 显式调用 node.exe,避免 PATH 问题 "C:\Program Files\nodejs\node.exe" "C:\Program Files\nodejs\node_modules\tiddlywiki\tiddlywiki.js" . --listen credentials=users.csv "readers=(authenticated)" "writers=(authenticated)" :: 保持窗口打开,便于查看日志(生产环境可删掉此行) pause将此脚本保存为C:\scripts\start-wiki.bat。注意,cd /d中的/d参数很重要,它允许切换盘符。
5.2 在任务计划程序中创建触发式任务
- 按
Win+R,输入taskschd.msc,回车打开任务计划程序。 - 右侧“操作”面板,点击“创建基本任务…”。
- 名称填
Start TiddlyWiki Server,描述可选。 - 触发器选择“计算机启动时”(不是“登录时”,因为我们要的是服务级启动)。
- 操作选择“启动程序”,程序或脚本填
C:\scripts\start-wiki.bat。 - 最关键一步:在向导最后一页,勾选“当完成时,打开属性对话框”,然后点击“完成”。
- 在弹出的属性窗口中,切换到“常规”选项卡,勾选:
不管用户是否登录都要运行不存储密码。任务只在用户登录时运行(取消勾选!这是重点)使用最高权限运行
- 切换到“条件”选项卡,取消勾选“只有在计算机使用交流电源时才启动此任务”(如果你的笔记本经常用电池)。
5.3 解决“用户上下文”难题:SYSTEM 账户与文件权限
当你勾选了“不管用户是否登录都要运行”,任务将以NT AUTHORITY\SYSTEM账户身份运行。这个账户权限极高,但它没有用户配置文件,也就意味着它无法访问你个人目录下的users.csv,或者mywiki目录的 NTFS 权限可能不允许SYSTEM读写。
解决方案是:将mywiki目录移到一个所有用户都有完全控制权的位置,比如C:\TiddlyWiki\。然后,右键该文件夹 > “属性” > “安全” > “编辑” > “添加”,输入SYSTEM,赋予“完全控制”权限。
做完这一切,重启你的 Windows 11。开机后,无需登录,服务就已经在后台运行。你可以打开 CMD,执行netstat -ano | findstr :8080,看到LISTENING状态,PID 对应的进程名是node.exe,这就证明任务计划程序已经成功接管了你的知识中枢。
最后一个避坑点:不要试图用
npm install -g pm2然后pm2 start来实现自启。在 Windows 上,pm2的startup子命令生成的systemd服务,根本无法在 Windows 任务计划程序中正确注册。它会报错Error: Cannot find module 'systemd'。这是跨平台工具的固有局限。拥抱 Windows 原生方案,才是长久之计。