“写笔记”支持四种格式——Word 文档、Excel 表格、Markdown、纯文本,起稿或二次编辑时都能随时切换,同一篇笔记想用哪种形态来记,都由你说了算。
md、txt、csv、json 这类纯文本则原样载入,不做多余加工。拿一张现成的表倒进来、改几笔、再导出去,等于白用一台免费的格式转换器。
要带走就在右上角点“下载”,可导出 PDF、Word、Markdown、Excel、TXT 等格式;列表卡片“⋯”菜单里,也有同样的下载入口。
在“工具”页点“+ 上传工具”即可发布:填好名称与链接,再用 Markdown 把使用方法写清楚——能解决什么问题、怎么装、怎么用,比堆介绍实在。
要分发安装包就一并上传压缩包(ZIP、RAR、7Z、TAR.GZ,最大 35MB),别人在详情页一键下载;只放链接不带附件也可以。
工具按大家的收藏热度排序,好用的自然会被顶上来。发布后可在详情页或卡片菜单里编辑、下架。
写笔记时勾上“隐藏”,这篇就只存在于你自己的账号里:不进列表、不进搜索、不上首页精选,也不会出现在任何公开的页面,链接发给别人同样打不开。
适合放密码、草稿、日记这类只给自己看的内容;想公开,去“发布”打开它,把“隐藏”的勾去掉再保存,之后编辑会默认保持原状态,不会悄悄变回公开。
你的内容会同时保存在多个副本上,系统定期做备份与完整性校验,再配合异地容灾机制:就算某台机器出问题,数据也不会丢,可以长期放心存放;特别重要的资料,仍建议你另外再留一份备份。
全站跑在容器化、模块化的现代架构上,更新、部署、回滚都很快,扩展性和稳定性都按长期运营的标准来设计(Built for reliability, designed to scale)。
这个网站最早只是一个人的笔记仓库,后来慢慢长成现在的知识中枢。设计上很克制——没有广告、没有追踪、没有推荐算法,只是干干净净地存放一些东西;既然做好了,就公开出来,万一有人用得上呢。
不做大而全,不做平台梦,保持简单、保持克制、保持好奇。所有内容都由用户贡献、由用户维护:不会突然冒出付费墙,不会在角落塞广告位,也不会把你的数据卖给第三方。
产品会持续迭代,站内日志页记录着每一次改动,改了什么都有迹可循;想了解这个站是怎么一步步走到今天的,翻翻日志就能看到来龙去脉。
如果在这里看到涉嫌违规的内容,点对应卡片右侧的“举报”按钮就能提交,我们会尽快核实处理;也谢谢你花一点时间,一起把这里维护干净。
PaaS里你用得最多的部分,权限应该最小——所以我造了Mooring
写在前面
我笔记本上有个文件夹叫 side-projects,里面躺着十几个 Docker 化的项目。大部分这辈子都不会有超过两位数用户。但过去几年,每个项目都会撞上同一堵墙:怎么把它搞到一台便宜的 VPS 上,又不搭进去一整个周末?而且每次都是复制粘贴自己以前踩过的坑,一遍又一遍。
这让我慢慢形成了一个观点,后来干脆变成了一个项目:一个 PaaS 里你摸得最频繁的那部分,应该对你的服务器拥有最小的权限。
想一下一个部署工具,它其实有两个层面。一个是读平面——仪表盘、日志、容器健康状态,就是你整天盯着看的东西。这部分是你暴露面最大的地方,你 95% 的时间都花在这上面。另一个是写平面——部署、重启,真正会改变系统状态的操作。这类操作很少发生,但应该被严格管控。
让我不爽的是,我整天盯着看的东西,和那个能把我服务器重写一遍的东西,居然坐在同一堆权限上。所以我造了 Mooring,把这两个平面彻底分开。
这是个早期 solo 项目,这篇帖子就是拿出来亮个相,希望大家帮忙瞅瞅。
核心思路
整个流程,从头到尾:
- 把它装成一个非 root 的 systemd 服务
- 连上一个 git 仓库
- 写一个
mooring.yaml - 点一下 Deploy
就这么简单。下面说的全是底下怎么实现的。
它到底是什么
Mooring 是一个小型、安全优先、自托管的 Docker 控制面板——你可以把它理解成一个微型 PaaS。你给它一个 git 仓库,描述一下你的应用,它就在你自己的服务器上部署并运行容器。
这个领域已经有 Coolify、Dokku、CapRover、Kamal 这些工具,它们都做得很好。我关心的不同点在于底层的安全姿态。
Mooring 的形态:
- 单个静态 Go 二进制文件,CGO-free,没有外部依赖
- 以非特权 systemd 服务运行,不是 root
- 状态存在 SQLite 里(用的纯 Go 的 modernc 驱动)
- 所有静态资源用
go:embed打包,所以服务器上不需要 node_modules、不需要 asset pipeline、不需要构建任何东西
说实话,看看现有的自托管 PaaS 工具,它们普遍需要对你机器和 Docker 守护进程有广泛的访问权限。而对 Docker socket 的读写访问,在实际意义上就等于宿主机的 root 权限。我自己的 VPS 上放着真正的秘密数据,所以我特别想改变这个交易条件。
读平面永远不持有读写 Docker socket
这是整个项目的核心。
Mooring 的读平面——也就是所有展示容器状态的仪表盘视图——通过一个只读的 docker-socket-proxy 与 Docker 通信。这些视图永远不持有对 socket 的原始读写权限。
而写平面(改变系统状态的那些操作,比如部署、重启)走的是另一条受控路径,而不是混在每次页面加载里。
换句话说,你 95% 时间都在用的那部分界面,拥有最小的权限范围。
这种"假设这台服务器很重要"的思路还衍生出几个设计:
- 管理 Web UI 有严格的 Content-Security-Policy,不允许任何内联 JavaScript
- 认证用 密码 + TOTP 双因素认证,而且改密码、改用户名或改 TOTP 会撤销所有现有会话——靠一个"auth-epoch"指纹实现。这样即使会话被偷了,在凭据变更后它也没法存活
- 受管镜像(比如 socket proxy、edge 等)都是 digest-pinned 的,锁定到具体镜像摘要
- 绑定挂载到容器里的文件,权限设为最小必要权限
- API token 有作用域和 CIDR 限制——只在你指定的网络范围内生效
部署一个 Docker 化应用,不用写 Dockerfile
下面是我一个真实应用(trimmed 过的)的 mooring.yaml:
apiVersion: mooring/v1
kind: App
metadata:
slug: linkstash
spec:
compose:
source: generated # Mooring 生成并管理 compose 文件
services:
api:
build:
language: node # 不用写 Dockerfile——Mooring 生成一个加固版
start: [node, dist/main]
ports: [{ internal: 3000 }]
env:
NODE_ENV: production
MONGODB_URI: { secret: MONGODB_URI } # 这是一个引用——值存在存储里
secrets:
- name: MONGODB_URI
edge:
routes:
- hostname: api.example.com # Mooring 终止 HTTPS 并路由到 api:3000
service: api
port: 3000
有三行值得特别提一下:
source: generated—— Mooring 生成并拥有 compose 文件。你不需要手写。build.language: node—— 你指定语言,Mooring 生成一个加固的 Dockerfile。目前支持 Node、Python、Go、Ruby、PHP、静态站点和通用类型。MONGODB_URI: { secret: MONGODB_URI }—— 这是一个引用,不是值。秘密存在存储里,明文永远不会出现在文件中。
而我最自豪的部分,恰恰是我没写的东西:
- 没有 Dockerfile —— Mooring 生成并管理一个加固版的
- 没有 docker-compose.yml —— Mooring 生成并管理 compose
- 没有反向代理配置 —— 一个受管的 Caddy 自动处理 HTTPS 并续期证书,包括给 MQTT broker 这类服务用的内部证书
- 没有证书重载 sidecar —— 省了
- 文件里没有明文秘密 —— 因为 Mooring 拥有 compose 生成权,那些真正危险的 compose 键——比如
privileged、主机挂载、主机命名空间——在mooring.yaml的 schema 里根本就没语法让你写
自用过程中觉得好用的细节
Mooring 的构建系统最近学会了一件事:根据你提交的 lockfile 自动检测包管理器。
pnpm-lock.yaml→ 用 pnpmyarn.lock→ 用 yarn(包括 Yarn Berry)- 否则 → 用 npm
poetry.lock→ 用 poetryPipfile→ 用 pipenv- 否则 → 用 pip
而且它会从最终镜像中剥离 dev 依赖,只保留生产依赖。
GitOps 模型故意设计得很温和:连上仓库后,Mooring 会自己拉取变更(不需要配置 webhook),但它永远不会自动部署。你需要手动点 Deploy。推送到仓库就自动部署这个功能,是作为显式 opt-in 存在的。
一个仓库可以通过 mooring.yaml + mooring.*.yaml 管理多个应用。
运维层面还有:
- 自动伸缩的边缘负载均衡器
- Mooring 自身状态的加密备份
- 只读的服务器标签页:实时 CPU/内存/磁盘、top 进程、以及一个白名单文件查看器,它会拒绝显示秘密或状态文件
- 可选的 Trivy CVE 扫描:扫描你的应用镜像,但不把 Docker socket 挂载进 Trivy
- 自更新/安全通告检查器:即使正在运行的 Mooring 版本本身是受影响的那个,它也能提醒你
诚实的话
Mooring 还很年轻。一个人写的,目前大概 v0.4.x 左右,最认真的用户就是我自己,在我自己的机器上 dogfooding。我不会假装它已经经过大规模实战考验——因为它确实还没有。
我也不会夸大它的保障:我的主张是读平面不持有读写 socket,以及危险的 compose 键无法表达,而不是说整个系统牢不可破。
但这个核心思路我觉得是对的。我特别希望有人能看看它——尤其是那些跟我一样在意 Docker socket 访问问题的朋友。
如果你在 VPS 上跑 Docker 化的 side-project,而且上面说的任何一点让你有共鸣,我真心期待你的反馈、你的"等等,那 X 怎么办?"、以及你作为早期用户的 bug 报告。
如果你试了,回来告诉我哪里坏了。这就是我发帖的全部原因。