Skip to content

Installation zh

SkimMail docs edited this page Sep 17, 2026 · 8 revisions

English · Tiếng Việt · 中文

安装

SkimMail 有四种安装方式:apt 软件包、Docker 镜像、拉取该镜像的 docker-compose 文件,以及二进制 tarball。四选一即可——它们是同一个 构建(内置 SQLite + PostgreSQL + MySQL + S3 支持;WireGuard 出口是之后从 Settings ▸ Plugins 安装的插件)的四种独立安装方式,没有"精简版"需要纠结。

从源码构建不是公开仓库能做到的事。 SkimMail 采用 Business Source License 1.1 授权:源码位于一个私有仓库,只分发编译好的二进制文件。 github.com/lyquyduong/skimmail——公开仓库——里恰好只有三个文件 (README.mdREADME.vi.mdREADME.zh.md),没有源码树。如果你有权限 访问私有仓库,那里的 README.dev.md 会讲从源码构建、开发模式和 VS Code 配置;这里没有等价的内容可以给你,下面的任何步骤在公开仓库上都行不通。

支持的平台

安装方式 操作系统 / 架构
apt(.deb Debian/Ubuntu,amd64arm64
Docker / docker-compose Linux 容器,amd64arm64(多架构镜像)
二进制 tarball linux/amd64linux/arm64darwin/amd64darwin/arm64

怎么选

你想要…
一台普通的 Debian/Ubuntu 服务器,用 systemd 管理,用 apt upgrade 更新 apt
一台容器主机,或者你本来就用 Docker 跑一切 Dockerdocker-compose
一个能自我更新的单一二进制文件,不需要包管理器,也不需要容器运行时 二进制 tarball

四种方式在首次启动时都会打印同一个一次性 claim code,并在首次登录前 要求输入它——原因见 Security。读取它的具体命令因安装方式而 异,下面每一节都会给出。


apt(Debian / Ubuntu)

前置条件

  • amd64arm64 架构上的 Debian 或 Ubuntu,具备 sudo 权限。
  • 能通过 HTTPS 访问 lyquyduong.github.io(apt 仓库)以及 github.com/objects.githubusercontent.com(apt 本身不会直接从后者拉取 任何内容,但之后的自我更新检查会用到同一条网络路径)。

添加软件源和签名密钥

curl -fsSL https://lyquyduong.github.io/skimmail/apt/skimmail.gpg \
  | sudo tee /usr/share/keyrings/skimmail.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/skimmail.gpg] https://lyquyduong.github.io/skimmail/apt stable main" \
  | sudo tee /etc/apt/sources.list.d/skimmail.list
sudo apt update

刚下载的这个密钥是一个 ed25519 OpenPGP 密钥,用于给软件源的 Release 文件 签名(由发布流水线通过 apt-ftparchive + gpg 生成);如果签名对不上, apt 会直接拒绝这个源,所以没有别的东西需要你再手动核对。

安装

sudo apt install skimmail

这会创建一个专用的系统用户(skimmail,没有登录 shell),注册并启动 skimmail.service,然后打印一段简短的横幅,其中包含获取 claim code 的命 令。配置文件在 /etc/default/skimmail(一个 systemd EnvironmentFile—— 见 Configuration);数据在 /var/lib/skimmail

确认已经启动

sudo systemctl status skimmail
curl http://localhost:8080/healthz

健康的实例会返回 {"status":"ok","version":"1.17.0"}。实时日志: sudo journalctl -u skimmail -f(另外还有一份会自动轮转的日志文件在 /var/log/skimmail/skimmail.log,登录后可以在 Settings ▸ Logs 里查看和 调整)。

首次运行:claim code

打开 http://<server>:8080。在允许你创建第一个账户或密码之前,SkimMail 会 要求输入它在首次启动时打印到日志里的一次性 claim code:

sudo journalctl -u skimmail | grep 'claim code'

这里的 sudo 不是可选项。 少了它,journalctl 会默默隐藏其他用户的 unit(该服务以系统用户 skimmail 运行,不是你),并打印一条提示而不是 claim code——这正是 1.9.1 上被多次报告的问题:有人不带 sudo 运行这条命 令,什么有用信息都没看到,就以为 claim code 根本没被打印过。

丢了 code,或者日志已经轮转把它冲掉了?重新生成一个——旧的会在你这么做的 瞬间失效:

sudo -u skimmail skimmail --data-dir /var/lib/skimmail claim-code --rotate

--data-dir /var/lib/skimmail 是必须的。这条命令不会读取 /etc/default/skimmail——那是一个 systemd EnvironmentFile,只有在 systemd 自己启动这个 unit 时才会把里面的变量交给进程,永远不会交给一条交 互式敲出来的 shell 命令。没有 --data-dirDATA_DIR 会退回到内置默认值 ./data,按你敲命令时所在的目录去解析——这要么会因为权限问题直接失败,要 么(更糟)会在那里悄悄新建一个用完即弃的数据库,并打印出一个看起来完全合 法、但真正在运行的服务器永远不会接受的 code。从 1.9.1 起,这条命令会直接 拒绝在一个不包含任何实例的目录里运行,所以路径写错了现在会明确报错,而不 是再出现上面那种悄悄跑错数据库的情况。

卸载

sudo apt purge skimmail        # 停止服务,删除二进制文件、systemd unit
                                # 以及 /etc/default/skimmail

apt purge 不会删除你的邮件——SkimMail 里从来没有任何操作会这么做。 卸载软件包时的提示信息会明确告诉你数据到底在哪里。如果你确实想彻底删除:

sudo rm -rf /var/lib/skimmail  # ⚠ 删除所有账户、邮件以及加密主密钥——不可恢复
sudo rm -rf /var/log/skimmail  # 日志文件及其轮转备份
sudo userdel skimmail          # 安装时创建的系统用户
sudo rm -f /etc/apt/sources.list.d/skimmail.list /usr/share/keyrings/skimmail.gpg
sudo apt update

如果还有可能想要回这些数据,先备份(Settings ▸ Backup)。


Docker

前置条件

  • Docker Engine(较新的版本都可以;镜像是多架构的 linux/amd64 + linux/arm64,会自动选择匹配的架构)。

运行

docker run -d --name skimmail -p 8080:8080 -v skimmail-data:/data \
  -e AUTH_MODE=passphrase ghcr.io/lyquyduong/skimmail:latest

把容器命名为 skimmail——下面的命令都假定是这个名字。镜像自己会设置 DATA_DIR=/dataLISTEN_ADDR=:8080skimmail-data 是一个命名卷, 所以数据能在 docker rm 之后保留下来。如果想固定某个版本而不是 latest,用带 v 前缀的标签,例如 ghcr.io/lyquyduong/skimmail:v1.17.0

确认已经启动

docker ps                              # skimmail 显示为 Up
curl http://localhost:8080/healthz     # {"status":"ok","version":"1.17.0"}

这个镜像是 distroless 的(里面没有 shell,也没有包管理器)—— docker exec skimmail sh 是不会成功的。docker exec skimmail /skimmail <command> 可以,因为它是直接运行 SkimMail 二进制文件,而不是经过 shell; 下面用的就是这种形式。

首次运行:claim code

docker logs skimmail 2>&1 | grep 'claim code'

Docker 的日志驱动会捕获容器里那一个进程写出的全部内容,所以——和 apt/journalctl 的情况不同——这里不存在按用户区分权限的问题;在一个普通的 Docker 安装上运行这条命令不需要 sudo(只有上面 journalctl 那种情况才 需要)。

丢了 code?重新生成一个:

docker exec skimmail /skimmail claim-code --rotate

这里不需要 --data-dir:镜像本身已经设置了 DATA_DIR=/data,而 docker exec——在容器自己的环境里运行——会自动看到这个变量。(对比一下上 面 apt 的情况:对应的环境文件从来不会交给一条交互式 shell 命令。)

卸载

docker rm -f skimmail
docker rmi ghcr.io/lyquyduong/skimmail:latest

你的数据不受影响——它保存在 skimmail-data 卷里,不在容器里。如果连它也 想删掉(⚠ 不可恢复):

docker volume rm skimmail-data

Docker Compose

前置条件

  • Docker Engine + docker compose 插件(Compose v2;docker-compose v1 这个独立二进制也能用,但不是下面这些命令所假定的)。

获取 compose 文件并启动

不需要检出源码——compose 文件会随每个发行版一起发布:

curl -fsSLO https://lyquyduong.github.io/skimmail/docker-compose.yml
docker compose up -d

这会拉取 ghcr.io/lyquyduong/skimmail:latest,发布 8080 端口,并为 /data 创建一个命名卷。要固定版本:SKIMMAIL_VERSION=v1.17.0 docker compose up -d。如果想从一开始就用 Postgres 或 MySQL,在首次启动之前取消注释文件 里的 BASE_URLAUTH_MODEDB_DRIVER/DATABASE_URL——已经有数据之 后再换数据库到底需要做什么,见 Configuration

确认已经启动

docker compose ps
curl http://localhost:8080/healthz     # {"status":"ok","version":"1.17.0"}

首次运行:claim code

docker compose logs skimmail 2>&1 | grep 'claim code'

要用 docker compose logs <service>,按 compose 文件里的服务名skimmail)来找——不是 docker logs skimmail。Compose 不会把容器直接 命名为 skimmail:按照发布出来的文件里 name: skimmail 这个项目名,加上 同样叫 skimmail 的服务名,实际的容器名是 skimmail-skimmail-1,所以裸的 docker logs skimmail 会报 "No such container"。docker compose logs 则会按 compose 文件里的服务名去查找,不管真实容器名是什么,这就是这里要用 这种写法的原因。

丢了 code?用同样的方式,通过服务重新生成:

docker compose exec skimmail /skimmail claim-code --rotate

卸载

docker compose down            # 停止并删除容器
rm docker-compose.yml          # 你下载的那个文件

数据仍保留在命名卷里。要删除一切(⚠ 不可恢复):

docker compose down -v

二进制 tarball

前置条件

  • linux/amd64linux/arm64darwin/amd64darwin/arm64
  • 不需要数据库,不需要容器运行时,也不需要包管理器——SQLite 已经内置在 二进制文件里。

下载并运行

GitHub Releases 获取 匹配你操作系统和架构的文件——文件名遵循 skimmail_<version>_<os>_<arch>.tar.gz 的规则,例如当前版本在 Linux/amd64 上:

curl -fsSLO https://github.com/lyquyduong/skimmail/releases/download/v1.17.0/skimmail_v1.17.0_linux_amd64.tar.gz
tar xzf skimmail_v1.17.0_linux_amd64.tar.gz

解压出来正好是一个可执行文件,文件名已经带上了自己的版本和平台(比如 skimmail_v1.17.0_linux_amd64),也已经具备可执行权限——不需要 chmod +x。想打字更短的话可以重命名:

mv skimmail_v1.17.0_linux_amd64 skimmail
DATA_DIR=./skimmail-data ./skimmail

像上面这样显式设置 DATA_DIR,不要依赖默认值 ./data——这个默认值是相对 于你启动它时所在的目录,一旦你从别的地方启动它(一个 cron 任务、另一个终 端、你自己写的 systemd unit),就会意外多出第二个空的实例。

这种方式没有内置任何服务定义——把这个二进制接入你系统上用来监管长驻进程的 任何东西(Linux 上自己写的 systemd unit、macOS 上的 launchd、某个进程管 理器,或者临时试用时用 nohup …/screen/tmux)。一个最基本的 systemd unit 大致只需要 User=、一个指向该二进制并带上明确 --data-dirExecStart=,以及 Restart=on-failure;这种方式不会像 apt 软件包那样自 动帮你装好一个。

确认已经启动

curl http://localhost:8080/healthz     # {"status":"ok","version":"1.17.0"}

首次运行:claim code

这个二进制文件把日志打印到 stdout,所以去看是什么在捕获它(你的终端、某个 systemd unit 的 journalctl、或者你的进程管理器写的日志文件):

journalctl -u <你的unit名字> | grep 'claim code'   # 如果你接入了自己的 systemd unit
# 或者直接看你启动它的那个终端

丢了 code?用启动时同一个 DATA_DIR 重新生成:

./skimmail --data-dir ./skimmail-data claim-code --rotate

卸载

停止进程(不管你是怎么启动或监管它的),然后删除二进制文件和它的数据目录:

rm ./skimmail
rm -rf ./skimmail-data          # ⚠ 删除所有账户、邮件以及加密主密钥——不可恢复

如果你接入了自己的 systemd unit 或其他监管方式,也一并删除。


接下来

  • Configuration —— 三个配置层的模型,以及每一个环境 变量。
  • Security —— claim code 的完整细节、屏幕锁定、trusted proxy,以及静态加密到底覆盖了什么。

SkimMail · skimmail@base101.app · 2026-09-17 · commit 97c7846

Clone this wiki locally