先选对部署方式Pick the right deployment first
手机端必须走 HTTPS。浏览器只在整个页面是安全上下文时才提供加密能力(crypto.subtle),这是硬前提;服务端自己也会拒绝非 HTTPS 的 API 凭据请求。
The phone side must use HTTPS. Browsers only provide encryption capability (crypto.subtle) when the whole page is a secure context — a hard prerequisite; the server itself also refuses non-HTTPS API credential requests.
无论服务端跑在哪,它前面都需要一层 TLS(Caddy、Tailscale、临时隧道或自签 + 装 CA)。服务端本身只监听本机回环,明文端口永远不直接暴露到网络。
Wherever the server runs, something in front of it must terminate TLS (Caddy, Tailscale, a temporary tunnel, or self-signed + an installed CA). The server itself listens only on the local loopback; the plaintext port is never exposed to the network.
| 路径(点击直达) | 需要 | 数据目录 | 适合 |
|---|---|---|---|
| Windows 本地直跑 | 现成的 Windows 电脑 + Novara 安装包(自带 Sync\) | %LOCALAPPDATA%\Novara\Server\data | 已经有台常开的电脑,想五分钟跑起来 |
| Docker Compose(Linux / VPS) | Docker 与 Compose v2 + 一个域名(https profile) | ./data(bind mount) | 长期挂在公网,推荐 Compose + Caddy 自动证书 |
| 群晖 DSM | x86 机型 + Container Manager | NAS 本机磁盘目录 | 家里已有群晖 |
| 威联通 QNAP | amd64 机型 + Container Station | NAS 本机存储池 | 家里已有威联通 |
| 纯二进制 | 能跑 net10.0 自包含发布的任何机器 | 自定(NOVARA_SYNC_DATA) | 不想用 Docker 的进阶玩家 |
| Path (click to jump) | Requires | Data directory | Best for |
|---|---|---|---|
| Windows direct-run | An existing Windows PC + the Novara installer (bundles Sync\) | %LOCALAPPDATA%\Novara\Server\data | An always-on PC, running in five minutes |
| Docker Compose (Linux / VPS) | Docker + Compose v2 + a domain (https profile) | ./data (bind mount) | Long-running in the open; Compose + Caddy auto-certificates recommended |
| Synology DSM | x86 model + Container Manager | A local NAS disk directory | You already own a Synology |
| QNAP | amd64 model + Container Station | A local NAS storage pool | You already own a QNAP |
| Plain binary | Any machine running a net10.0 self-contained build | Custom (NOVARA_SYNC_DATA) | Advanced users skipping Docker |
无论选哪条都相同的事
True no matter which you pick
- 数据目录必须在本机磁盘。NFS / SMB 网络盘是数据损坏风险(SQLite 的 WAL 依赖共享内存与文件锁),不是性能问题。
- 首跑都是同一套三步:建空间(凭据只显示一次)→ 起服务 → 桌面端配对。细节见下方《建空间与配对》。
- 服务端只监听回环或内网,TLS 由前面的反代终止;反代与转发头规则见《反向代理与 HTTPS》。
- The data directory must be on a local disk. NFS / SMB network shares are a data-corruption risk (SQLite's WAL depends on shared memory and file locks), not a performance issue.
- The first run is always the same three steps: create the space (credentials shown once) → start the server → pair the desktop. Details in "Create a space and pair" below.
- The server listens on loopback or the internal network only, with TLS terminated by the reverse proxy in front; proxy and forwarded-header rules in "Reverse proxy and HTTPS".
怎么选
How to choose
- 手头有常开的 Windows 电脑 → 先走 Windows 直跑,十分钟出结果,之后随时迁到 NAS。
- 有 VPS 或家里的 Linux 小主机 → Docker Compose + Caddy,一次配好长期不用管证书。
- 已有群晖 / 威联通 → 直接看 群晖 / 威联通;先确认机型是 x86 / amd64。
- 全部都不合适或想极致控制 → 纯二进制,与 Docker 同一套代码、同一组环境变量。
- An always-on Windows PC at hand → start with Windows direct-run; results in ten minutes, migrate to a NAS any time.
- A VPS or a Linux box at home → Docker Compose + Caddy; set up once, never manage certificates again.
- Already have a Synology / QNAP → go straight to Synology / QNAP; confirm the model is x86 / amd64 first.
- Nothing fits, or you want total control → the plain binary: the same code, the same environment variables as Docker.
Windows 本地直跑Run on Windows
Sync\ 里有什么
What is inside Sync\
Novara 安装目录下的 Sync\ 文件夹包含 NovaraSync.exe 与三个脚本,无需另装 .NET runtime:
The Sync\ folder in the Novara install directory contains NovaraSync.exe and three scripts, with no separate .NET runtime needed:
| 文件 | 作用 |
|---|---|
1-建空间.cmd | 创建同步空间,打印 space id 与 enrollment secret(只显示一次) |
2-启动服务端.cmd | 用与建空间相同的数据目录启动服务端 |
3-查看空间.cmd | 列出当前数据目录里的空间 |
| File | Purpose |
|---|---|
1-建空间.cmd | Creates the sync space, printing the space id and enrollment secret (shown once) |
2-启动服务端.cmd | Starts the server with the same data directory used for space creation |
3-查看空间.cmd | Lists the spaces in the current data directory |
三个脚本共用同一个数据目录 %LOCALAPPDATA%\Novara\Server\data——建空间与服务端不会各说各话。
All three scripts share one data directory, %LOCALAPPDATA%\Novara\Server\data — space creation and the server can never drift apart.
双击式流程
The double-click flow
- 建空间双击
1-建空间.cmd,按提示执行;记下打印的两串凭据。 - 启动服务端双击
2-启动服务端.cmd。窗口开着 = 服务端在跑;关闭窗口即停止。 - 配上 HTTPS 通道手机要访问就需要一条 HTTPS 链路(域名 + Caddy、Tailscale、临时隧道或自签),见《反向代理与 HTTPS》。
- 桌面端配对填
https://你的对外地址(或 Tailscale 地址)、space id、enrollment secret,空间密钥留空。
- Create the spaceDouble-click
1-建空间.cmdand follow the prompts; note the two printed credentials. - Start the serverDouble-click
2-启动服务端.cmd. Window open = server running; closing the window stops it. - Add an HTTPS pathPhone access needs an HTTPS route (domain + Caddy, Tailscale, a temporary tunnel or self-signed) — see "Reverse proxy and HTTPS".
- Pair the desktopFill
https://your-public-address(or the Tailscale address), the space id and the enrollment secret; leave the space key empty.
服务端只监听 127.0.0.1:5180——外部网络直接访问不到,这是有意的;对外一律走 HTTPS 通道。
The server listens only on 127.0.0.1:5180 — unreachable from outside by design; external access always goes through the HTTPS route.
手动命令(进阶)
Manual commands (advanced)
想自定义数据目录或做开机自启时,可以直接跑命令。注意建空间与启动必须指向同一个数据目录:
To customize the data directory or run at startup, drive the commands directly. Space creation and the server must point at the same data directory:
NovaraSync.exe space create --name my-space
NovaraSync.exe --urls http://127.0.0.1:5180改数据目录、配额、版本保留等用环境变量,见《服务端环境变量速查》。
Data directory, quota and retention are configured with environment variables — see "Server environment variables".
Docker Desktop 可选路径
Docker Desktop as an alternative
装了 Docker Desktop 的 Windows 机器也可以直接用 deploy/compose/ 的 compose 文件,行为与 Linux 完全一致(同样的 ./data、同样的 --profile https)。适合想统一用容器管理、或以后要迁到 NAS 的情况。
A Windows machine with Docker Desktop can use the compose files from deploy/compose/ directly, behaving exactly like Linux (the same ./data, the same --profile https). Good for keeping everything container-managed, or for a later move to a NAS.
升级
Upgrading
新版本 Novara 安装包会带更新后的服务端:正常覆盖安装后重新启动 2-启动服务端.cmd 即可,数据目录不动。升级前建议把 %LOCALAPPDATA%\Novara\Server\data 整个复制一份。
A newer Novara installer ships an updated server: install over the existing one normally and restart 2-启动服务端.cmd; the data directory is untouched. Before upgrading, copy %LOCALAPPDATA%\Novara\Server\data somewhere safe.
Ubuntu VPS + DockerUbuntu VPS with Docker
安装 Docker
Install Docker
需要 Docker Engine 与 Compose v2 插件。验证方式:
You need Docker Engine and the Compose v2 plugin. Verify with:
docker compose version有正常输出即可继续;没有就先装 Docker Engine 与 compose 插件。
Normal output means you can continue; otherwise install Docker Engine and the compose plugin first.
放文件与配置
Place the files and configure
把主工程 deploy/compose/ 下的 docker-compose.yml、.env.example 与上级的 Caddyfile 传到服务器同一目录(compose 以 ../Caddyfile 挂载)。然后:
Upload the project's docker-compose.yml and .env.example from deploy/compose/, plus the Caddyfile from the parent directory, into one directory on the server (compose mounts ../Caddyfile). Then:
cp .env.example .env
# 编辑 .env:至少填 NOVARA_DOMAIN 与 NOVARA_SYNC_ALLOWED_HOSTS(同一域名)两个变量都填你的域名(如 sync.example.com),并把域名 A/AAAA 记录指向这台机器。
Both variables take your domain (e.g. sync.example.com), and the domain's A/AAAA records should point at this machine.
防火墙放行
Open the firewall
放行 80/tcp(证书质询)、443/tcp(HTTPS 入口)与 443/udp(HTTP/3)。云厂商安全组与系统防火墙都要覆盖。除此之外不要对公网开放 5180——它只通过 compose 发布在 127.0.0.1:5180。
Allow 80/tcp (certificate challenge), 443/tcp (the HTTPS entry) and 443/udp (HTTP/3). Both the cloud provider's security group and the system firewall must cover them. Beyond that, do not expose 5180 to the public internet — compose publishes it only on 127.0.0.1:5180.
起栈并建空间
Start the stack and create the space
docker compose run --rm novara-sync space create --name 我的空间
docker compose --profile https up -d
docker compose ps- space id 与 enrollment secret 只显示一次,当场收好。
- Caddy 会自动申请并续期证书,等几十秒;
docker compose ps应看到两个服务 running、novara-sync(healthy)。 - 若
./data属主不对,服务端拒绝启动并打印chown -R 1654:1654 ./data——照做即可。
- The space id and enrollment secret are shown exactly once — save them on the spot.
- Caddy obtains and renews certificates automatically; wait a few dozen seconds;
docker compose psshould show both services running and novara-sync(healthy). - If
./datahas the wrong owner, the server refuses to start and printschown -R 1654:1654 ./data— just run it.
配对
Pair
桌面端 → 互联同步 → 配对:https://你的域名 + space id + enrollment secret,空间密钥留空。之后生成手机凭据即可。出问题先查《故障排查》的 403 与证书条目。
Desktop → Encrypted sync → Pair: https://your-domain + space id + enrollment secret, space key empty. Then issue phone credentials. If something fails, check the 403 and certificate entries in "Troubleshooting" first.
群晖 DSM Container ManagerSynology Container Manager
前提条件
Prerequisites
x86 机型为前提。群晖大量入门型号是 ARM 处理器,装不到 Docker / Container Manager——先到 DSM 套件中心确认能安装 Container Manager 再往下走。
An x86 model is a precondition. Many entry-level Synology units use ARM processors and cannot install Docker / Container Manager — confirm in the DSM Package Center that Container Manager installs before going further.
- DSM 7.2+,套件中心可安装 Container Manager。
- 一个域名(启用自动证书的 https profile 时必需;没有域名见《反向代理与 HTTPS》的自签路径)。
- 数据目录落在本机卷——不要把
./data指到 SMB/NFS 网络共享,SQLite 会损坏。
- DSM 7.2+, with Container Manager installable from the Package Center.
- A domain (required for the https profile with automatic certificates; without one, see the self-signed path in "Reverse proxy and HTTPS").
- The data directory on a local volume — do not point
./dataat an SMB/NFS network share; SQLite will corrupt.
建 Compose 项目
Create the Compose project
- 上传文件把主工程
deploy/compose/里的docker-compose.yml与.env.example,以及上级目录的Caddyfile,放到 NAS 的一个目录(compose 会以../Caddyfile挂载它)。 - 新建项目Container Manager → 项目 → 新增 → 选"使用已有 compose",指向刚上传的
docker-compose.yml。 - 配置 .env复制
.env.example为.env放同目录,至少填NOVARA_DOMAIN=你的域名与NOVARA_SYNC_ALLOWED_HOSTS=你的域名。
- Upload the filesPut the project's
docker-compose.ymland.env.examplefromdeploy/compose/, plus theCaddyfilefrom the parent directory, into one folder on the NAS (compose mounts it as../Caddyfile). - Create the projectContainer Manager → Project → Create → choose "use an existing compose", pointing at the uploaded
docker-compose.yml. - Configure .envCopy
.env.exampleto.envin the same folder; at minimum fillNOVARA_DOMAIN=your-domainandNOVARA_SYNC_ALLOWED_HOSTS=your-domain.
首跑三步
The first-run three steps
以下命令可在 Container Manager 的终端机里执行,或 SSH 进 NAS。第一步用一次性容器建空间——它挂载的 ./data 与服务端相同,凭据不会落错目录:
Run these in Container Manager's terminal or over SSH. Step one creates the space with a one-off container — it mounts the same ./data as the server, so credentials cannot land in the wrong place:
cp .env.example .env
docker compose run --rm novara-sync space create --name 我的空间
docker compose --profile https up -d
docker compose ps- 输出里的 space id 与 enrollment secret 只显示这一次,当场收好。
--profile https会同时启动 Caddy 并自动申请证书(需要 80/443 可达),等几十秒。docker compose ps里两个服务都应是 running,novara-sync 显示(healthy)。
- The space id and enrollment secret in the output are shown exactly once — save them on the spot.
--profile httpsalso starts Caddy and issues certificates automatically (80/443 must be reachable); give it a few dozen seconds.- In
docker compose psboth services should be running, with novara-sync(healthy).
配对与后续
Pairing and what follows
桌面端 → 互联同步 → 配对:填 https://你的域名、space id、enrollment secret,空间密钥留空。配对完成后即可生成手机访问凭据。
Desktop → Encrypted sync → Pair: fill in https://your-domain, the space id and the enrollment secret, and leave the space key empty. After pairing you can issue phone credentials.
bind mount 的 ./data 属主来自宿主机,而容器以非 root 用户(uid 1654)运行。属主不对时服务端会拒绝启动,并把该执行的命令原样打印出来:
The bind-mounted ./data keeps the host's ownership, while the container runs as a non-root user (uid 1654). With the wrong owner the server refuses to start and prints the exact command to run:
NovaraSync: refusing to start - the data directory (/data) cannot be written (...)
... fix it with `sudo chown -R 1654:1654 ./data`, or switch to the named volume ...照它说的执行即可——这是设计好的报错,不是崩溃。验证方式:重启 NAS 后数据仍在、同步照常。
Do what it says — this is a designed error, not a crash. Verify by restarting the NAS: the data survives and sync continues.
威联通 Container StationQNAP Container Station
与群晖(5.2)的差异
Differences from Synology (5.2)
先读《群晖 DSM Container Manager》拿到完整流程,下表是全部差异——其余规则(本机磁盘、同一数据目录、非 root 容器、HTTPS 与转发头)逐字相同。
Read "Synology Container Manager" first for the full flow; the table below is every difference — everything else (local disk, same data directory, non-root container, HTTPS and forwarded headers) is word-for-word identical.
| 事项 | 群晖 DSM | 威联通 QTS / QuTS hero |
|---|---|---|
| 管理入口 | Container Manager(套件中心安装) | Container Station(App Center 安装) |
| 机型前提 | x86 机型 | amd64 机型——同样先确认,ARM 机型装不了 |
| 项目创建 | 项目 → 新增 → 使用已有 compose | 应用程序 → 创建应用程序 → 粘贴 / 指向 compose |
| 数据卷位置 | 本机卷共享文件夹 | 本机存储池上的共享文件夹 |
| 首跑三步 | 相同 | 相同 |
| 凭据与配对 | 相同 | 相同 |
| Item | Synology DSM | QNAP QTS / QuTS hero |
|---|---|---|
| Management entry | Container Manager (Package Center) | Container Station (App Center) |
| Model precondition | x86 models | amd64 models — confirm first; ARM cannot install it |
| Project creation | Project → Create → use existing compose | Applications → Create Application → paste / point at the compose |
| Data volume location | Shared folder on a local volume | Shared folder on a local storage pool |
| First-run three steps | Identical | Identical |
| Credentials and pairing | Identical | Identical |
快速流程(细节见群晖篇)
Quick flow (details in the Synology page)
- 确认架构App Center 安装 Container Station;确认 NAS 是 amd64 架构。
- 上传文件
docker-compose.yml、.env.example与上级Caddyfile放到本机存储池的共享文件夹。 - 创建应用程序Container Station → 应用程序 → 创建,指向 compose 文件;同目录放好
.env(至少填NOVARA_DOMAIN与NOVARA_SYNC_ALLOWED_HOSTS)。 - 首跑三步建空间(
run --rm)→--profile https up -d→docker compose ps看 healthy。 - 配对桌面端填域名、space id、enrollment secret,空间密钥留空。
- Confirm the architectureInstall Container Station from the App Center; confirm the NAS is amd64.
- Upload the files
docker-compose.yml,.env.exampleand the parentCaddyfileinto a shared folder on the local storage pool. - Create the applicationContainer Station → Applications → Create, pointing at the compose file; put
.envin the same folder (at leastNOVARA_DOMAINandNOVARA_SYNC_ALLOWED_HOSTS). - First-run three stepsCreate the space (
run --rm) →--profile https up -d→docker compose psshows healthy. - PairFill the domain, space id and enrollment secret on the desktop; leave the space key empty.
两处多看一眼
Two things to double-check
- 架构匹配:确认拉取的镜像架构与 NAS 一致;架构不匹配时容器起不来,报 exec format error 一类错误。
- 目录隔离:数据目录放本机存储池,别放跨机器挂载的网络盘;站点目录(Novara.Web)不包含数据目录——这些规则在威联通上同样生效。
- 首跑命令在哪里执行:通过 Container Station 的终端,或 SSH 进 NAS——与群晖完全一致。
- Architecture match: confirm the pulled image architecture matches the NAS; a mismatch keeps the container from starting with exec format error-style messages.
- Directory isolation: keep the data directory on the local storage pool, never on a cross-machine network share; the web root (Novara.Web) must not contain the data directory — these rules apply on QNAP too.
- Where to run the first-run commands: Container Station's terminal, or SSH into the NAS — exactly as on Synology.
纯二进制部署Binary deployment
拿到什么
What you get
- 服务端使用 net10.0 自包含单文件发布——目标机器不需要安装任何 .NET runtime。
- 发布物包含
NovaraSync主程序与Novara.Web\站点目录(手机端页面)。 - 与 Docker 镜像是同一套代码:同一组
NOVARA_SYNC_*环境变量、同一份 Caddyfile(裸机时NOVARA_UPSTREAM默认127.0.0.1:5180,容器里才是novara-sync:5180)。
- The server ships as a net10.0 self-contained single-file build — the target machine needs no .NET runtime installed.
- The build contains the
NovaraSyncmain program and theNovara.Web\site directory (phone-side pages). - The same code as the Docker image: the same
NOVARA_SYNC_*environment variables, the same Caddyfile (on bare metalNOVARA_UPSTREAMdefaults to127.0.0.1:5180; inside containers it isnovara-sync:5180).
跑起来
Run it
- 放置把发布物放到一个数据目录可写、站点目录完整的位置。
- 设环境变量至少考虑
NOVARA_SYNC_DATA(数据目录)与NOVARA_SYNC_ALLOWED_HOSTS(域名固定时建议填,只写主机名)。 - 建空间并启动同一二进制、同一数据目录,两条命令:
- Place itPut the build somewhere with a writable data directory and the site directory intact.
- Set environment variablesAt least consider
NOVARA_SYNC_DATA(data directory) andNOVARA_SYNC_ALLOWED_HOSTS(recommended with a fixed domain; hostname only). - Create the space and startSame binary, same data directory, two commands:
NovaraSync space create --name my-space
NovaraSync.exe --urls http://127.0.0.1:5180服务端只监听回环。建空间打印的 space id 与 enrollment secret 只显示一次,然后到桌面端配对(空间密钥留空)。
The server listens on loopback only. The space id and enrollment secret print exactly once; then pair on the desktop (space key left empty).
裸机跑 Caddy 时用 caddy run --config deploy/Caddyfile——与 Docker 共用同一份反代配置,NOVARA_UPSTREAM 默认就是回环地址,不用改。
To run Caddy on bare metal: caddy run --config deploy/Caddyfile — the same reverse-proxy config Docker uses; NOVARA_UPSTREAM already defaults to the loopback address, nothing to change.
站点目录的红线
The web-root red lines
NOVARA_SYNC_WEB_ROOT默认指向应用目录下的Novara.Web,一般不用动;指向的位置不存在时服务端只跑 API。- 站点目录绝不包含数据目录:否则静态托管会把密文库与 keywrap 记录公开在
/web下。服务端启动时校验并拒绝启动(refusing to start)。 - 站点树内出现 junction / 符号链接同样拒绝启动——静态提供者会跟着链接走。需要外部内容就把它搬进站点目录。
NOVARA_SYNC_WEB_ROOTdefaults toNovara.Webunder the application directory and rarely needs changing; if the path does not exist, the server runs API-only.- The web root must never contain the data directory: otherwise static serving would publish the ciphertext vault and keywrap records under
/web. The server checks at startup and refuses to start (refusing to start). - Junctions / symbolic links inside the site tree are also refused — the static provider would follow them. Move external content into the site directory if you need it.
验证
Verify
- 启动后访问
http://127.0.0.1:5180/web应跳转到/web/且页面正常。 - 配对一轮后停掉进程再启动,数据仍在——数据目录落点正确。
- 对外链路按《反向代理与 HTTPS》验收;仓库的
Tools/web_selfcheck.py可复核跳转、转发头与安全响应头。
- After startup,
http://127.0.0.1:5180/webshould redirect to/web/and render. - Pair once, stop the process, start it again — the data survives; that confirms the data directory landed in the right place.
- Accept the public route per "Reverse proxy and HTTPS"; the repo's
Tools/web_selfcheck.pycan re-check redirects, forwarded headers and security headers.
反向代理与 HTTPSReverse proxy and HTTPS
四条上线路径
Four ways to get TLS
| 路径 | 需要 | 隐私 | 适用 |
|---|---|---|---|
| A. 域名 + Caddy 自动证书 | 一个域名 + 80/443 可达 | 好(只有你自己的机器) | 推荐,一次配好长期用 |
| B. Tailscale | 两端装 Tailscale | 最好(P2P,无第三方中转内容) | 无域名,或不愿开端口 |
| C. Cloudflare 临时隧道 | 装 cloudflared | 一般(第三方可见密文与令牌流量) | 仅用于一次性验收 |
| D. 局域网 + 自签证书 | 无 | 好 | 完全离线;但必须在手机上装 CA,最麻烦 |
| Path | Requires | Privacy | Use for |
|---|---|---|---|
| A. Domain + Caddy auto-certificates | A domain + reachable 80/443 | Good (only your own machines) | Recommended; set up once, runs forever |
| B. Tailscale | Tailscale on both ends | Best (P2P, no third party relays content) | No domain, or you would rather not open ports |
| C. Cloudflare quick tunnel | cloudflared installed | Moderate (a third party sees ciphertext and token traffic) | One-off acceptance checks only |
| D. LAN + self-signed certificate | Nothing | Good | Fully offline; but the phone must install the CA — the fussiest |
cloudflared tunnel --url http://127.0.0.1:5180路径 C 会给出一个 https://<随机>.trycloudflare.com 临时域名——零配置就有可信 HTTPS,适合"只想在手机上确认能用"。Cloudflare 能看到密文、keywrap 与令牌流量,但看不到明文。临时域名公开可达,验收完立刻关掉。
Path C gives a temporary https://<random>.trycloudflare.com domain — trusted HTTPS with zero configuration, fine for "just confirm it works on my phone once". Cloudflare sees ciphertext, keywrap and token traffic, never plaintext. The temporary domain is publicly reachable — shut it down right after checking.
Caddyfile 全文
The Caddyfile, in full
仓库里只有这一份反代样例,容器与裸机共用(差别只在 NOVARA_UPSTREAM 一个环境变量)。注释保留了"为什么这么写":
The repo has exactly this one reverse-proxy sample, shared by containers and bare metal (the only difference is the NOVARA_UPSTREAM environment variable). The comments keep the "why":
{$NOVARA_DOMAIN:novara.example.com} {
encode zstd gzip
# No public hostname? Uncomment to have Caddy issue itself a certificate.
# tls internal
reverse_proxy {$NOVARA_UPSTREAM:127.0.0.1:5180} {
header_up X-Forwarded-Proto {http.request.scheme}
header_up X-Forwarded-Host {http.request.host}
}
header {
X-Content-Type-Options nosniff
X-Frame-Options DENY
Referrer-Policy no-referrer
X-Robots-Tag "noindex, nofollow, noarchive"
Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; manifest-src 'self'; worker-src 'self'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; object-src 'none'"
}
}要改的只有一处:第一行域名换成你的。header_up 两行是服务端一切绝对 URL 的依据——没有它们,/web 的跳转会指向内网监听地址;换其他反代时必须自己补上这两条转发。
Only one thing to change: the domain on the first line. The two header_up lines are the basis for every absolute URL the server emits — without them, the /web redirect would point at the internal listen address. When switching to another reverse proxy, you must reproduce these two forwarded headers.
自签证书要装 CA
Self-signed means installing the CA
局域网自签(Caddy tls internal)必须让手机信任那张根证书,否则页面不是安全上下文,crypto.subtle 根本不暴露——点"继续访问"也没用。
With LAN self-signing (Caddy tls internal) the phone must trust that root certificate; otherwise the page is not a secure context, crypto.subtle is not exposed at all — and "continue anyway" will not help.
- 根证书在 Caddy 数据目录
pki/authorities/local/root.crt(Windows 在%AppData%\Caddy\,Linux 在~/.local/share/caddy/)。 - iOS:设置 → 通用 → VPN与设备管理 安装描述文件后,还必须到「关于本机 → 证书信任设置」开启完全信任——这一步最常被漏。
- Android:设置 → 安全 → 加密与凭据 → 安装证书 → CA 证书。
- 用域名(而非 IP)访问——证书绑定的是域名。
- The root certificate lives in Caddy's data directory at
pki/authorities/local/root.crt(Windows:%AppData%\Caddy\; Linux:~/.local/share/caddy/). - iOS: after installing the profile under Settings → General → VPN & Device Management, you must also enable full trust in "About → Certificate Trust Settings" — the step most often missed.
- Android: Settings → Security → Encryption & credentials → Install a certificate → CA certificate.
- Access by domain, not IP — the certificate is bound to the domain.
如果这三步让你觉得麻烦,选路径 A 或 B。
If those steps feel like too much, pick path A or B.
TRUSTED_PROXIES:不配 = 每个请求 403
TRUSTED_PROXIES: unset = 403 on every request
反代在另一台机器上时,必须把它的单个 IP 写进 NOVARA_SYNC_TRUSTED_PROXIES(逗号分隔,不支持 CIDR)。不配的话,服务端不信任它转发的头,每个 /api 请求都会被拒绝:403,错误原文 https is required for api requests。
When the reverse proxy runs on a different machine, its single IP must be listed in NOVARA_SYNC_TRUSTED_PROXIES (comma-separated, no CIDR). Unset, the server does not trust its forwarded headers and refuses every /api request: 403, with the exact error https is required for api requests.
回环上的反代默认已信任,无需配置。Compose 部署的默认值已包含 Caddy 容器地址 172.28.0.250 与网关 172.28.0.1。服务端判定的是转发头生效之后的 scheme,所以不受信任的反代无法声称一个它没有提供的 HTTPS。
Proxies on the loopback are trusted by default, no configuration needed. The Compose deployment's default already includes the Caddy container address 172.28.0.250 and the gateway 172.28.0.1. The server judges the scheme after forwarded headers take effect, so an untrusted proxy cannot claim an HTTPS it does not actually provide.
建空间与配对Create a space and pair
为什么要单独一步
Why this is a separate step
新装的服务器上没有任何空间,桌面端的"生成令牌"无处可点。建空间是一次性的管理动作,只能用 CLI 完成;它打印的两样凭据是设备注册的唯一门禁。
A freshly installed server has no spaces, so the desktop's "issue token" has nothing to point at. Creating a space is a one-time administrative action, possible only through the CLI; the two credentials it prints are the only gate for device registration.
凭据只显示一次:服务端只存 space id 与 enrollment secret 的哈希,关掉终端就找不回。
Credentials are shown exactly once: the server stores only hashes of the space id and enrollment secret; close the terminal and they are unrecoverable.
首跑三步
The first-run three steps
- 建空间
docker compose run --rm novara-sync space create --name 我的空间(Compose 路径)或NovaraSync space create --name my-space(裸机路径)。记下 space id 与 enrollment secret。 - 起服务
docker compose --profile https up -d,或双击2-启动服务端.cmd,或直接运行NovaraSync.exe --urls http://127.0.0.1:5180。 - 配对桌面端 → 互联同步 → 配对:地址 + space id + enrollment secret,空间密钥留空(首台设备自己生成 SpaceKey)。
- Create the space
docker compose run --rm novara-sync space create --name 我的空间(Compose path) orNovaraSync space create --name my-space(bare metal). Note the space id and enrollment secret. - Start the server
docker compose --profile https up -d, or double-click2-启动服务端.cmd, or runNovaraSync.exe --urls http://127.0.0.1:5180directly. - PairDesktop → Encrypted sync → Pair: address + space id + enrollment secret, space key left empty (the first device generates its own SpaceKey).
为什么用 run --rm 而不是 exec:这一步不需要服务端在跑,run 起一个一次性容器、挂同一个 ./data、写完即退——凭据与服务端同源。
Why run --rm instead of exec: this step does not need the server running; run starts a one-off container, mounts the same ./data, writes and exits — credentials stay in one place with the server.
CLI 与服务端必须使用同一数据目录(同一个 NOVARA_SYNC_DATA 或同一工作目录),否则凭据落进另一个目录,服务器看不到这个空间。
The CLI and the server must use the same data directory (the same NOVARA_SYNC_DATA or the same working directory); otherwise the credentials land in another directory and the server never sees the space.
CLI 子命令速查
CLI subcommand reference
NovaraSync space create --name my-space
NovaraSync space list --json
NovaraSync space show <space id>
NovaraSync space rotate-secret <space id>
NovaraSync space delete <space id> --yes| 命令 | 作用 |
|---|---|
space create --name <名称> | 创建空间,打印 space id 与 enrollment secret(仅此一次) |
space list | 列出空间;--json 输出机器可读格式 |
space show <space id> | 查看单个空间信息 |
space rotate-secret <space id> | 换发 enrollment secret;旧 secret 立即失效,已配对设备不受影响 |
space delete <space id> --yes | 删除空间。不可逆;缺 --yes 时不执行并退出(退出码 2) |
| Command | Effect |
|---|---|
space create --name <name> | Creates the space; prints the space id and enrollment secret (once only) |
space list | Lists spaces; --json for machine-readable output |
space show <space id> | Shows one space's details |
space rotate-secret <space id> | Issues a new enrollment secret; the old secret dies instantly; paired devices are unaffected |
space delete <space id> --yes | Deletes the space. Irreversible; without --yes it refuses and exits (exit code 2) |
全部子命令支持 --json。退出码约定:0 成功;1 操作失败(凭据错误、空间不存在等);2 命令用法问题(如 delete 缺 --yes)。
Every subcommand supports --json. Exit codes: 0 success; 1 the operation failed (bad credentials, missing space, etc.); 2 command usage problem (like delete without --yes).
配对之后
After pairing
首台设备生成并保管 SpaceKey(弹窗展示、可在卡片里另存)。此时才轮到只读访问:生成令牌、复制链接、发到手机——见《手机只读访问》。
The first device generates and keeps the SpaceKey (shown in a dialog, savable from the card). Only now does read-only access come into play: issue a token, copy the link, send it to the phone — see "Read-only mobile access".
备份、恢复与升级Backup, restore and upgrade
两种数据卷形态
Two volume layouts
| 形态 | 特点 |
|---|---|
bind mount ./data:/data(默认) | 文件看得见、直接复制即备份;属主来自宿主机,不对时服务端拒绝启动并打印 chown 命令 |
named volume novara-data:/data | 零权限问题(Docker 用镜像内属主播种);代价是文件不在你的目录树里,备份要靠临时容器 tar |
| Layout | Traits |
|---|---|
bind mount ./data:/data (default) | Files visible; backup = copy; ownership comes from the host and, when wrong, the server refuses to start and prints the chown command |
named volume novara-data:/data | Zero permission issues (Docker seeds the image's ownership); the trade-off is files outside your directory tree — backups need a temporary container with tar |
无论哪种:数据目录必须在本机磁盘。SQLite 的 WAL 依赖共享内存与文件锁,NFS / SMB 网络盘上是数据损坏风险,不是性能问题。
Either way: the data directory must be on a local disk. SQLite's WAL depends on shared memory and file locks; on NFS / SMB network shares it is a corruption risk, not a performance issue.
备份与恢复
Backup and restore
docker compose stop novara-sync
cp -a ./data ./data-backup-$(date +%Y%m%d)
docker compose start novara-sync恢复就是反过来:停服务 → 把备份目录换回去 → 起服务。整个目录一起复制,含 novara-sync.db 与 spaces/。
Restoring is the same in reverse: stop the server → swap the backup directory back in → start. Copy the whole directory, including novara-sync.db and spaces/.
数据目录里全是密文,敏感度低于客户端本地库——但仍建议按敏感文件对待。镜像里刻意不带 sqlite3 命令行(少一个攻击面);要查库请在宿主机上用工具打开 ./data/novara-sync.db。
The data directory holds nothing but ciphertext — less sensitive than the client's local vault — but treat it as sensitive files anyway. The image deliberately ships no sqlite3 CLI (one less attack surface); to inspect the database, open ./data/novara-sync.db from the host with your own tools.
升级
Upgrading
docker compose pull
docker compose up -d- v4 容器格式与存储 schema 不变,数据天然向前兼容。
- 升级前先备份(上一节)。
- 若你的常驻形态带 Caddy(https profile),沿用与首次启动相同的
docker compose --profile https up -d形态即可。 - 回滚 = 把镜像退回旧 tag 并恢复升级前备份的数据目录。
- The v4 container format and storage schema do not change; data is forward-compatible by construction.
- Back up before upgrading (previous section).
- If your regular setup includes Caddy (https profile), keep the same
docker compose --profile https up -dform used at first start. - Rollback = move the image back to the old tag and restore the pre-upgrade data-directory backup.
升级后检查
Post-upgrade checks
docker compose ps:两个服务 running、novara-sync(healthy)。- 桌面端手动跑一轮同步,确认版本正常推进。
- 重启容器(或 NAS 重启)后数据仍在——这是验收标准,不是可选项。
docker compose ps: both services running, novara-sync(healthy).- Run one manual sync from the desktop and confirm versions advance normally.
- Restart the container (or the NAS) — the data survives. That is the acceptance bar, not an optional extra.
服务端环境变量速查Server environment variables
全表
The full table
| 变量 | 默认值 | 什么时候需要动它 |
|---|---|---|
NOVARA_SYNC_DATA | data(相对工作目录) | 想把数据放别处时。注意不要落在 NOVARA_SYNC_WEB_ROOT 之内,否则服务端拒绝启动 |
NOVARA_SYNC_WEB_ROOT | 输出目录下的 Novara.Web | 几乎不用动。指向包含数据目录的路径会被拒绝启动;站点树内含 junction/符号链接同样被拒 |
NOVARA_SYNC_ALLOWED_HOSTS | 空 = 不过滤 | 域名固定时建议填(Host 头注入兜底)。只写主机名——带端口或尾点的条目永远匹配不上,且启动时 stderr 告警 |
NOVARA_SYNC_TRUSTED_PROXIES | 空(回环默认已信任) | 反代在另一台机器上时填它的单个 IP(逗号分隔,不支持 CIDR)。不填而跨机反代 → /api 全部 403 |
NOVARA_SYNC_STORE | sqlite | 想零依赖时可选 file(JSON 存储),语义完全一致 |
NOVARA_SYNC_QUOTA_BYTES | 524288000(500 MiB) | 单空间密文较大或多人共用服务器时调整 |
NOVARA_SYNC_MAX_VERSIONS | 10 | 想保留更多历史版本时调大 |
NOVARA_SYNC_MAX_PAYLOAD_BYTES | 67108864(64 MiB) | 单次上传报 413 且确属正常数据时调大 |
NOVARA_SYNC_MAX_AUTH_FAILURES | 10 | 鉴权失败限速阈值(1 分钟窗口);一般不动 |
| Variable | Default | When you need to touch it |
|---|---|---|
NOVARA_SYNC_DATA | data (relative to the working directory) | When the data should live elsewhere. Make sure it is not inside NOVARA_SYNC_WEB_ROOT, or the server refuses to start |
NOVARA_SYNC_WEB_ROOT | Novara.Web under the output directory | Rarely touched. Pointing it at a path containing the data directory refuses to start; junctions/symlinks inside the site tree are refused too |
NOVARA_SYNC_ALLOWED_HOSTS | Empty = no filtering | Recommended with a fixed domain (a backstop against Host-header injection). Hostnames only — entries with ports or trailing dots never match, and startup warns on stderr |
NOVARA_SYNC_TRUSTED_PROXIES | Empty (loopback trusted by default) | When the reverse proxy runs on another machine: list its single IP (comma-separated, no CIDR). Cross-machine proxy without it → every /api call gets 403 |
NOVARA_SYNC_STORE | sqlite | Choose file (JSON storage) for zero dependencies; semantics identical |
NOVARA_SYNC_QUOTA_BYTES | 524288000 (500 MiB) | Adjust for larger per-space ciphertext or several people sharing a server |
NOVARA_SYNC_MAX_VERSIONS | 10 | Raise to keep more history |
NOVARA_SYNC_MAX_PAYLOAD_BYTES | 67108864 (64 MiB) | Raise when a legitimate upload returns 413 |
NOVARA_SYNC_MAX_AUTH_FAILURES | 10 | Auth-failure rate limit (1-minute window); usually untouched |
仅 Compose 部署使用
Compose deployment only
| 变量 | 默认值 | 说明 |
|---|---|---|
NOVARA_DOMAIN | (必填) | Caddy 申请证书的域名;不填 compose 直接报错 set NOVARA_DOMAIN in .env |
NOVARA_IMAGE | ghcr.io/novara-owner/novara-sync:9.1.0 | 锁定镜像用;生产建议固定 digest |
| Variable | Default | Note |
|---|---|---|
NOVARA_DOMAIN | (required) | The domain Caddy requests certificates for; unset, compose fails immediately with set NOVARA_DOMAIN in .env |
NOVARA_IMAGE | ghcr.io/novara-owner/novara-sync:9.1.0 | Pin the image; for production, pin a digest |
compose 里 NOVARA_SYNC_TRUSTED_PROXIES 的默认值已含 Caddy 容器地址 172.28.0.250 与网关 172.28.0.1,正常情况无需改动;若你在 docker-compose.yml 里改过网段,记得同步改它。
In compose, NOVARA_SYNC_TRUSTED_PROXIES already defaults to the Caddy container address 172.28.0.250 and the gateway 172.28.0.1; normally untouched. If you changed the subnet in docker-compose.yml, update it to match.
三条实用提醒
Three practical reminders
.env只被 compose 读取,裸机部署请直接设系统环境变量——两边的变量名完全一致。- 改完环境变量要重建容器(
up -d)才生效;restart不会重读 .env。 - Trusted proxies 里列出的地址可以声明请求的 scheme——只列你实际运行的反代,别的什么都不要列。
.envis read by compose only; on bare metal set system environment variables directly — the names are identical on both sides.- Environment variable changes take effect when the container is recreated (
up -d);restartdoes not re-read .env. - Addresses listed in trusted proxies may declare a request's scheme — list only the proxy you actually run, nothing else.
故障排查Troubleshooting
用之前
Before you start
- 先看现象在哪一侧:手机/浏览器上的一句提示,还是服务端启动失败/接口报错。
- 错误信息原文(如
https is required for api requests)可以直接拿去搜索,比描述现象更精确。 - 服务端问题先看容器日志:
docker compose logs novara-sync的第一行往往就是答案。
- First locate which side the symptom is on: a message on the phone/browser, or a server startup failure / API error.
- Exact error strings (like
https is required for api requests) make the best search keywords — more precise than describing the symptom. - For server problems, read the container log first: the first line of
docker compose logs novara-syncis often the answer.
手机 / 浏览器侧
Phone / browser side
| 现象 | 原因 | 处理 |
|---|---|---|
| "当前浏览器不支持所需的加密能力" | 不是安全上下文:明文 HTTP,或自签证书未被手机信任 | 用 HTTPS;自签需装 CA 并开启完全信任(iOS 最常漏) |
| "链接不完整" | URL 里没有 #s=<spaceId> 片段 | 用桌面端复制的完整链接;从主屏图标启动也会这样,是已知限制 |
| "令牌无效或已作废" | 抄错、已被重新生成或已作废 | 重新复制;I/L→1、O→0 会自动折叠,无需手工纠正 |
| "口令不正确" | 填的不是那个密码 | 是包装空间密钥的 Novara 解锁密码,与桌面端"查看空间密钥"要求输入的一致 |
| 解锁一直 429 限速 | 该空间在窗口内失败过多(1 分钟窗口,阈值 10) | 等一分钟再试;这是限速不是凭据错误,别反复重试 |
打开链接跳到 127.0.0.1 | 反代未传 X-Forwarded-Proto/Host | 用仓库内 Caddyfile;跨机反代把它的 IP 加进 NOVARA_SYNC_TRUSTED_PROXIES |
| 手机能打开但一直转圈 | 服务器关机 / 隧道断了 / 域名解析变了 | 先确认服务端进程还在,再确认通道 |
| 不能安装 PWA / manifest 报错 | 反代改写了 application/manifest+json 的 MIME | 用仓库内 Caddyfile;或跑 python Tools/web_selfcheck.py 定位 |
| Service Worker 未注册 | sw.js 的 MIME 不是 JavaScript,或缺 viewer.js 导致 cache.addAll 整体失败 | 同上 |
| Symptom | Cause | Fix |
|---|---|---|
| "this browser does not support the required encryption capability" | Not a secure context: plain HTTP, or a self-signed certificate the phone does not trust | Use HTTPS; self-signed requires installing the CA and enabling full trust (most often missed on iOS) |
| "incomplete link" | The URL has no #s=<spaceId> fragment | Use the full link copied by the desktop; launching from a home-screen icon also shows this — a known limitation |
| "token invalid or revoked" | Copied wrong, regenerated, or revoked | Copy it again; I/L→1 and O→0 fold automatically — no manual fixing needed |
| "incorrect passphrase" | What you typed is not that password | It is the Novara unlock password that wraps the space key — the same one "view space key" on the desktop asks for |
| Unlock keeps hitting 429 rate limiting | Too many failures for this space within the window (1 minute, threshold 10) | Wait a minute and retry; it is rate limiting, not a credential error — do not hammer retries |
The link opens onto 127.0.0.1 | The proxy did not forward X-Forwarded-Proto/Host | Use the repo's Caddyfile; for a cross-machine proxy, add its IP to NOVARA_SYNC_TRUSTED_PROXIES |
| The phone opens but spins forever | Server down / tunnel broken / DNS changed | Confirm the server process first, then the tunnel |
| Cannot install the PWA / manifest errors | The proxy rewrote the application/manifest+json MIME type | Use the repo's Caddyfile; or run python Tools/web_selfcheck.py to locate it |
| Service Worker not registered | sw.js MIME is not JavaScript, or a missing viewer.js makes cache.addAll fail as a whole | Same as above |
服务端 / 接口侧
Server / API side
| 现象 | 原因 | 处理 |
|---|---|---|
/api 一律 403,错误原文 https is required for api requests | 请求在服务端看来不是 HTTPS:反代没传 X-Forwarded-Proto、跨机反代没进 NOVARA_SYNC_TRUSTED_PROXIES,或明文端口直接暴露到了网络 | 补协议头 / 登记反代 IP / 不要把明文端口开到网络上 |
启动即退出,日志是 refusing to start + 数据目录不能写 | bind mount 的 ./data 属主不对(容器以 uid 1654 运行) | 按报错执行 sudo chown -R 1654:1654 ./data,或改用 named volume |
启动即退出,日志是 refusing to start + 站点目录 | NOVARA_SYNC_WEB_ROOT 指向了包含数据目录的位置,或站点树里有 junction / 符号链接——静态托管会把密文库暴露出去 | 站点目录指向纯站点目录,或把数据目录移出它;站点里的链接改为把内容搬进来 |
409 version_conflict | 两端同时修改,上传的基础版本已落后 | 正常机制:按提示导出两端 / 采用云端 / 显式强制覆盖。不是错误状态,别急着"修"它 |
507 quota_exceeded | 空间配额(默认 500 MiB)用满 | 错误体带 usedBytes / limitBytes;删旧版本或调大 NOVARA_SYNC_QUOTA_BYTES |
413 payload_too_large | 单次上传超过 64 MiB 上限 | 确属正常数据时调大 NOVARA_SYNC_MAX_PAYLOAD_BYTES |
401 unauthenticated | 令牌无效或已撤销 | 重新生成设备令牌或只读令牌;注意与 429 区分——429 是限速,401 才是凭据问题 |
直连 http://主机:5180/healthz 得到 400 | Host 过滤在工作:Host: 主机:5180 不在允许列表 | 这是预期行为。健康检查由容器内部完成;从宿主探测就带上 -H "Host: 你的域名" |
docker compose up 报 Address already in use | 固定 IP 被先占(动态分配从低地址往上走) | docker compose down 后重试;反复出现就换网段,并同步改 Caddy 的 ipv4_address 与 NOVARA_SYNC_TRUSTED_PROXIES |
容器一直 starting / unhealthy | 数据目录写不进去或端口被占;自定义 ALLOWED_HOSTS 成多段时第一段须是主机名 | docker compose logs novara-sync 看第一行 |
| Caddy 拿不到证书 | 80 端口没通到这台机器,或域名 A 记录不对 | docker compose logs caddy;确认 80/443 都可达 |
docker compose up 报 set NOVARA_DOMAIN in .env | .env 没建或没填 | cp .env.example .env 后填 NOVARA_DOMAIN |
| Symptom | Cause | Fix |
|---|---|---|
/api always 403, exact error https is required for api requests | The request does not look like HTTPS to the server: the proxy did not send X-Forwarded-Proto, a cross-machine proxy is not in NOVARA_SYNC_TRUSTED_PROXIES, or the plaintext port is exposed to the network | Add the protocol header / register the proxy IP / never expose the plaintext port |
Exits at startup with refusing to start + the data directory cannot be written | Wrong owner on the bind-mounted ./data (the container runs as uid 1654) | Run sudo chown -R 1654:1654 ./data as the error says, or switch to a named volume |
Exits at startup with refusing to start + the web root | NOVARA_SYNC_WEB_ROOT points at a location containing the data directory, or the site tree has junctions / symlinks — static serving would expose the ciphertext vault | Point the web root at a pure site directory, or move the data directory out of it; bring external content into the site directory instead of linking |
409 version_conflict | Both sides edited; the upload's base version is stale | Normal mechanism: export both versions / take the cloud / explicit force overwrite as prompted. Not an error state — do not rush to "fix" it |
507 quota_exceeded | The space quota (500 MiB by default) is used up | The body carries usedBytes / limitBytes; delete old versions or raise NOVARA_SYNC_QUOTA_BYTES |
413 payload_too_large | A single upload exceeded the 64 MiB cap | Raise NOVARA_SYNC_MAX_PAYLOAD_BYTES if the data is legitimately that large |
401 unauthenticated | The token is invalid or revoked | Reissue the device or read-only token; distinguish from 429 — 429 is rate limiting, 401 is a credential problem |
Direct http://host:5180/healthz returns 400 | Host filtering is working: Host: host:5180 is not on the allow list | Expected behavior. Health checks run inside the container; from the host, probe with -H "Host: your-domain" |
docker compose up says Address already in use | The fixed IP is taken (dynamic allocation walks upward from low addresses) | docker compose down then retry; if it recurs, change the subnet and update Caddy's ipv4_address and NOVARA_SYNC_TRUSTED_PROXIES together |
Container stuck starting / unhealthy | The data directory is unwritable or the port is taken; a multi-entry custom ALLOWED_HOSTS must list the hostname first | docker compose logs novara-sync — read the first line |
| Caddy cannot obtain certificates | Port 80 does not reach this machine, or the domain's A record is wrong | docker compose logs caddy; confirm both 80/443 are reachable |
docker compose up says set NOVARA_DOMAIN in .env | .env missing or unfilled | cp .env.example .env and fill NOVARA_DOMAIN |
桌面端侧
Desktop side
| 现象 | 原因 | 处理 |
|---|---|---|
| 已配对但同步不动 | 同步总开关没开 | 打开总开关;或点「立即同步」手动跑一轮 |
| 忘了空间密钥 | 服务端只有密文 | 在创建它的设备上「查看空间密钥」,或导入 .novakey 备份取回 |
| 某台设备丢了 | — | 在「设备中心」撤销;撤销后该设备立即失去同步与读取 |
| 锁定期间同步停了 | 锁定期禁网是硬规则 | 正常现象;解锁后自动恢复 |
| Symptom | Cause | Fix |
|---|---|---|
| Paired but sync does not move | The sync master switch is off | Turn it on; or click "Sync now" for a manual round |
| Forgot the space key | The server holds only ciphertext | "View space key" on the device that created it, or import a .novakey backup |
| A device was lost | — | Revoke it in the device center; revocation immediately cuts its sync and read access |
| Sync paused while locked | No network while locked is a hard rule | Normal; it resumes automatically after unlocking |
版本与升级(服务端)Versions and upgrades (server)
docker compose stop novara-sync
cp -a ./data ./data-backup-$(date +%Y%m%d)
docker compose pull
docker compose up -d- v4 容器格式与存储 schema 不变,数据天然向前兼容;升级前先备份。
- Windows 直跑路径:用新版安装包覆盖安装后重新启动
2-启动服务端.cmd,数据目录不动。 - 旧版桌面端与新服务端之间没有强绑定——契约与容器格式未变,混跑一个过渡期是安全的。
- 回滚 = 镜像退回旧 tag 并恢复升级前备份的数据目录。
- The v4 container format and storage schema are unchanged, so data is forward-compatible by construction; still, back up before upgrading.
- Windows direct-run path: install the new build over the old one and restart
2-启动服务端.cmd; the data directory is untouched. - There is no hard binding between an older desktop and a newer server — the contract and container format are unchanged, so a mixed transition period is safe.
- Rollback = move the image back to the old tag and restore the pre-upgrade data-directory backup.
常见问题FAQ
需要用固定 IP 吗?
不需要。用域名(Caddy 自动证书)或 Tailscale 都可以,家里宽带 IP 变化不影响。
有 Docker / NAS 版服务端吗?
9.0 起有:Docker Compose、群晖、威联通、Ubuntu VPS 与纯二进制都是当前版本能力,见本篇各节。
部署完第一步做什么?
建空间 → 配对(见《建空间与配对》)→ 生成手机凭据(见互联同步指南《手机只读访问》)。
Do I need a fixed IP?
No. A domain (Caddy auto-certificates) or Tailscale both work; home broadband IP changes do not matter.
Is there a Docker / NAS server?
Since 9.0 there is: Docker Compose, Synology, QNAP, Ubuntu VPS and the plain binary are all current-version capabilities — see the sections in this guide.
First thing after deployment?
Create the space → pair (see "Create a space and pair") → issue phone credentials (see "Read-only mobile access" in the sync guide).
继续阅读Keep reading
- What to do after deployment (pairing, phone access, conflicts) → the encrypted sync guide
- Quick jumps on this page: pick a deployment · troubleshooting · environment variables