From 0d141eb8a706dd0df42480fc885ab2e3c9143681 Mon Sep 17 00:00:00 2001 From: chenyue Date: Sun, 16 Aug 2026 18:20:33 +0800 Subject: [PATCH] =?UTF-8?q?=E9=80=9A=E8=BF=87workbuddy=E5=AF=B9=E5=86=85?= =?UTF-8?q?=E5=AE=B9=E8=BF=9B=E8=A1=8C=E6=95=B4=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .workbuddy/memory/2026-08-16.md | 127 +++++++ .../如何搭建web版本obsidian.md | 345 +++++++++++++----- 2 files changed, 382 insertions(+), 90 deletions(-) create mode 100644 .workbuddy/memory/2026-08-16.md diff --git a/.workbuddy/memory/2026-08-16.md b/.workbuddy/memory/2026-08-16.md new file mode 100644 index 0000000..eb8e0cd --- /dev/null +++ b/.workbuddy/memory/2026-08-16.md @@ -0,0 +1,127 @@ +# 2026-08-16 + +## Obsidian Web 版部署教程改稿 + +**项目**:`E:\svn\OSQY\如何搭建web版本obsidian` + +**用户需求**:检查初稿部署方案的可行性 + 搜同类竞品文章对照改稿,做成爆款向。 + +**关键发现**: +- 初稿 Caddyfile 里**硬编码了 4 段真实 API 凭证**(阿里云 AccessKey、DNSPod Token、Cloudflare Token),已经提示用户必须去对应云厂商轮换 +- 部署方案 3 个硬伤:reverse_proxy 用了 `localhost:88`(caddy 容器内的 localhost 指向自己)、HTTPS 端口映射成 `8001:443`(公网 443 访问失败)、basic_auth 哈希硬编码(人人密码一样) +- 缺 WS_ORIGINS、缺离线安装(国内服务器首启下载 Obsidian 会被墙)、缺 Caddy 固定镜像来源说明 + +**已交付**: +- `如何搭建web版本obsidian.md` 重写完毕,347 行 +- 新结构:痛点 → 竞品对比 → 准备清单 → 6 步部署 → 踩坑/进阶 → FAQ → 结尾引导 +- 镜像:使用官方 `nobbe/ignis:latest` + `caddy:2`,清华/阿里云镜像用户可自行替换 +- 加了 Tailscale 替代方案(无公网 IP 场景) + +**参考的同类文章**: +- 喵斯基部落 moewah.com(结构最好,参考了它的标题钩子和 FAQ 形式) +- yanh.tech(简洁的 docker-compose 编排) +- 飞牛俱乐部 fnnas.com(早期社区帖) +- jinli.io(VNC 方案对比) +- 官方仓库:Nystik-gh/ignis + +**下次可继续**: +- 用户处理 4 段密钥轮换后,回填一份自己验证过的截图 +- 考虑加一张架构图(docker-compose 启动后的网络拓扑) +- 写 Obsidian Git 自动备份的下篇 + +## 二次改稿(同日 17:42) + +**用户新要求**:1) 默认假定无 80 端口;2) 突出主题、删非必要内容、精简。 + +**改动**: +- 证书改为 **DNS 验证(acme_dns)为主方案**,Caddyfile 全局块直接内置;compose 只映射 `443:443`,去掉 80 +- Caddy 官方 `caddy:2` 镜像不带 DNS 插件 → 增加 `Dockerfile.caddy`(xcaddy 编译 alidns/dnspod/cloudflare 三模块),compose 改 `build:`;Cloudflare 用户可选现成 `caddy-dns/cloudflare` +- 全文 347 → 约 130 行:砍掉 5 方案对比表(压缩成 2 句)、环境变量大表、10 条 FAQ 砍到 3 个核心坑(证书失败/离线安装/无公网 IP) +- 保留:WS_ORIGINS、离线 .deb 安装、Tailscale、备份/升级一行带过 + +**教训**:中国用户服务器常见无 80 端口(运营商封锁),DNS 验证是默认正确姿势;官方 caddy 镜像无 DNS provider 插件是必讲的前提,否则读者直接抄配置会失败。 + +## 三次改稿(同日 17:48) + +**用户提出新问题**:电信家庭网下入站 443 是否也被封? + +**结论**:是。国内家庭宽带默认封入站 80/443,多数用户还没公网 IP(CGNAT)。acme_dns 只能解决证书签发(出站),解决不了外部访问(入站)。 + +**改动(已交付)**:文章主线改为 **frp 内网穿透 + 轻量云服务器**: +- 云服务器(有公网 IP):`snowdreamtech/frps`,host 网络监听 7000 + 443,`frps.toml`(bindPort/auth.token) +- 家里:原 ignis + caddy(acme_dns 证书不变,TLS 终止在家里)+ 新增 `snowdreamtech/frpc` 服务(host 网络,`frpc.toml` 把本地 443 转发到云服务器 443) +- 架构:浏览器 → 云服务器 443 → frp 隧道 → 家里 Caddy 443 → ignis:8080;家里不需要公网 IP 和任何入站端口 +- 备选保留:无云服务器 → 非标端口 8443(acme_dns 不变)或 Tailscale +- 坑新增:安全组放行 7000/443、token 不一致、云服务器 443 被占、家里 443 被占可改 8443 +- 篇幅约 185 行 + +## 四次改稿(同日 17:54):用户假定没有云主机 + +**用户选择**:主线改为**非标端口 8443**(零成本、直连家里、数据不出网;前提:有公网 IP + 8443 未被运营商封)。 + +**改动(已交付)**: +- 删除 frps/frpc 全部内容(云服务器步骤整个移除) +- Caddy 端口映射 `443:443` → `8443:443`;WS_ORIGINS 域名带 `:8443` +- 新增第 1 步「验证前提」:ip.sb 对光猫 WAN 口 IP 判断有无公网 IP(100.64~100.127 为 CGNAT);在线端口扫描测 8443 是否被封 +- 新增第 5 步 DDNS:`jeessy/ddns-go` 容器(host 网络,web 配置 :9876),飞牛用户可用内置 DDNS(阿里云/腾讯云/花生壳/DuckDNS) +- 新增第 6 步:光猫/路由器端口转发 8443 +- 备选(文末):Cloudflare Tunnel(零成本、无需公网 IP、自动 HTTPS、数据过 CF、国内速度一般)、Tailscale(纯自用) +- 坑新增:8443 也被封可换 9443 等、换 IP 后连不上(DDNS 未生效) + +**飞牛相关事实**(搜索确认):飞牛 fnOS 内置 Docker Compose 支持 + 镜像加速(docker.ketches.cn)+ FN Connect(官方穿透,限速,只适合管 fnOS 界面)+ 内置 DDNS(仅阿里云/腾讯云/花生壳/DuckDNS,无 DNSPod/CF)。ignis 镜像注意 x86/ARM 架构。 + +## 五次改稿(同日 18:00):端口 8443 → 666 + +**用户判断**:8443 属于常见端口、部分城市在封锁列表;666 冷门端口大概率不封。 + +**改动(已交付)**:全文所有 8443 替换为 666(标题、架构图、compose 映射 `666:443`、WS_ORIGINS 带 `:666`、端口转发、访问地址、坑/备选标题);被封端口列表恢复为 8080/8443/8888 并加说明"666 冷门端口大概率没事";备选端口 9443 → 6666;新增一条低端口提示(<1024,rootless Docker 需 `sysctl net.ipv4.ip_unprivileged_port_start=0`)。 + +## 六次改稿(同日 18:06):DDNS 并入 Caddy,删除 ddns-go + +**用户需求**:DDNS 能否也用 Caddy 完成,简化部署步骤。 + +**查证结论**:`github.com/mholt/caddy-dynamicdns`(Caddy 作者 Matt Holt 写的 app 模块,2026-08 仍在活跃维护)可完全替代 ddns-go: +- xcaddy 加 `--with github.com/mholt/caddy-dynamicdns` 即可,复用文章已编译的 caddy-dns provider(alidns/dnspod/cloudflare) +- Caddyfile 全局块 `dynamic_dns { provider alidns {...} domains { example.cc ob } versions ipv4 ip_source simple_http https://api.ipify.org }` +- 默认 30 分钟查一次公网 IP,变化时更新 A 记录;dynamic_domains 可自动收集站点域名(本文用显式 domains 更稳) +- 注意:ACME 的 `acme_dns alidns` 是内建指令,与 dynamic_dns 用的 caddy-dns provider 是两套模块体系,Token 会写两遍(可改用 {env.XXX}) + +**改动(已交付)**:Dockerfile.caddy 加 dynamicdns 模块;compose 删 ddns-go 服务(3 容器→2 容器);Caddyfile 全局块加 dynamic_dns;删第 5 步"配置 DDNS",步骤重排为 6 步;常见坑改为查 `docker compose logs caddy | grep -i dynamic_dns`;Cloudflare 现成镜像提示改为"不含 dynamic_dns 模块"的警告。 + +## 七次改稿(同日 18:11):改用现成国内镜像 xm798/caddy:plus + +**用户需求**:caddy-dynamicdns 有没有现成的国内镜像? + +**查证结论**: +- 官方无预编译镜像(dynamic_dns 是 Non-standard 模块,官方只提供 xcaddy 自建) +- **`xm798/caddy:plus`**(国内作者,Docker Hub + 阿里云 `registry.cn-shanghai.aliyuncs.com/xm798/caddy:plus`,README 官方推荐国内直拉):普通版含 alidns/dnspod/cloudflare/tencentcloud,plus 版再加 replace-response + **mholt/caddy-dynamicdns** +- **坑**:Caddy 2.10 后 libdns 升 1.0,dnspod 插件未适配,作者 2025-06 已从最新构建移除 dnspod → 用现成镜像时 DNSPod 不可用,需用腾讯云 tencentcloud 替代(`acme_dns tencentcloud ,`) +- 其他社区镜像(serfriz/caddy-*、vnxme/caddy)只含单 provider,且无国内镜像 + +**改动(已交付,用户选"现成镜像为主、自建作备选")**: +- compose 主线:`build:` → `image: registry.cn-shanghai.aliyuncs.com/xm798/caddy:plus` +- 第 2 步 hash-password 镜像同步改为国内地址(原 `caddy:2` 国内也可能拉不动) +- Caddyfile 注释:DNSPod → 腾讯云(两处:acme_dns + dynamic_dns provider) +- 准备表格 DNS 服务商:阿里云/腾讯云/Cloudflare,DNSPod 用户指到文末自建备选 +- 文末新增「备选:自建 Caddy」(原 Dockerfile.caddy + build: 回退写法 + DNSPod 语法 + `ENV GOPROXY=https://goproxy.cn,direct` 国内编译加速) +- 全文镜像拉取全部走国内地址 + +## 八次改稿(同日 18:14):ignis 也换国内镜像 + +**用户需求**:ignis 也改成国内镜像。 + +**查证**:本机 Docker 27.1.1 实测——Docker Hub 直连 000(连接失败,复现读者痛点);探测 6 个加速站对 `nobbe/ignis` 的 manifest 可用性:`docker.1panel.live` **200 且 tags 完整(0.8.0~0.8.9+latest)**;daocloud/1ms.run 401(无此镜像或需认证)、xuanyuan 429 限流、dockerpull.pw 000 不可达、rat.dev 302。 + +**改动(已交付)**:compose 里 `nobbe/ignis:latest` → `docker.1panel.live/nobbe/ignis:latest`(注释保留原版名);第 9 行项目说明同步;compose 提示区加一条"拉不动时换其他加速站前缀或配加速器后用原版名"。全文镜像现在全部国内直拉(caddy: registry.cn-shanghai.aliyuncs.com/xm798/caddy:plus,ignis: docker.1panel.live/nobbe/ignis:latest)。 + +## 九次改稿(同日 18:17):面向网络传播的整体优化 + +**用户需求**:重新整理全文优化内容和标题,使文章更适合网络传播。 + +**改动(已交付)**:技术内容/命令/配置一字未动,重排结构与文案: +- 标题改为爆款向:「没有官方网页版?30 分钟自建一个 Web 版 Obsidian」+ 收益型副标题(免费/私有/带密码/不用买云服务器/封 80/443 不影响) +- 新增「先看痛点」:出差没带电脑/公司电脑不让装/平板随手记 三场景代入 +- 新增「你能得到什么」表:时间 30 分钟、成本 0 元、2 容器、数据 100% 在家、前提不满足有备选 +- 小标题全部口语化+承诺化:「开工前,备好这 5 样东西」「部署:6 步,30 分钟」「常见坑(先看这里,能省一小时)」「启动!看到登录页就成功了」 +- 结尾改为「写在最后」:评论互动引导(卡住留言补坑)+ 点赞收藏转发 + 下篇预告强化 +- 约 268 行,结构与字数基本持平,传播性增强 diff --git a/如何搭建web版本obsidian/如何搭建web版本obsidian.md b/如何搭建web版本obsidian/如何搭建web版本obsidian.md index 21b25ea..f7268e5 100644 --- a/如何搭建web版本obsidian/如何搭建web版本obsidian.md +++ b/如何搭建web版本obsidian/如何搭建web版本obsidian.md @@ -1,121 +1,286 @@ -# 如何搭建web版本obsidian +# 没有官方网页版?30 分钟自建一个 Web 版 Obsidian -## 背景 +> 免费、私有、带密码,数据全在自己家。不用买云服务器,运营商封了 80/443 也不影响——浏览器打开就能记笔记。 -最近大神开源了一个 ignis 项目,可以通过网页访问 obsidian,但是默认是 http,且无密码,对于公网无法安全使用。 +## 先看痛点:Obsidian 官方一直没做网页版 -下面这个方案完善了安全访问,采用了加密的 https,并且有需要用户名登陆才能访问。 +出差没带电脑、公司电脑不让装软件、想用平板随手记……Obsidian 重度用户绕不开这三件事。 -## 具体步骤 +官方没有网页版,官方同步要付费;过去想远程用 Obsidian,只能 VNC 远程桌面——又重又卡。 -### 申请一个免费的域名,比如 ob.xxxx.cc +好在有 [Ignis](https://github.com/Nystik-gh/ignis):它在浏览器里重新实现了 Obsidian 依赖的 Electron API,让 Obsidian **原生跑在网页里**。vault 留在你自己家里,部署一次长期可用。 -[搞一个免费 10 年的二级域名,公网访问飞牛 NAS](https://mp.weixin.qq.com/s?__biz=MzI2MTA5NzM5MA==&mid=2247499770&idx=1&sn=a5a1a3d78f3d729a45aa44204bb02694&scene=21&poc_token=HJpGeGqjYSRgiB6T6FdBh23s-6Fcjn90eBjF5E-6) +> 本文要用到的两个前提,先记住: +> - **Ignis 没内置认证**,必须自己套一层反向代理加密码(本文用 Caddy) +> - **必须 HTTPS**:剪贴板、离线缓存等 API 只在 HTTPS 下生效,纯 HTTP 公网访问会直接失效 -### 通过反向代理 caddy,通过 https 访问 web 版本 obsidian +## 你能得到什么 -1. 创建 4 个文件目录 +| 项目 | 结果 | +|------|------| +| 时间 | 照做约 30 分钟 | +| 成本 | **0 元**,不需要云服务器 | +| 容器 | 2 个(ignis + Caddy),一个装好、一个转发 | +| 访问 | 任何设备的浏览器:`https://你的域名:666` | +| 数据 | **100% 留在家里**,不经过任何第三方 | +| 前提 | 家里有公网 IP + 666 未被运营商封(不满足也有免费备选,见文末) | - - vaults - - data - - obsidian-app - - caddy-data -2. 建立一个 caddyfile.txt 文件放到 caddy-data 目录 +## 最大的坑:运营商封 80/443,但封不了 666 - caddy 文件内容如下,注意: +国内电信/联通/移动家庭宽带默认封锁**入站 80、443**(防私搭网站),很多用户还没有公网 IP。 - - ob.xxxx.cc 要改成自己的域名 - - localhost 要改成自己服务器的 IP - - 默认用户名:Bob - - 默认密码:hiccup +但 **666 这种冷门端口大概率不在封锁名单**。本文的思路,就是把 HTTPS 挪到 666: -```yml -# 全局选项 -{ - # 全局使用alidns - acme_dns alidns { - access_key_id LTAI5tQfd6bBCHDR7HUjpWQR - access_key_secret b74sGYcTuwcvfiiQpTZtNWp5gCAQds - } - # 使用dnspod token - # acme_dns dnspod 37456,ejbe9tb5tiasjz2yu5u688vrwegpm - # 使用cloudflare api token - # acme_dns cloudflare v3ipam6idiwcmfub4iee4yjqyvykx - - # 储存目录默认映射 - storage file_system /data/cert - # 注意storage目录文件默认权限不允许其他人访问 - # 如果需要被其他程序访问,可以自己手动chmod -R - - # 关闭http自动重定向,可避免出现80端口占用问题(可手动加重定向配置) - auto_https disable_redirects - - # 尝试申请Google CA - # 你需要到Google获取eab key来使用,详见:https://pki.goog/ - # eab key仅仅是使用这个服务的权限与域名无关,不管是哪个账号申请,都是通用的 - # 申请eab key不用会自动过期 - # 如果你有Google domains,可以一键申请https://domains.google.com - # 注意:你需要自己解决https://dv.acme-v02.api.pki.goog/的科学访问 - # email exmaple@gmail.com - # cert_issuer acme https://dv.acme-v02.api.pki.goog/directory { - # eab - # } - # 失败回退常规acme - # cert_issuer acme - - # 屏幕打印日志,需要调试的时候可打开 - # log { - # output stdout - # format console - # level debug - # } -} -ob.xxxx.cc {#这里要改成自己的域名 - reverse_proxy http://localhost:88 #这里要改成自己服务器的IP - basic_auth { - # Username "Bob", password "hiccup" - Bob $2a$14$Zkx19XLiW6VYouLHR5NmfOFU0z2GTNmpkT/5qqR7hx4IjWJPDhjvG - } -} +```text +浏览器 → https://ob.example.cc:666 + → 电信光猫/路由器(端口转发 666 → NAS) + → 家里 NAS · Caddy(TLS 终止 + 密码) + → ignis :8080 ``` -3. 使用以下 docker compose 文件建立 docker 服务 +- 证书由 Caddy 用 **DNS 验证**申请和续期,走的是**出站**流量,运营商封不封入站端口都不影响 +- 家里公网 IP 是动态的,用 **DDNS** 自动更新域名解析(Caddy 自带,不用额外容器) +- 数据完全留在家里,**不经过任何第三方** -```yml -version: '3' +**前提只有两个**:① 家里有公网 IP;② 666 没被运营商封。不满足?直接跳到文末备选,还有两条免费的路。 +## 开工前,备好这 5 样东西 + +| 需要 | 说明 | +|------|------| +| 家里有公网 IP | 打电信客服 10000 申请(部分地区直接有,客服一般会给);拿不到就跳到最后备选 | +| 一个二级域名 | 如 `ob.example.cc`,解析由 DDNS 自动维护,不用手动改 | +| DNS 服务商 API Token | 阿里云 / 腾讯云 / Cloudflare 都行,**只开"修改 DNS"权限**(签证书、更新解析都用它);必须用 DNSPod 的见文末自建备选 | +| 路由器端口转发 | 把公网 666 转发到家里 NAS 的 666(光猫是路由模式就在光猫上做) | +| 一台能跑 Docker 的机器 | NAS / 旧电脑 / 小主机,1 GB 内存即可 | + +## 部署:6 步,30 分钟 + +### 1. 花两分钟确认:公网 IP 有没有?666 封没封? + +- **公网 IP**:浏览器打开 `ip.sb` 记下 IP;登录光猫(`192.168.1.1`)看 WAN 口 IP。两者一致 = 有;WAN 口是 `100.64.x.x ~ 100.127.x.x` = CGNAT 大内网,**没有**,直接看文末备选 +- **666 封没封**:用在线端口扫描工具(如 `ping.chinaz.com` 的端口检测),输入公网 IP 和 666,显示"开放"即可。部分城市 8080/8443/8888 这类常见端口都在封锁名单,666 这种冷门端口大概率没事,但务必先测 + +### 2. 生成登录密码 + +basic_auth 要求 bcrypt 哈希,别照抄网上的,自己生成: + +```bash +docker run --rm registry.cn-shanghai.aliyuncs.com/xm798/caddy:plus caddy hash-password --plaintext 你的密码 +``` + +记下输出的一长串 `$2a$14$...`,第 4 步要用。 + +### 3. 写 docker-compose.yml:只有 2 个容器 + +直接用现成镜像 **`xm798/caddy:plus`**——国内开发者维护,已内置阿里云 / 腾讯云 / Cloudflare 三个 DNS 模块和 dynamic_dns(DDNS)模块,同步在阿里云容器镜像仓库,**国内直拉、不用配加速器、不用编译**: + +```yaml services: - ignis: - image: registry.cn-hangzhou.aliyuncs.com/yue-images/ignis:latest - container_name: ignis2 + caddy: + image: registry.cn-shanghai.aliyuncs.com/xm798/caddy:plus + container_name: caddy + restart: unless-stopped ports: - - "88:8080" + - "666:443" # 公网走 666,映射到容器内 443 + volumes: + - ./Caddyfile:/etc/caddy/Caddyfile:ro + - ./caddy_data:/data + - ./caddy_config:/config + networks: + - ignis-net + + ignis: + image: docker.1panel.live/nobbe/ignis:latest # Docker Hub 原版:nobbe/ignis:latest + container_name: ignis + restart: unless-stopped environment: - OBSIDIAN_VERSION=1.12.7 - PUID=1000 - PGID=1000 + - WS_ORIGINS=https://ob.example.cc:666 # 改你的域名,注意带端口 volumes: - ./vaults:/vaults - ./data:/app/data - - ./obsidian-app:/app/obsidian-app - restart: unless-stopped - caddy: - pull_policy: always - image: registry.cn-hangzhou.aliyuncs.com/yue-images/caddy:latest - container_name: caddy - restart: unless-stopped - environment: - - TZ=Asia/Shanghai - - DNS=223.5.5.5,8.8.8.8 - volumes: - - ./caddy_data:/data - ports: - # - '8000:80' - - '8001:443' + networks: + - ignis-net + +networks: + ignis-net: ``` -### 结果 +> 注意:这个镜像**不含** DNSPod 模块(Caddy 2.10 后 libdns 升级,dnspod 插件尚未适配,作者已从最新构建移除)。必须用 DNSPod 的读者,见文末「自建 Caddy(备选)」。 +> +> ignis 走 1Panel 加速站前缀(国内直拉,已验证可用);哪天拉不动了,换成其他加速站前缀,或配好 Docker 加速器后用原版 `nobbe/ignis:latest`,其他配置不用动。 + +家里建 `~/obsidian-web`,把上面存为 `docker-compose.yml`。几个要点: + +- caddy 和 ignis 同在 `ignis-net` 内网,Caddy 用服务名 `ignis:8080` 访问上游 +- ignis **不映射任何端口**,公网只能通过 Caddy 进入 +- 证书走 DNS 验证,**不依赖任何入站端口**;666 只是暴露在公网的入口 +- **DDNS 也由 Caddy 承担**,所以整个部署只有 2 个容器 +- 666 < 1024 是低端口,常规 Docker(root 守护进程)可直接绑定;用 rootless Docker 的读者需先执行 `sudo sysctl -w net.ipv4.ip_unprivileged_port_start=0` + +### 4. 写 Caddyfile:证书 + DDNS + 密码,一次配好 + +把域名、密码哈希、DNS Token 换成你自己的: + +```caddyfile +# 全局配置:用 DNS 验证申请证书(出站申请,不依赖任何入站端口) +{ + acme_dns alidns { + access_key_id <你的阿里云 AccessKey ID> + access_key_secret <你的阿里云 AccessKey Secret> + } + # 用腾讯云 DNS 的话,替换上面为: + # acme_dns tencentcloud , + # 用 Cloudflare 的话,替换上面为: + # acme_dns cloudflare + + # DDNS:家里公网 IP 变了,自动更新 ob.example.cc 的解析 + # Token 与上面 acme_dns 用同一个;不想写两遍可改用 {env.XXX} 环境变量 + dynamic_dns { + provider alidns { + access_key_id <你的阿里云 AccessKey ID> + access_key_secret <你的阿里云 AccessKey Secret> + } + # 用腾讯云 DNS 的话,替换上面为: + # provider tencentcloud , + # 用 Cloudflare 的话,替换上面为: + # provider cloudflare + + domains { + example.cc ob + } + versions ipv4 + ip_source simple_http https://api.ipify.org + } + + storage file_system /data/cert + auto_https disable_redirects +} + +ob.example.cc { + encode gzip zstd + + reverse_proxy ignis:8080 + + basic_auth { + admin $2a$14$你的密码哈希 + } +} +``` + +> ⚠️ Token 用**最小权限**子账号或专用 Token(只给"修改 DNS 记录"权限),**永远不要把主账号凭证写进配置**。 + +配好之后 DDNS 也一并生效:Caddy 每 30 分钟查一次家里公网 IP,变了就自动更新 `ob.example.cc` 的 A 记录,不需要任何额外容器。 + +> 飞牛用户更习惯图形界面的话,也可以用系统内置的「网络 → DDNS」(支持阿里云 / 腾讯云 / 花生壳 / DuckDNS),二选一即可。 + +### 5. 路由器端口转发 + +把公网 `666` 转发到家里 NAS 的 `666`。电信光猫默认是路由模式:登录光猫(`192.168.1.1`)→ 端口映射 / 虚拟服务器 → 新增:外部端口 666 → 内网 NAS IP 的 666(TCP)。光猫改过桥接、用自备路由器的,就在路由器上做同样的映射。 + +### 6. 启动!看到登录页就成功了 + +```bash +docker compose up -d +docker compose logs -f ignis +# 首次启动会从 Obsidian 官方源下载客户端,看到 Listening on http://0.0.0.0:8080 即成功 +``` + +浏览器打开 **`https://ob.example.cc:666`**,输入用户名(示例 `admin`)和第 2 步设置的密码: ![image](assets/image-20260809181306-0e1qd33.png) +登录后进入 Vault 管理器(`vaults/` 为空则新建): + ![Snipaste_2026-08-09_18-27-29](assets/Snipaste_2026-08-09_18-27-29-20260809183007-aavwkz2.png) + +到这里,**Web 版 Obsidian 就跑起来了**——没花一分钱,数据全在自己家,任何设备的浏览器都能用。 + +## 常见坑(先看这里,能省一小时) + +**证书申请失败** + +- `docker compose logs caddy` 看报错 +- 确认域名解析已指向**家里公网 IP**(`dig ob.example.cc`)——刚配完 DDNS 可能有延迟,等一两分钟 +- 确认 Token 权限是"修改 DNS 记录"且对应域名所在的账号 +- Cloudflare 用户要把代理(橙色云)关掉,保持 DNS only + +**666 也是封的 / 没有公网 IP** + +- 换文末备选方案(Cloudflare Tunnel / Tailscale) +- 有些城市 8080、8443、8888 这类常见端口都在封锁名单,部署前先测;666 被真封了,换一个没封的端口(如 6666)改 compose 映射和 DDNS 域名即可 + +**换 IP 后连不上** + +- 看 Caddy 日志里 dynamic_dns 的输出:`docker compose logs caddy | grep -i dynamic_dns`,确认解析已更新(再 `nslookup ob.example.cc` 核对) +- 光猫/路由器重启会换 IP,IP 检测默认 30 分钟一次,稍等几分钟 + +**国内服务器下载不了 Obsidian** + +首次启动要从 GitHub 下载客户端,被墙会卡在 `curl: (18) ...`。手动下载 `.deb` 包挂载进去: + +```bash +# 在有外网的机器下载,再传到 ~/obsidian-web/ +wget https://github.com/obsidianmd/obsidian-releases/releases/download/1.12.7/obsidian_1.12.7_amd64.deb +``` + +`docker-compose.yml` 的 ignis 服务加两行: + +```yaml + volumes: + - ./obsidian.deb:/packages/obsidian.deb:ro + environment: + - OBSIDIAN_PACKAGE=/packages/obsidian.deb +``` + +然后 `docker compose up -d` 重启。 + +**日常备份 / 升级** + +- 备份:vault 就是普通文件夹,直接 `tar czf vault-$(date +%F).tar.gz vaults/`,或同步到 Git / WebDAV +- 升级:`docker compose pull && docker compose up -d`,笔记和配置都不会动 + +## 备选:没有公网 IP,或 666 也被封 + +- **Cloudflare Tunnel**:零成本、无需公网 IP、自动 HTTPS、标准域名不带端口。家里跑 cloudflared 容器,主动出站连 Cloudflare 边缘即可,连端口转发都省了。缺点:国内免费版速度一般、数据会经过 Cloudflare。适合域名已托管在 CF 的读者 +- **Tailscale**:纯自用最省事。服务器和设备的 Tailscale 登录同一账号、开 MagicDNS,服务器执行 `tailscale serve --bg 8080`,浏览器访问生成的 `https://xxx.ts.net` 即可,同样有 HTTPS。缺点:只有装了 Tailscale 的设备能访问 + +## 备选:自建 Caddy(必须用 DNSPod / 想自定义模块时) + +主线镜像不支持 DNSPod,且属于第三方构建。必须用 DNSPod、或想自己加模块的读者,改用 xcaddy 自建,模块、配置与主线完全一致。新建 `Dockerfile.caddy`: + +```dockerfile +FROM caddy:2-builder AS builder +RUN xcaddy build --with github.com/caddy-dns/alidns \ + --with github.com/caddy-dns/dnspod \ + --with github.com/caddy-dns/cloudflare \ + --with github.com/mholt/caddy-dynamicdns + +FROM caddy:2 +COPY --from=builder /usr/bin/caddy /usr/bin/caddy +``` + +compose 里把 caddy 的 `image:` 一行换成: + +```yaml + build: + context: . + dockerfile: Dockerfile.caddy +``` + +Caddyfile 的 DNS provider 相应改回 DNSPod 语法:`acme_dns dnspod ,`、`provider dnspod ,`。 + +> 国内编译慢/失败的话:先给 Docker 配好镜像加速(拉 `caddy:2-builder`),再在 Dockerfile 顶部加一行 `ENV GOPROXY=https://goproxy.cn,direct`,让 xcaddy 从国内 Go 代理拉模块,编译时间能从十几分钟降到一两分钟。 + +--- + +## 写在最后 + +这篇教程踩过的坑,基本都写进去了:运营商封锁、国内拉不动镜像、证书失败、首次启动卡下载……如果你照着做,卡在文章里没有的地方,欢迎评论区留言,我会把新坑补进来。 + +觉得有用的话,点个**赞**、**收藏**,转给同样在折腾 Obsidian 的朋友。 + +**下一篇预告**:Obsidian + Ignis + Obsidian Git 三件套自动备份方案——笔记双保险,一篇讲透。关注不迷路。