Files
OSQY/如何搭建web版本obsidian/如何搭建web版本obsidian.md
T

13 KiB
Raw Blame History

没有官方网页版?30 分钟自建一个 Web 版 Obsidian

免费、私有、带密码,数据全在自己家。不用买云服务器,运营商封了 80/443 也不影响——浏览器打开就能记笔记。

先看痛点:Obsidian 官方一直没做网页版

出差没带电脑、公司电脑不让装软件、想用平板随手记……Obsidian 重度用户绕不开这三件事。

官方没有网页版,官方同步要付费;过去想远程用 Obsidian,只能 VNC 远程桌面——又重又卡。

好在有 Ignis:它在浏览器里重新实现了 Obsidian 依赖的 Electron API,让 Obsidian 原生跑在网页里。vault 留在你自己家里,部署一次长期可用。

本文要用到的两个前提,先记住:

  • Ignis 没内置认证,必须自己套一层反向代理加密码(本文用 Caddy)
  • 必须 HTTPS:剪贴板、离线缓存等 API 只在 HTTPS 下生效,纯 HTTP 公网访问会直接失效

你能得到什么

项目 结果
时间 照做约 30 分钟
成本 0 元,不需要云服务器
容器 2 个(ignis + Caddy),一个装好、一个转发
访问 任何设备的浏览器:https://你的域名:666
数据 100% 留在家里,不经过任何第三方
前提 家里有公网 IP + 666 未被运营商封(不满足也有免费备选,见文末)

最大的坑:运营商封 80/443,但封不了 666

国内电信/联通/移动家庭宽带默认封锁入站 80、443(防私搭网站),很多用户还没有公网 IP。

但 666 这种冷门端口大概率不在封锁名单。本文的思路,就是把 HTTPS 挪到 666:

浏览器 → https://ob.example.cc:666
        → 电信光猫/路由器(端口转发 666 → NAS)
        → 家里 NAS · Caddy(TLS 终止 + 密码)
        → ignis :8080
  • 证书由 Caddy 用 DNS 验证申请和续期,走的是出站流量,运营商封不封入站端口都不影响
  • 家里公网 IP 是动态的,用 DDNS 自动更新域名解析(Caddy 自带,不用额外容器)
  • 数据完全留在家里,不经过任何第三方

前提只有两个:① 家里有公网 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 哈希,别照抄网上的,自己生成:

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)模块,同步在阿里云容器镜像仓库,国内直拉、不用配加速器、不用编译:

services:
  caddy:
    image: registry.cn-shanghai.aliyuncs.com/xm798/caddy:plus
    container_name: caddy
    restart: unless-stopped
    ports:
      - "666:443"         # 公网走 666,映射到容器内 443
    volumes:
      - ./caddyfile.txt:/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    
    volumes:
      - ./vaults:/vaults
      - ./data:/app/data
    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.txt:证书 + DDNS + 密码,一次配好

把域名、密码哈希、DNS Token 换成你自己的:

# 全局配置:用 DNS 验证申请证书(出站申请,不依赖任何入站端口)
{
    acme_dns alidns {
        access_key_id <你的阿里云 AccessKey ID>
        access_key_secret <你的阿里云 AccessKey Secret>
    }
    # 用腾讯云 DNS 的话,替换上面为:
    # acme_dns tencentcloud <SecretId>,<SecretKey>
    # 用 Cloudflare 的话,替换上面为:
    # acme_dns cloudflare <API Token>

    # 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 <SecretId>,<SecretKey>
        # 用 Cloudflare 的话,替换上面为:
        # provider cloudflare <API Token>

        domains {
            example.cc ob
        }
        versions ipv4
        # 获取公网 IP 的方式,可以使用多个作为备份
        ip_source simple_http https://myip.ipip.net
        ip_source simple_http https://ip.3322.net
    }

    storage file_system /data/cert
    auto_https disable_redirects
}

ob.example.cc {
    encode gzip zstd

    reverse_proxy ignis:8080

    basic_auth {
		# Username "Bob", password "hiccup"
		Bob $2a$14$Zkx19XLiW6VYouLHR5NmfOFU0z2GTNmpkT/5qqR7hx4IjWJPDhjvG
    }
}

⚠️ 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. 启动!看到登录页就成功了

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

登录后进入 Vault 管理器(vaults/ 为空则新建):

Snipaste_2026-08-09_18-27-29

到这里,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 包挂载进去:

# 在有外网的机器下载,再传到 ~/obsidian-web/
wget https://github.com/obsidianmd/obsidian-releases/releases/download/1.12.7/obsidian_1.12.7_amd64.deb

docker-compose.yml 的 ignis 服务加两行:

    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:

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: 一行换成:

    build:
      context: .
      dockerfile: Dockerfile.caddy

Caddyfile 的 DNS provider 相应改回 DNSPod 语法:acme_dns dnspod <ID>,<Token>、provider dnspod <ID>,<Token>。

国内编译慢/失败的话:先给 Docker 配好镜像加速(拉 caddy:2-builder),再在 Dockerfile 顶部加一行 ENV GOPROXY=https://goproxy.cn,direct,让 xcaddy 从国内 Go 代理拉模块,编译时间能从十几分钟降到一两分钟。


写在最后

这篇教程踩过的坑,基本都写进去了:运营商封锁、国内拉不动镜像、证书失败、首次启动卡下载……如果你照着做,卡在文章里没有的地方,欢迎评论区留言,我会把新坑补进来。

觉得有用的话,点个赞、收藏,转给同样在折腾 Obsidian 的朋友。

下一篇预告:Obsidian + Ignis + Obsidian Git 三件套自动备份方案——笔记双保险,一篇讲透。关注不迷路。