基于本服务器的部署经历,踩过的坑记录下来,由chatgpt润色
使用 Obsidian + LiveSync + Quartz 搭建自托管博客
这套方案将 Obsidian 作为内容编辑器,通过 Self-hosted LiveSync 同步到 CouchDB,再由 livesync-cli 将数据库内容还原成服务器上的 Vault,最后使用 Quartz 生成静态网站。
最终链路:
Obsidian PC / Android
│
│ Self-hosted LiveSync
▼
CouchDB
│
│ livesync-cli
▼
/opt/obsidian/vault
│
└── Public
│
│ Quartz --watch
▼
Static HTML
│
▼
1Panel / OpenResty
│
▼
linvk.com博客内容仍然是普通 Markdown 文件,不依赖 WordPress、数据库型 CMS 或 GitHub Pages。
一、目录结构
服务器统一使用:
/opt/obsidian/
├── livesync-data/
├── vault/
│ ├── Private/
│ └── Public/
│ ├── index.md
│ ├── Linux/
│ ├── Docker/
│ └── attachments/
│
└── quartz/
└── quartz.config.yaml1Panel 网站目录:
/opt/1panel/www/sites/linvk.com/index其中:
Private/用于私人笔记。
Public/作为 Quartz 唯一的博客内容目录。
只要文件不进入 Public,就不会被博客发布。
二、部署 CouchDB
Obsidian Self-hosted LiveSync 使用 CouchDB 作为同步数据库。
可以通过 1Panel 应用商店或 Docker Compose 部署 CouchDB。
示例:
services:
couchdb:
image: couchdb:3.5.2
container_name: obsidian-couchdb
restart: unless-stopped
environment:
COUCHDB_USER: obsidian
COUCHDB_PASSWORD: CHANGE_ME
volumes:
- ./data:/opt/couchdb/data
ports:
- "127.0.0.1:5984:5984"建议不要直接将:
5984暴露到公网。
通过 OpenResty 反向代理:
https://obsidian.example.com访问 CouchDB。
例如:
location / {
proxy_pass http://127.0.0.1:5984;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}然后在 CouchDB 中创建数据库,例如:
obsidiannotes三、配置 Obsidian Self-hosted LiveSync
在 Obsidian 安装:
Self-hosted LiveSync配置 CouchDB:
URI:
https://obsidian.example.com
Database:
obsidiannotes
Username:
obsidian
Password:
********完成配置后,让 PC、Android 等设备均连接到同一个 CouchDB。
此时同步链路为:
Obsidian
↕
CouchDB但 CouchDB 中的数据还不能直接交给 Quartz。
还需要 livesync-cli 将数据同步为真实的 Markdown 文件。
四、部署 livesync-cli
创建目录:
mkdir -p /opt/obsidian/livesync-data
mkdir -p /opt/obsidian/vault使用官方镜像:
ghcr.io/vrtmrz/livesync-cli:latestCompose:
services:
livesync-cli:
image: ghcr.io/vrtmrz/livesync-cli:latest
container_name: obsidian-livesync-cli
restart: unless-stopped
volumes:
- /opt/obsidian/livesync-data:/data
- /opt/obsidian/vault:/vault
command:
- --vault
- /vault
- --interval
- "30"
- daemon首次使用时需要完成 livesync-cli 的远程配置。
之后 daemon 会定期从 CouchDB 同步。
正常情况下服务器会出现:
/opt/obsidian/vault/
├── Private/
├── Public/
├── xxx.md
└── attachments/--interval 30 表示大约每 30 秒检查一次变化。
五、规划 Public 和 Private
建议 Vault 使用:
Vault/
├── Private/
│ ├── 私人笔记.md
│ ├── 服务器密码.md
│ └── 内部资料.md
│
└── Public/
├── index.md
├── hello-world.md
├── Linux/
├── Docker/
└── attachments/Quartz只读取:
/vault/Public因此:
Private不会进入构建过程。
这是整个博客最重要的安全边界。
六、附件和图片
公开文章使用的附件同样必须位于 Public 内。
正确:
Public/
├── article.md
└── attachments/
└── test.jpgObsidian:
![[test.jpg]]不要使用:
Vault/
├── Public/
│ └── article.md
│
└── test.jpg虽然 Obsidian 可以在整个 Vault 中找到 test.jpg,但 Quartz 输入目录只有:
/vault/Public因此无法访问 Public 外的附件。
建议在 Obsidian:
设置
→ 文件与链接
→ 新附件的默认位置设置为当前笔记目录下的附件子目录。
七、部署 Quartz v5
使用官方 Quartz 镜像:
ghcr.io/jackyzha0/quartz:latest创建:
/opt/obsidian/quartz/quartz.config.yaml基础配置:
configuration:
pageTitle: "LinVK"
locale: zh-CN
baseUrl: linvk.comQuartz Compose:
services:
quartz:
image: ghcr.io/jackyzha0/quartz:latest
container_name: obsidian-quartz
restart: unless-stopped
user: "0:0"
working_dir: /usr/src/app
mem_limit: 768m
memswap_limit: 1g
volumes:
- "/opt/obsidian/vault:/vault:ro"
- "/opt/obsidian/quartz/quartz.config.yaml:/usr/src/app/quartz.config.yaml:ro"
- "/opt/1panel/www/sites/linvk.com:/site"
entrypoint:
- /bin/sh
- -lc
command:
- exec npx quartz build -d /vault/Public -o /site/index --concurrency 1 --watch其中:
-d /vault/Public指定博客来源。
-o /site/index指定生成目录。
--watch持续监听 Public 中的文件变化。
--concurrency 1限制构建并发,在低核心数服务器上可以减少瞬时负载。
启动后 Quartz 容器应长期保持:
Running而不是一次性构建模式下的:
Exited (0)八、为什么输出到 /site/index
不要直接这样挂载:
- /opt/1panel/www/sites/linvk.com/index:/output然后:
-o /outputQuartz 构建时会清理输出目录。
Docker bind mount 本身不能被直接删除,因此可能出现:
EBUSY: resource busy or locked正确方式是挂载父目录:
- /opt/1panel/www/sites/linvk.com:/site再输出到普通子目录:
/site/index对应:
/opt/1panel/www/sites/linvk.com/indexQuartz 可以正常删除和重新创建 index。
九、创建博客首页
Public 根目录需要:
index.md例如:
---
title: LinVK
description: LinVK 的个人笔记与技术记录
---
# LinVK
技术记录、项目笔记以及问题排查记录。
## 内容
- Linux
- Docker
- 网络
- 服务器
- 嵌入式
- AI
> 记录问题,也记录解决问题的过程。Quartz 会生成:
index.html对应:
https://linvk.com/十、配置 1Panel 网站
在 1Panel 创建静态网站:
linvk.com网站目录指向:
/opt/1panel/www/sites/linvk.com/index配置 SSL 后即可由 OpenResty 提供 Quartz 生成的静态文件。
十一、配置 Clean URL
Quartz 生成的文件通常类似:
index.html
hello-world.html
test.html但页面链接使用:
/
/hello-world
/test因此 OpenResty 需要支持无 .html 后缀访问。
1Panel:
网站
→ linvk.com
→ 伪静态配置:
location / {
try_files $uri $uri.html $uri/ =404;
}
error_page 404 /404.html;
location = /404.html {
internal;
}此时:
/hello-world会自动匹配:
/hello-world.html浏览器地址仍然保持:
https://linvk.com/hello-world十二、Quartz 自动更新流程
启用 --watch 后,不再需要每分钟执行 Quartz 构建任务。
完整流程:
Obsidian 编辑文章
│
▼
Self-hosted LiveSync
│
▼
CouchDB
│
▼
livesync-cli
│
▼
/opt/obsidian/vault/Public
│
▼
Quartz --watch
│
▼
重新生成 HTML
│
▼
OpenResty
│
▼
linvk.com更新时间主要取决于 livesync-cli 的轮询周期。
如果:
--interval 30通常保存 Obsidian 后几十秒内即可更新网站。
十三、Quartz 资源限制
Quartz 是 Node.js 应用。
--watch 模式会长期驻留内存,因此服务器需要保留足够的 RAM。
建议至少配置:
mem_limit: 768m
memswap_limit: 1g同时观察:
free -h
cat /proc/pressure/memory
docker stats obsidian-quartz正常状态应满足:
MemAvailable 有明显余量
Swap 不持续快速增长
memory PSI 接近 0如果出现:
Swap 100%
kswapd0 高占用
memory PSI 接近 100%
load 快速升高说明宿主机内存不足。
此时应该增加服务器内存,而不是继续提高 Quartz 的容器限制。
十四、磁盘空间
Docker、containerd、数据库和日志会持续消耗系统盘。
建议定期检查:
df -h /
docker system df
journalctl --disk-usage尤其需要关注:
/var/lib/containerd
/opt/1panel/apps
/opt/1panel/backup
/opt/1panel/tmp不要直接删除:
/var/lib/containerd/*
/var/lib/docker/*这会破坏 Docker 镜像和容器状态。
Docker 构建缓存可以通过:
docker builder prune -af清理。
APT 缓存:
apt clean对于数据库服务器,建议系统盘长期保持至少:
15%~20%可用空间。
CouchDB 在磁盘完全耗尽时可能出现:
ENOSPC
HTTP 500因此不应让根分区长期处于 95% 以上。
十五、安全配置
以下内容不应直接暴露公网:
PostgreSQL 5432
CouchDB 5984
Redis 6379
MySQL 3306数据库应监听:
127.0.0.1或仅发布到 Docker 内部网络。
CouchDB 对外只保留:
443
↓
obsidian.example.com
↓
OpenResty
↓
CouchDB同时不要将以下内容放入:
Public/包括:
- SSH 私钥
- API Key
- Cookie
- Token
- 数据库密码
- Cloudflare 凭据
- LiveSync Setup URI
- VPN 私钥
- 未脱敏配置文件
十六、最终架构
┌────────────────────┐
│ Obsidian │
│ PC / Android │
└─────────┬──────────┘
│
│ Self-hosted LiveSync
▼
┌────────────────────┐
│ CouchDB │
└─────────┬──────────┘
│
│ livesync-cli
▼
┌────────────────────┐
│ Vault │
│ │
│ Private Public │
│ │ │
└──────────────┼─────┘
│
│ Quartz v5 --watch
▼
┌────────────────────┐
│ Static HTML │
└─────────┬──────────┘
│
│ OpenResty
▼
┌────────────────────┐
│ linvk.com │
└────────────────────┘整个系统中各组件职责:
| 组件 | 作用 |
|---|---|
| Obsidian | Markdown 编辑 |
| Self-hosted LiveSync | 多设备同步 |
| CouchDB | LiveSync 数据存储 |
| livesync-cli | CouchDB 内容同步为真实 Vault |
| Public | 博客发布边界 |
| Quartz v5 | Markdown 转静态网站 |
--watch | 自动监听 Public 变化 |
| Docker | 服务运行环境 |
| 1Panel | 服务和网站管理 |
| OpenResty | HTTPS、静态文件和 Clean URL |
最终使用方式:
在 Obsidian 中写文章
↓
移动到 Public
↓
保存
↓
自动同步
↓
自动构建
↓
博客更新原始内容始终保持为:
Markdown + 图片 + 附件即使以后更换静态网站生成器,也不影响 Obsidian 中的原始笔记。