Skip to content

部署 ​

本文介绍如何安装 ProjectWikit、首次启动、创建首个站点与管理员、通过 HTTPS 在域名上提供站点,以及将 pwikit 作为系统服务运行。全部设置见配置,全部命令见命令行。

运行要求 ​

项目用途
Windows(amd64)、Linux(amd64 或 arm64)或 macOS(amd64 或 arm64)运行 pwikit
用于页面的域名,以及可选的另一个用于上传文件的域名,其 DNS 记录指向本机通过 HTTPS 公开访问
可从互联网访问的 TCP 80 与 443 端口自动获取 HTTPS 证书
glibc 2.28 或更高版本(RHEL 8、Debian 10、Ubuntu 20.04 及更新的发行版)在 Linux 上运行 pwikit
systemd在 Linux 上将 pwikit 安装为服务
PostgreSQL 14 或更高版本仅在不使用内置 PostgreSQL、改用自有数据库时需要

获取 pwikit ​

使用安装脚本 ​

安装脚本下载适合本机的发布包,校验 sha256,将 pwikit 放入安装目录,并使 pwikit 可以在任意目录直接输入。它不创建站点,也不安装服务。

在 Linux 与 macOS 上:

sh
curl -fsSL https://github.com/WikitTeam/ProjectWikit/releases/latest/download/install.sh | sh

在 Windows 的 PowerShell 中:

powershell
irm https://github.com/WikitTeam/ProjectWikit/releases/latest/download/install.ps1 | iex

安装脚本安装到当前目录,该目录必须为空。请先为实例创建一个目录,进入该目录后再执行脚本。

安装目录归执行脚本的账户所有;通过 sudo 执行时归执行 sudo 的账户所有;在 Linux 上以 root 登录执行时归 root 所有,参见以 root 身份运行。

install.sh 的参数写在 sh -s -- 之后:

sh
curl -fsSL https://github.com/WikitTeam/ProjectWikit/releases/latest/download/install.sh | sudo sh -s -- --dir /srv/wiki
参数说明
--version <vX.Y.Z>安装指定版本,默认为最新版本
--dir <目录>安装到指定目录而不是当前目录。目录必须不存在或为空
--mirror <地址>GitHub 无法访问时使用的镜像。同时写入 pwikit.toml,之后的自动更新也使用该镜像
--user <账户>以 root 身份执行时,安装目录的所有者。默认为执行 sudo 的账户;以 root 登录执行时,目录归 root 所有。在 macOS 上以 root 身份执行时必须指定
--no-path不使 pwikit 可以在任意目录直接输入

install.ps1 通过管道交给 iex 执行时,从环境变量 PWIKIT_VERSION、PWIKIT_DIR、PWIKIT_MIRROR 与 PWIKIT_NO_PATH 读取相同的选项;保存为文件后,也可以使用 -Version、-Dir、-Mirror 与 -NoPath 参数。

无法访问 GitHub 时,改从镜像获取安装脚本。镜像的地址结构与 GitHub Releases 相同,把 https://github.com/WikitTeam/ProjectWikit/releases 换成镜像地址即可:

sh
curl -fsSL https://wikit.unitreaty.org/projwikit/update/latest/download/install.sh | sh
powershell
irm https://wikit.unitreaty.org/projwikit/update/latest/download/install.ps1 | iex

从镜像获取的安装脚本直接从该镜像下载,并将镜像地址写入 pwikit.toml,之后的自动更新在 GitHub 无法访问时使用该镜像。https://wikit.unitreaty.org/projwikit/update 是 ProjectWikit 维护者提供的镜像,供中国大陆等无法稳定访问 GitHub 的服务器使用。发布不做签名,请只使用您信任的镜像,见下载源与镜像。

手动下载 ​

从 GitHub Releases 下载适合本机的发布包,并与同一版本的 SHA256SUMS 核对:

系统发布包
Linux(amd64 / arm64)pwikit-<版本>-linux-amd64.tar.gz / pwikit-<版本>-linux-arm64.tar.gz
macOS(Intel / Apple 芯片)pwikit-<版本>-darwin-amd64.tar.gz / pwikit-<版本>-darwin-arm64.tar.gz
Windowspwikit-<版本>-windows-amd64.zip

解压得到的目录包含 pwikit、LICENSE 与 NOTICE(第三方组件的版权与许可声明)。

macOS 上的发布包没有签名。通过浏览器下载时,macOS 会阻止运行,请在解压后执行一次:

sh
xattr -d com.apple.quarantine pwikit

通过 curl 或安装脚本下载的文件不受此限制。

可执行文件与数据目录 ​

pwikit 是单个可执行文件:Linux 与 macOS 上为 pwikit,Windows 上为 pwikit.exe。将其放入实例用于保存数据的目录,例如 /opt/pwikit 或 C:\pwikit。本文的示例均在该目录中以 ./pwikit 执行命令。在 Windows 上,请将示例中的 ./pwikit 替换为 .\pwikit.exe。仅在以系统服务方式安装或执行 pwikit path install 之后,才能在任意目录直接输入 pwikit,见直接使用 pwikit 命令。

默认情况下,pwikit 将全部数据保存在可执行文件所在的目录中。通过符号链接启动时,使用链接所指向文件的目录。该目录中的内容如下:

条目内容
pwikit.toml设置文件。首次启动时写入一份带注释的模板。见配置。
files/上传到各站点的文件。
archive/创建时为空。可在导入前存放 wikitCLI 备份;pwikit import 未指定其他目录时读取该目录。
secrets/pwikit 生成的密钥与证书。请勿公开该目录。
postgres/内置 PostgreSQL 的程序文件,首次启动时解压。
pgdata/内置 PostgreSQL 的数据库。
logs/PostgreSQL 日志;在 Windows 或 macOS 上作为服务运行时,也包含 pwikit 自身的日志。
backups/pwikit backup create 写入的备份。见运维。

postgres/ 与 pgdata/ 仅在使用内置 PostgreSQL 时存在。

如需将数据保存在其他位置,请为每条命令指定 -data-dir <目录>,或设置环境变量 PWIKIT_DATA_DIR。命令行参数优先于环境变量。所有命令必须使用同一个数据目录,否则会读取到不同的设置与数据库。

页面静态资源 ​

页面所用的样式表、脚本、字体与图片已内置于 pwikit,无需单独的目录。-static-dir <目录> 改为从指定目录提供这些文件,而不使用内置的副本,仅在修改网页界面时使用。该参数只能在命令行中指定,无法写入 pwikit.toml。

首次启动 ​

启动服务器:

sh
./pwikit serve

在 macOS 上,请使用普通账户启动 pwikit。内置 PostgreSQL 不以 root 身份运行。

以 root 身份运行 ​

在 Linux 上,pwikit 也可以以 root 身份运行。PostgreSQL 本身仍然拒绝以 root 身份运行,因此 pwikit 会以另一个账户启动它:

  • 若 pgdata/ 或数据目录归非 root 账户所有,使用该账户;
  • 否则使用名为 pwikit 的系统账户,首次启动时若不存在则自动创建。

该账户拥有 pgdata/ 与 PostgreSQL 的日志文件,数据目录中的其余内容仍归 root 所有。数据目录的每一级上级目录都必须允许该账户进入,因此位于 /root 下的数据目录无法使用,pwikit 会中止并说明原因。请改为安装在 /opt 或 /srv 下。

以专用的普通账户运行 ​

在 Linux 上,也可以专门创建一个普通账户来运行 pwikit。pwikit 与内置 PostgreSQL 都以该账户运行,整个数据目录归它所有,pwikit 不持有 root 权限。

  1. 创建账户与数据目录,并以该账户获取 pwikit:

    sh
    sudo useradd --system --home-dir /srv/pwikit --shell /usr/sbin/nologin pwikit
    sudo mkdir /srv/pwikit && sudo chown pwikit: /srv/pwikit
    cd /srv/pwikit
    curl -fsSL https://github.com/WikitTeam/ProjectWikit/releases/latest/download/install.sh | sudo -u pwikit sh

    自行解压发布包时,将全部文件放入 /srv/pwikit 后执行 sudo chown -R pwikit: /srv/pwikit。

  2. 以该账户创建站点与管理员。需要导入 Wikidot 站点时,同样以该账户在创建管理员之前导入:

    sh
    sudo -u pwikit ./pwikit createsite -slug main -domain wiki.example.org -title "我的维基" -headline "维基副标题"
    sudo -u pwikit ./pwikit admin create -name "Site Admin"
  3. 安装系统服务,并用 -user 指定该账户。服务以该账户运行,并获准监听 80 与 443 端口:

    sh
    sudo ./pwikit service install -user pwikit

之后请继续以该账户执行 pwikit 命令,例如 sudo -u pwikit pwikit backup create。普通账户在终端中直接运行 pwikit serve 时无法监听 80 与 443 端口,见无法监听 80 或 443 端口。

首次启动时,pwikit 写入 pwikit.toml 并初始化内置 PostgreSQL,因此明显慢于之后的启动。之后每次启动时,pwikit 将自动应用新版本带来的数据库变更。

启动进度会写入日志;未指定 -log-file 时,日志输出到标准错误。在创建站点之前,访问任何地址都会显示 站点不存在 页面,说明该地址未绑定站点。

内置 PostgreSQL 只接受来自本机的连接。在 Linux 与 macOS 上,它使用套接字文件,不开放任何网络端口。在 Windows 上,它仅监听 127.0.0.1。因此内置 PostgreSQL 无需更改防火墙。它从不使用 5432 端口。如果已有其他 PostgreSQL 监听 5432 端口,pwikit 会输出一条提示,说明如何改用该服务器,且不会对其进行任何操作。

按 Ctrl+C 即可停止 pwikit。pwikit 会在退出前停止其 PostgreSQL。如果 pwikit 被强行终止,下次启动时会先停止上次遗留的 PostgreSQL。

createsite、admin 等其他命令使用同一个数据库。pwikit serve 运行期间,这些命令连接到它的 PostgreSQL;否则,它们会在自身运行期间启动内置 PostgreSQL。在 Linux 与 macOS 上,请使用与 pwikit serve 相同的账户执行这些命令。

创建首个站点与管理员 ​

数据库表尚不存在时,createsite 会自行创建。若 pwikit serve 正在运行,请保持其运行,另开一个终端。

  1. 创建站点:

    sh
    ./pwikit createsite -slug main -title "My Wiki" -headline "A Wikidot-compatible wiki" \
      -domain wiki.example.org -media-domain files.example.org
    参数含义
    -slug站点标识名,可包含字母、数字、- 与 _。命令通过它指定站点。
    -title站点标题。
    -headline站点副标题。
    -domain提供页面的主机名,不含 https:// 与路径。
    -media-domain提供上传文件的主机名,默认与 -domain 相同。使用单独的主机名,可将上传的 HTML 文件与站点自身的页面隔离。

    请将示例中的名称替换为您自己的名称。example.org 下的名称为保留名称,永远不会启用自动 HTTPS。如需在本机试用 pwikit,请使用 -domain localhost,并访问 http://localhost:8080。

  2. 添加内容。可以使用 pwikit seed 写入初始页面(见命令行),也可以按照从 Wikidot 导入导入 Wikidot 站点。请在创建管理员之前导入:这样管理员可以接管导入的账号,以及该账号编写的页面与帖子。

  3. 创建管理员:

    sh
    ./pwikit admin create -name "YourName"

    如果不存在该名称的账号,pwikit 会在创建新账号前请求确认。随后以不回显的方式要求输入密码。该账号在本实例的所有站点上拥有全部权限。

  4. 如果站点的域名是公网域名,请重新启动 pwikit serve(按 Ctrl+C 后再次启动),使其切换到 HTTPS。此时 createsite 会输出相应提示。见下文「域名与 HTTPS」。

在站点域名的 /-/login 登录。管理后台位于 /-/admin,在各页面顶部的账号链接中显示为 管理面板。见站点管理。

域名与 HTTPS ​

自动 HTTPS ​

如果以下各项均未配置,pwikit 会在启动时决定是否提供 HTTPS:

  • HTTPS 模式(-tls、PWIKIT_TLS 或 [tls] 中的 mode)
  • 监听地址(-listen 或 [server] 中的 listen)
  • 可信代理(-trusted-proxies 或 [server] 中的 trusted_proxies)

只要有一个站点的域名或文件域名是公网域名,pwikit 就会监听 80 与 443 端口,并从 Let's Encrypt 获取证书。否则,它在 127.0.0.1:8080 上提供纯 HTTP。

以下名称不属于公网域名,永远不会启用 HTTPS:

  • IP 地址,以及包含端口的名称
  • 不含点号的名称,例如 wiki
  • localhost、localdomain、local、test、example、invalid、internal、lan、home.arpa、example.com、example.net 与 example.org,以及以它们结尾的所有名称(例如 wiki.test 或 files.example.org)

启用自动 HTTPS 后:

  • 某个名称的第一个 HTTPS 请求到达时才申请证书,因此首次访问每个名称时速度较慢。pwikit 会在证书到期前自动续期。
  • 只为本实例上各站点的域名与文件域名签发证书。针对其他任何名称的 HTTPS 请求(包括本机 IP 地址)一律拒绝。
  • 80 端口将请求重定向到 HTTPS,并响应证书颁发机构的验证请求。
  • 证书保存在 secrets/certs 中。
  • 使用 Let's Encrypt 即表示接受其订阅者协议。

首次以 HTTPS 启动前,请确认域名与文件域名的 DNS 记录均指向本机,且 80 与 443 端口可从互联网访问。

HTTP 与 HTTPS 的选择在启动时进行。实例以纯 HTTP 运行时绑定了公网域名,须重新启动 pwikit。pwikit 已提供 HTTPS 后,之后绑定的域名无需重启即可获得证书。

如需向证书颁发机构登记联系地址,请在 [tls] 中设置 acme_email。如需先获取测试证书,请将 acme_directory 设置为 Let's Encrypt 测试环境目录 https://acme-staging-v02.api.letsencrypt.org/directory。浏览器不信任测试证书。切换回正式环境前,请删除 secrets/certs,否则将继续使用测试证书。

使用自有证书 ​

如需使用自行获取的证书,请将模式设置为 file:

toml
[tls]
mode = "file"
cert = "/etc/ssl/wiki/fullchain.pem"
key = "/etc/ssl/wiki/privkey.pem"

pwikit 监听 80 端口(重定向到 HTTPS)与 443 端口。所有名称均使用同一张证书,因此该证书必须覆盖每个站点的域名与文件域名。两个文件均为 PEM 格式;cert 包含完整的证书链。

续期时替换这两个文件即可。pwikit 会在约一分钟内察觉变更,无需重启。如果新文件无法加载,pwikit 会记录错误并继续使用原有证书。如果启动时无法加载证书文件,pwikit 不会启动。

置于反向代理之后 ​

由 nginx 等其他 Web 服务器在 pwikit 前端处理 HTTPS 时,请设置可信代理。这会停用自动 HTTPS;除非 listen 另有指定,pwikit 在 127.0.0.1:8080 上提供纯 HTTP:

toml
[server]
listen = "127.0.0.1:8080"
trusted_proxies = ["127.0.0.1", "::1"]

反向代理必须:

  • 原样传递 Host 请求头,因为 pwikit 根据主机名选择站点;
  • 设置 X-Forwarded-For 与 X-Forwarded-Proto。

pwikit 只接受来自 trusted_proxies 中地址的 X-Forwarded-For 与 X-Forwarded-Proto。如果未列出代理的地址,所有访客看起来都来自该代理,且即使访客使用 HTTPS,邮件中的链接也以 http:// 开头。最简 nginx 配置如下:

nginx
server {
    listen 443 ssl;
    server_name wiki.example.org files.example.org;
    ssl_certificate     /etc/ssl/wiki/fullchain.pem;
    ssl_certificate_key /etc/ssl/wiki/privkey.pem;
    client_max_body_size 100m;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

client_max_body_size 用于放宽 nginx 自身的请求大小限制,否则较大的上传会被拦截。

使用 Cloudflare ​

DNS 记录开启 Cloudflare 代理(橙色云朵)时,Cloudflare 位于访客与 pwikit 之间。pwikit 仍可使用自动 HTTPS,但须注意以下几点。

SSL/TLS 加密模式必须为「完全(严格)」。 在「灵活」模式下,Cloudflare 通过 HTTP 连接 pwikit 的 80 端口,而 pwikit 会将该请求重定向到 HTTPS,浏览器因此陷入循环,报错「重定向次数过多」(ERR_TOO_MANY_REDIRECTS)。在「完全(严格)」模式下,Cloudflare 连接 443 端口并校验 pwikit 从 Let's Encrypt 获取的证书。

只对 pwikit 的名称设置加密模式。 如果同一 Cloudflare 域名下的其他网站只能使用「灵活」模式,无需更改全局设置。可以在 Cloudflare 中添加一条规则,仅将 pwikit 站点的域名与文件域名的加密模式设为「完全(严格)」。

首次获取证书。 证书颁发机构通过 80 端口验证域名,该请求可经 Cloudflare 转发到 pwikit,因此无需关闭代理。如果切换到「完全(严格)」后页面报错 525 或 526,说明 pwikit 尚未取得证书。此时可暂时将 DNS 记录改为「仅 DNS」(灰色云朵),通过域名访问一次站点,待 pwikit 取得证书后再开启代理。

访客地址。 开启代理后,所有请求都来自 Cloudflare 的地址。如需在日志、封禁和登录记录中看到访客的真实地址,请将 Cloudflare 的地址段列为可信代理,并显式设置 HTTPS 模式,否则设置可信代理会停用自动 HTTPS:

toml
[tls]
mode = "auto"

[server]
trusted_proxies = [
  "173.245.48.0/20", "103.21.244.0/22", "103.22.200.0/22", "103.31.4.0/22",
  "141.101.64.0/18", "108.162.192.0/18", "190.93.240.0/20", "188.114.96.0/20",
  "197.234.240.0/22", "198.41.128.0/17", "162.158.0.0/15", "104.16.0.0/13",
  "104.24.0.0/14", "172.64.0.0/13", "131.0.72.0/22",
  "2400:cb00::/32", "2606:4700::/32", "2803:f800::/32", "2405:b500::/32",
  "2405:8100::/32", "2a06:98c0::/29", "2c0f:f248::/32",
]

以上地址段取自 https://www.cloudflare.com/ips/。Cloudflare 偶尔会增加地址段,请以该页面为准。

更改域名 ​

在管理后台的 站点设置 中更改域名与文件域名(字段为 文章域名 与 文件域名),详见站点管理。如果无法通过已保存的域名访问管理后台,请使用 pwikit site rebind,详见命令行。省略 -media-domain 时,site rebind 会将文件域名设为与域名相同。

以系统服务方式运行 ​

pwikit service install 将 pwikit 注册为开机自动启动,并立即启动。-- 之后的所有内容都会传递给 pwikit serve:

sh
sudo ./pwikit service install -- -upload-limit 20GB
  • 服务运行安装时所在位置的可执行文件。之后移动 pwikit 需要重新注册,见搬迁实例。
  • 安装还会让 pwikit 可以在任意目录直接执行,见直接使用 pwikit 命令。加 -no-path 可跳过。
  • 安装还会注册检查与安装新版本的计划任务,见更新与回档。
  • 安装时生效的数据目录会写入服务。
  • 环境变量不会传递给服务。请将设置写入 pwikit.toml,或放在 -- 之后。
  • 安装时会检查 -- 之后的参数并读取 pwikit.toml,任一处有误都会中止安装。
  • pwikit service print 显示安装将注册的内容,但不进行注册。
  • 如需在同一台机器上安装第二个实例,请为其使用单独的数据目录与端口,并通过 -name 指定不同的名称。

服务的启动、停止、状态查看与卸载见运维。

Linux ​

使用 sudo 执行安装。机器必须使用 systemd。

  • 服务以执行 sudo 的账户运行,或以 -user 指定的账户运行。由 root 安装且两者都未指定时,服务以 root 身份运行,内置 PostgreSQL 的运行方式见以 root 身份运行。
  • 数据目录,以及已存在的 pgdata/,必须属于该账户。数据目录的每一级上级目录都必须允许该账户访问,因此位于 /root 下的数据目录无法使用。出现上述任一问题时,安装会中止并说明解决方法,例如执行 sudo chown -R wiki: /opt/pwikit。
  • 服务发生故障后自动重启,并获准监听 80 与 443 端口。
  • 日志写入系统日志(journal),可通过 journalctl -u pwikit -f 持续查看。
  • 请以服务账户执行其他 pwikit 命令,例如 sudo -u wiki ./pwikit createsite ...。

macOS ​

  • 使用 sudo 安装时,pwikit 作为启动守护进程(LaunchDaemon)安装到 /Library/LaunchDaemons。它在开机时启动,并以执行 sudo 的账户或 -user 指定的账户运行。
  • 不使用 sudo 安装时,pwikit 作为启动代理(LaunchAgent)安装到 ~/Library/LaunchAgents。它在您登录时启动,无人登录时无法启动。
  • 使用 sudo 安装的服务须通过 sudo 管理,未使用 sudo 安装的服务则不使用 sudo 管理。
  • 日志为 logs/pwikit.log,崩溃输出写入 logs/pwikit-stderr.log。

Windows ​

在通过以管理员身份运行打开的终端中执行安装:

powershell
.\pwikit.exe service install
  • 服务以虚拟账户 NT SERVICE\pwikit 运行,该账户将获得数据目录的修改权限。
  • 日志为 logs\pwikit.log。服务因错误停止时,错误还会记录到 Windows 事件日志中。

安装时对防火墙的更改 ​

系统更改
Linux如果 firewalld 或 ufw 处于启用状态,安装会开放 pwikit 所监听、尚未开放的 TCP 端口。卸载时只关闭安装时开放的端口。
macOS使用 sudo 安装且应用程序防火墙已开启时,放行 pwikit。卸载时移除。
Windows添加名为 ProjectWikit 的入站规则,在所有网络配置文件下允许连接到 pwikit。卸载时删除。无法添加规则时,安装会输出警告并继续。

在 Linux 上,端口根据 -- 之后的参数与 pwikit.toml 推算。如果 HTTPS 模式、监听地址与可信代理均未设置,安装会开放 80 与 443 端口,因为此时尚无法判断是否绑定了公网域名。位于 127.0.0.1、::1 或 localhost 上的地址从不开放。更改端口后,请重新安装服务以更新防火墙。

本机以外的防火墙,例如云服务商的安全组或路由器,不会被更改。

直接使用 pwikit 命令 ​

只有完成以下任一操作后,才能在任意目录直接输入 pwikit。 在此之前,请在 pwikit 所在的目录中以 ./pwikit 执行命令(Windows 为 .\pwikit.exe)。Linux 与 macOS 仅在 PATH 中查找命令,当前目录不在其中。

  • 执行 pwikit service install。安装服务时默认一并完成此设置,加 -no-path 可跳过。
  • 执行 pwikit path install。适用于不以系统服务方式运行的实例。

Windows 上完成后请重新打开终端。通过 pwikit 执行的命令仍使用可执行文件所在的数据目录,与在哪个目录中执行无关。各系统上的具体更改与 path 的其他子命令见命令行。

搬迁实例 ​

实例的全部内容都在数据目录中:可执行文件、数据库、上传文件、密钥与配置。更换磁盘、更换路径或重命名文件夹,都是移动这一个目录。

系统服务与 pwikit 命令记录的都是绝对路径,搬迁后必须重新注册,否则服务无法启动。

  1. 停止并注销服务。这一步同时移除 pwikit 命令:

    sh
    sudo pwikit service uninstall
  2. 移动数据目录。移动时 pwikit 必须处于停止状态。

  3. 进入新位置,重新注册服务。这一步同时重新建立 pwikit 命令:

    sh
    sudo ./pwikit service install
  4. 未以系统服务方式运行的实例,只需在新位置执行:

    sh
    ./pwikit path install
  • 注册服务时 -- 之后写过的参数不会保留,请在第 3 步中重新写上。
  • 在 Linux 上,新目录及其每一级上级目录都必须允许服务账户访问,要求与首次安装相同。
  • 如果移动前忘记注销,pwikit 命令此时已经失效。请在新位置先执行 sudo ./pwikit service uninstall,再执行第 3 步;指向旧位置的失效链接会被自动替换。未以系统服务方式运行的实例直接执行第 4 步即可。
  • 在 Windows 上,请在以管理员身份运行的终端中执行上述命令,完成后重新打开终端。
  • 使用 -data-dir 把数据放在可执行文件之外的,移动数据后请在第 3 步中指定新的 -data-dir。

使用 Docker ​

ProjectWikit 同时以容器镜像 ghcr.io/wikitteam/pwikit 发布。镜像不含 PostgreSQL,仓库中的 docker/compose.yaml 会同时运行官方 PostgreSQL 镜像。首次启动时自动生成随机的数据库密码,保存在 secrets 卷中,不需要编辑任何文件:

sh
curl -fsSLO https://raw.githubusercontent.com/WikitTeam/ProjectWikit/main/docker/compose.yaml
docker compose up -d

pwikit 在主机的 8080 端口上提供纯 HTTP。创建站点与管理员:

sh
docker compose run --rm pwikit createsite -slug main -title "我的维基" -headline "维基副标题" -domain wiki.example.org -media-domain files.example.org
docker compose run --rm pwikit admin create -name "您的用户名"
docker compose run --rm pwikit seed
docker compose restart pwikit
卷内容
datapwikit 的数据目录:pwikit.toml、files/、secrets/、logs/、backups/
pgdataPostgreSQL 的数据库
secrets数据库密码
  • 设置写入 data 卷中的 pwikit.toml,或在 compose.yaml 的 environment 中以环境变量指定,见配置。
  • 端口通过环境变量 PWIKIT_PORT 更改,例如 PWIKIT_PORT=9000 docker compose up -d。
  • 容器中的 pwikit 不负责 HTTPS,请在前面放置反向代理,并按置于反向代理之后设置 trusted_proxies。
  • 容器中的 pwikit 不会自动更新。更新时执行 docker compose pull 与 docker compose up -d;新版本启动时自动应用数据库迁移。
  • 备份使用 docker compose run --rm pwikit backup create 等命令,备份写入 data 卷中的 backups/。

自行构建镜像:

sh
docker build -t pwikit --build-arg VERSION=v1.0.0 .
PWIKIT_IMAGE=pwikit docker compose -f docker/compose.yaml up -d

使用自有 PostgreSQL ​

如需使用自行运行的 PostgreSQL 服务器,请通过以下任一方式为 pwikit 指定连接字符串(按顺序,先找到者生效):

  1. -database 参数
  2. DATABASE_URL 环境变量
  3. pwikit.toml 中的 database
toml
database = "postgres://pwikit:password@127.0.0.1:5432/pwikit"

密码中的特殊字符须进行百分号编码。pwikit.toml 中的设置同样适用于其他命令与系统服务。

要求:

  • PostgreSQL 14 或更高版本。服务器版本过低时,pwikit 拒绝启动,并说明如何迁移数据。
  • 数据库必须已存在,pwikit 不会创建数据库。首次启动时,pwikit 会创建数据表以及 citext 与 pg_trgm 扩展。这两个扩展属于 PostgreSQL 标准 contrib 模块,部分 Linux 发行版将其单独打包。
  • pwikit 所用的数据库账户必须有权创建数据表与上述扩展。将该账户设为数据库的所有者即可:
sql
CREATE ROLE pwikit LOGIN PASSWORD 'change-me';
CREATE DATABASE pwikit OWNER pwikit ENCODING 'UTF8' TEMPLATE template0;

使用自有数据库时,pwikit 不会创建 postgres/ 与 pgdata/。

如需迁移 Python 版 ProjectWikit 的现有安装,请参阅从 Python 版迁移。

邮件 ​

pwikit 在以下场合发送邮件:邮箱地址验证、邮箱地址变更、密码重置、密码修改通知,以及从管理后台发出的邀请。在配置邮件服务器之前,这些邮件会写入日志而不会发出。这些邮件中的链接由站点域名与触发该邮件的请求所用的协议组成。当 pwikit 提供 HTTPS,或 trusted_proxies 中列出的代理在 X-Forwarded-Proto 中报告 HTTPS 时,链接以 https:// 开头;否则以 http:// 开头。在相同条件下,登录 cookie 仅通过 HTTPS 连接发送。

在 pwikit.toml 的 [mail] 节中配置邮件服务器:

toml
[mail]
host = "smtp.example.net"
port = 587
username = "wiki@example.net"
password = "..."
use_tls = true
from = "wiki@example.net"

全部邮件设置见配置。

开发模式 ​

如需在本机试用 pwikit,请以开发模式启动:

sh
./pwikit serve -dev

在开发模式下,pwikit:

  • 在 127.0.0.1:8080 上提供纯 HTTP,即使有站点绑定了公网域名;
  • 忽略 pwikit.toml 与环境变量中的 HTTPS 模式、监听地址与可信代理;
  • 照常应用其他所有设置,例如数据库与邮件。

如需使用其他端口,请通过 -listen 指定:-listen 9000 与 -listen :9000 均监听 127.0.0.1:9000。其他机器可访问的地址(例如 0.0.0.0:9000)会被拒绝,-tls=auto 与 -tls=file 同样会被拒绝。

pwikit 根据浏览器地址栏中的主机名选择站点,因此在开发模式下,只能通过解析到本机的名称(例如 localhost)访问站点。

故障排查 ​

错误信息以 pwikit: 为前缀输出。

内置 PostgreSQL 拒绝以 root 身份运行 ​

text
pwikit: the bundled PostgreSQL will not run as root.

此问题出现在 macOS 上。请使用普通账户启动 pwikit。如需开机自动运行,请使用 sudo 将其安装为服务;服务以执行 sudo 的账户运行。安装服务后,请通过 sudo -u <账户> 以服务账户执行其他命令。

内置 PostgreSQL 无法进入数据目录 ​

text
pwikit: the bundled PostgreSQL runs as pwikit, which cannot enter /root.

在 Linux 上以 root 身份运行时,pwikit 会以另一个账户启动 PostgreSQL,该账户无法进入 /root 这类不对其他账户开放的目录。请将 pwikit 所在目录移到 /opt 或 /srv 下,然后重新启动。参见以 root 身份运行。

pgdata/ 中的数据由其他 PostgreSQL 版本写入 ​

text
pwikit: the data in pgdata/ was written by PostgreSQL 17, and this pwikit carries PostgreSQL 18.

当前启动的 pwikit 所带的 PostgreSQL 主版本与创建该数据库的版本不同。pwikit 未启动任何程序,也未进行任何更改。请按照信息中的三个步骤操作:使用原先的 pwikit 创建备份;将 pgdata/ 移到别处并启动新的 pwikit;然后恢复备份。见运维。

无法监听 80 或 443 端口 ​

text
pwikit: listen on :80 for http: listen tcp :80: bind: permission denied. Grant the binary CAP_NET_BIND_SERVICE, ...

在 Linux 上,普通账户无法监听 1024 以下的端口。可采用以下任一方法:

  • 将 pwikit 安装为系统服务,服务有权使用这些端口。
  • 允许该可执行文件使用这些端口:sudo setcap cap_net_bind_service=+ep ./pwikit。替换可执行文件后须重新执行。
  • 按「置于反向代理之后」所述,将 pwikit 置于反向代理之后。

端口已被占用 ​

text
pwikit: listen on :443 for https: listen tcp :443: bind: address already in use

信息的后半部分因操作系统而异。另一个程序(通常是 Web 服务器或另一个 pwikit)正在使用该端口。请停止该程序,或按「置于反向代理之后」所述,将 pwikit 置于其后。

内置 PostgreSQL 已被占用 ​

text
pwikit: pwikit serve, process 1234, is already running the bundled PostgreSQL in this directory
pwikit: a PostgreSQL from /usr/lib/postgresql/18/bin/postgres is running on /opt/pwikit/pgdata as process 1234. Stop it before starting pwikit

同一时间仅能有一个程序使用数据目录中的内置 PostgreSQL。请先停止正在运行的 pwikit serve,或停止正在使用 pgdata/ 的其他 PostgreSQL,然后重新启动 pwikit。

  • 信息中为 another pwikit command 时,说明 backup 等命令仍在运行,请等待其完成。
  • 信息为 pwikit serve holds the bundled PostgreSQL but it is not ready yet 时,说明 pwikit serve 仍在启动中,请稍后重新执行命令。
  • 信息表明 pgdata holds files but no PostgreSQL data 时,请将其中的文件移到别处,然后重新启动 pwikit。

pwikit.toml 含有无法识别的设置 ​

text
pwikit: /opt/pwikit/pwikit.toml has settings pwikit does not know: server.lisen

pwikit.toml 中的某个键拼写错误或位于错误的节中。修正之前 pwikit 不会启动。有效的键见配置。

此 pwikit 未内置 PostgreSQL ​

text
pwikit: this pwikit was built without a PostgreSQL of its own and found none in /opt/pwikit/postgres.

此版本的 pwikit 不包含 PostgreSQL。请按「使用自有 PostgreSQL」所述使用自有 PostgreSQL,或改用包含 PostgreSQL 的版本。

如果信息为 the bundled PostgreSQL is incomplete,说明 postgres/ 中缺少文件。请删除 postgres 目录并重新启动 pwikit,它会重新解压 PostgreSQL。pgdata/ 中的数据库不受影响。

页面缺少样式与脚本 ​

text
WARN this build carries no page assets and -static-dir is not set, so pages are served without styles and scripts

此版本的 pwikit 不包含页面静态资源。请改用包含静态资源的版本,或通过 -static-dir 指定 ProjectWikit 的 static 目录的路径。

PostgreSQL 在运行期间停止 ​

pwikit 会随之停止,并输出 PostgreSQL 最后写入的几行日志。完整的 PostgreSQL 日志位于 logs/。作为系统服务运行时,服务管理器会重启 pwikit,PostgreSQL 也随之重新启动。

数据库已应用本版本没有的变更 ​

text
pwikit: the database was upgraded by pwikit v1.1.0, which applied 0011_example.sql; this pwikit (v1.0.0) cannot run on that schema. Run pwikit v1.1.0 or a newer release, or restore a backup taken before the upgrade

较新版本的 pwikit 对该数据库做了旧版本无法运行的修改。请运行报错中给出的版本,或恢复升级之前的备份,见旧版本与数据库。

页面提示该地址没有绑定站点 ​

浏览器中的主机名与任何站点的域名或文件域名都不匹配。请通过 pwikit site list 列出站点及其域名,并确认 DNS 记录指向本机。

HTTPS 无法使用 ​

  • 确认该名称是本实例上某个站点的域名或文件域名。
  • 确认其 DNS 记录指向本机,且 80 与 443 端口可从互联网访问。
  • 通过域名访问站点,而不是通过 IP 地址。
  • 在 pwikit 的日志中查找 TLS 握手错误(TLS handshake error),其中包含无法获取证书的原因。

浏览器提示重定向次数过多 ​

域名开启了 Cloudflare 代理,且 SSL/TLS 加密模式为「灵活」。请将 pwikit 所用名称的加密模式改为「完全(严格)」,见使用 Cloudflare。