-
Notifications
You must be signed in to change notification settings - Fork 0
Installation zh
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.md、README.vi.md、README.zh.md),没有源码树。如果你有权限 访问私有仓库,那里的README.dev.md会讲从源码构建、开发模式和 VS Code 配置;这里没有等价的内容可以给你,下面的任何步骤在公开仓库上都行不通。
| 安装方式 | 操作系统 / 架构 |
|---|---|
apt(.deb) |
Debian/Ubuntu,amd64、arm64
|
| Docker / docker-compose | Linux 容器,amd64、arm64(多架构镜像) |
| 二进制 tarball |
linux/amd64、linux/arm64、darwin/amd64、darwin/arm64
|
| 你想要… | 用 |
|---|---|
一台普通的 Debian/Ubuntu 服务器,用 systemd 管理,用 apt upgrade 更新 |
apt |
| 一台容器主机,或者你本来就用 Docker 跑一切 | Docker 或 docker-compose |
| 一个能自我更新的单一二进制文件,不需要包管理器,也不需要容器运行时 | 二进制 tarball |
四种方式在首次启动时都会打印同一个一次性 claim code,并在首次登录前 要求输入它——原因见 Security。读取它的具体命令因安装方式而 异,下面每一节都会给出。
-
amd64或arm64架构上的 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 里查看和
调整)。
打开 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-dir,DATA_DIR 会退回到内置默认值
./data,按你敲命令时所在的目录去解析——这要么会因为权限问题直接失败,要
么(更糟)会在那里悄悄新建一个用完即弃的数据库,并打印出一个看起来完全合
法、但真正在运行的服务器永远不会接受的 code。从 1.9.1 起,这条命令会直接
拒绝在一个不包含任何实例的目录里运行,所以路径写错了现在会明确报错,而不
是再出现上面那种悄悄跑错数据库的情况。
sudo apt purge skimmail # 停止服务,删除二进制文件、systemd unit
# 以及 /etc/default/skimmailapt 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 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=/data 和 LISTEN_ADDR=:8080;skimmail-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;
下面用的就是这种形式。
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 Engine +
docker compose插件(Compose v2;docker-composev1 这个独立二进制也能用,但不是下面这些命令所假定的)。
不需要检出源码——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_URL、AUTH_MODE 或 DB_DRIVER/DATABASE_URL——已经有数据之
后再换数据库到底需要做什么,见 Configuration。
docker compose ps
curl http://localhost:8080/healthz # {"status":"ok","version":"1.17.0"}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 --rotatedocker compose down # 停止并删除容器
rm docker-compose.yml # 你下载的那个文件数据仍保留在命名卷里。要删除一切(⚠ 不可恢复):
docker compose down -v-
linux/amd64、linux/arm64、darwin/amd64或darwin/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-dir 的
ExecStart=,以及 Restart=on-failure;这种方式不会像 apt 软件包那样自
动帮你装好一个。
curl http://localhost:8080/healthz # {"status":"ok","version":"1.17.0"}这个二进制文件把日志打印到 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