Releases: praming/Glimmer
Release list
浮光 / Glimmer v1.0.5
补丁版本。修掉「换台设备登录后设置不跟着走」的三个问题 —— 其中两个是真 bug,一个是缺功能。
它们的表现相似、原因完全不同,所以分开说。顺带修掉一个没被报上来的第 4 个 bug。
先说结论:这些设置从来不写在 Cookie 里。会话 Cookie 里只有一个随机令牌(
httpOnly+SameSite=Lax),一个设置项都没有。
一、头像不显示
现象:换台电脑登录后头像框是空的、回落成用户名首字;但头像文件还在图库里。
根因:头像存的是「上传那一刻的图库图片直链」,而这个地址是当时按域名写下的快照。图库图片的直链有重建工具(rebuild-urls),但它只管图库、从不碰用户表 —— 所以只要改过域名或直链路径前缀,头像地址就整体失效。文件没动,所以「图库里有、头像框里没有」。
改法:不再「从图库挑一张」,改为头像单独上传,并且地址由服务端现算:
- 上传后自动裁成 1:1 方图、转成 256×256 webp,单独存放在数据目录的
avatars/下(不在图片存储后端里,不受后端增删与路径前缀影响)。 - 对外地址是
/api/users/<id>/avatar?v=<版本>这种形式,域名、路径前缀怎么改都不会失效,也不需要任何重建命令。 - 「粘贴图片链接」的入口从界面上收掉了(后端能力保留,API 仍可传外链);外链与本地头像互斥 —— 上传会清掉外链,写外链会删掉本地文件。
老的(失效的)头像地址会被当作外链处理,载入失败时回落首字占位 —— 重新上传一次即可,不需要任何数据迁移。
二、亮暗主题不跟着账户走
现象:在 A 设备选了深色,换 B 设备登录还是浅色。
根因:主题其实一直在往账户里存,只是前端从来不读。同一个设置页里「字体」是有读取逻辑的,所以字体正常、主题不正常。
改法:补上读取,并让顶栏那个主题切换按钮也同步到账户(以前只写浏览器本地)。
做了一次一次性迁移:如果你的账户里还是默认值、而本机明确选过深色,升级后会把本机这次选择补写进账户 —— 否则你会看到界面在眼前变回浅色。这个迁移只做一次,之后以账户为准。
三、上传页的三个选项不跟账户走
现象:上传页选的「写入后端(本地存储 / 七牛)」「输出格式」「保留原图」,换设备后回到默认。
根因:这一项不是同步坏了,是服务端压根没有这几个字段 —— 它以前只存在浏览器本地。
改法:这三个选择正式存进账户偏好,跟主题、字体、默认复制格式一起走。
顺带修掉一个没被报上来的 bug:「保留原图」以前每次刷新页面都会被重置成全局默认 —— 你没选错,是改了也白改。
升级
cd <你的编排项目目录>
docker compose pull
docker compose up -d1Panel 等使用面板专用编排文件的场景:
docker compose -f docker-compose.1panel.yml pull
docker compose -f docker-compose.1panel.yml up -d- 数据无需迁移:
./glimmer-data原样使用,avatars/目录会在首次上传头像时自动创建。 - 容器启动时会幂等补上
users.avatar_updated_at这一列(只是ALTER TABLE ADD COLUMN,不动任何现有数据)。 ⚠️ 备份别忘了新目录:avatars/与glimmer.db、uploads/、.secrets.json一样属于必须备份的内容。
镜像
| 镜像 | 标签 |
|---|---|
praming/glimmer-api |
1.0.5 · latest |
praming/glimmer-web |
1.0.5 · latest |
想固定版本:在 .env 里设 IMAGE_TAG=1.0.5。1.0.4 / 1.0.3 / 1.0.2 / 1.0.1 / 1.0.0 的标签保持不动,仍可回退。
镜像目前只构建 linux/amd64;ARM 设备(树莓派 / 部分 NAS)请改用源码本地构建:docker compose up -d --build。
链接
- README —— 部署步骤、配置清单、常见问题
- v1.0.4 发布说明
- 许可:AGPL-3.0
浮光 / Glimmer v1.0.4
补丁版本。修掉 S3 存储后端的两处对象键 / 直链问题,都是配了七牛云这类 S3 兼容存储之后立刻会撞上的。
一、空间里凭空多出一个同名文件夹
现象:Bucket 填的是空间名,上传后文件却在 空间根目录/<空间名>/… 下,而不是直接落在空间根目录。
根因不是 Bucket 的语义,是 Endpoint 填错了。 对象存储控制台通常同时给出两个地址:
服务域名(Endpoint) https://s3.cn-east-1.qiniucs.com ← 这里该填这个
空间域名(虚拟主机风格) https://<空间名>.s3.cn-east-1.qiniucs.com ← 不要填这个
「空间域名」本身已经把请求路由到了该空间,再叠加「使用 Path-Style 访问」,这段主机名就被算进了对象键 —— 于是 Key 变成 <空间名>/<命名规则>。
本次的处理:
- 自动纠正:Endpoint 的主机名首段若与空间名相同、且余下部分像服务域名(
s3/oss/cos/r2/obs/storage),就把多余那段剥掉。自定义 CNAME 不会被误伤。 - 明确告知:「测试连接」的结果里会带上说明,成功与失败两条路径都会显示,不会再出现「配置悄悄被改写」。
- 表单引导:Endpoint / Bucket / 路径前缀三个字段都补了说明,并给出实时的存储位置预览。
Bucket 仍然就是空间名(七牛要填它在「空间概览 → S3 域名」里显示的「S3 空间名」);要在命名规则之前多一层目录,用**「路径前缀」**这一项,留空即不加。
二、填了「路径前缀」之后直链 404
S3 适配器拼直链时漏掉了 pathPrefix 这一段:文件被写到 <路径前缀>/<命名规则>,链接却指向 <命名规则>,两边对不上。本地与 WebDAV 适配器一直是对的,只有 S3 漏了,现已补齐。
若你在 S3 后端填过「路径前缀」,跑一次
rebuild-urls --apply就能把老记录的直链修正回来 —— 它只改 URL,不移动任何文件。从本次起,事后修改「路径前缀」等于把所有老文件的直链整体平移(数据库里存的是不含前缀的相对路径),所以前缀请在开始上传前定好。
如果你已经踩到了
| 你的配置 | 处理 |
|---|---|
| Endpoint 填的是「空间域名」 | 升级后自动纠正;已上传的老文件不用动,直链仍指向同一个对象(那层目录本来就在 Key 里)。想清理空间只能手工移动或重传 |
| 「路径前缀」填了空间名 | 把它清空即可。老文件的直链需要 rebuild-urls --apply 修正 |
| 「路径前缀」填了别的值 | 直链本来就是错的(缺陷二),跑 rebuild-urls --apply 修回来 |
其它
- 后端编辑弹窗的 Endpoint / Bucket / 路径前缀补了字段说明、存储位置实时预览与误填警示;
- 「使用 Path-Style 访问」的说明改为「MinIO、七牛 Kodo 及多数自建服务建议开启;R2 / AWS S3 通常不需要」;
- README 新增《使用 S3 兼容对象存储》一节与对应问答;数据库里
storage_records.path的注释修正为「不含 pathPrefix」(原文写反了,正是缺陷二的来源)。
升级
cd <你的编排项目目录>
docker compose pull
docker compose up -d1Panel 等使用面板专用编排文件的场景:
docker compose -f docker-compose.1panel.yml pull
docker compose -f docker-compose.1panel.yml up -d数据无需任何迁移,./glimmer-data 原样使用。不用 S3 后端的部署不受影响。
镜像
| 镜像 | 标签 |
|---|---|
praming/glimmer-api |
1.0.4 · latest |
praming/glimmer-web |
1.0.4 · latest |
想固定版本:在 .env 里设 IMAGE_TAG=1.0.4。1.0.3 / 1.0.2 / 1.0.1 / 1.0.0 的标签保持不动,仍可回退。
镜像目前只构建 linux/amd64;ARM 设备(树莓派 / 部分 NAS)请改用源码本地构建:docker compose up -d --build。
链接
- README —— 部署步骤、配置清单、常见问题
- v1.0.3 发布说明
- 许可:AGPL-3.0
浮光 / Glimmer v1.0.3
补丁版本。让图片直链里的 /files 变成可配置:可以换成自己的前缀,也可以完全去掉。
现在可以这样
到「设置 → 命名与域名 → 直链路径前缀」填:
files → https://pic.gukong.net/files/2026/0919-7sgcq0.webp (默认,与以前完全一致)
img → https://pic.gukong.net/img/2026/0919-7sgcq0.webp
(留空) → https://pic.gukong.net/2026/0919-7sgcq0.webp (直接挂在根路径)
保存即生效,不需要重启容器。设置页里带实时的直链效果预览,改之前就能看到链接会变成什么样。
为什么以前改不了
/files 不只是链接里的一段文案 —— 它是 API 的路由挂载点(文件真的由 /files/* 这个路由提供),同时被前端容器的代理白名单写死。所以「链接生成」与「服务端路由」必须一起改口,只改一头就会出现「链接变了但打不开」。
本次把六处写死点统一到一个配置:
- API 不再静态挂载
/files,改成按当前前缀动态认领请求 —— 这正是「保存即生效、无需重启」的原因; - 链接生成跟着前缀走,并把它纳入适配器缓存签名(否则会重演「改完配置、链接却还是旧值」的静默失效);
- 前端容器完全不感知前缀,只按「末段带图片扩展名」判断哪些请求要转发给后端 —— 所以以后无论你把前缀改成什么,前端都不用动。
两种配置方式
| 位置 | 说明 |
|---|---|
| 后台「设置 → 命名与域名 → 直链路径前缀」 | 推荐。保存即生效;留空即挂在根路径 |
.env 的 FILES_ROUTE_PREFIX |
部署级强制值,优先级更高。填 img 强制 /{img}/,填 / 强制根路径 |
设置页的后台前缀被 .env 锁定时,输入框会禁用并说明原因,不会让你改了半天才发现没生效。
⚠️ 改完后记得重写历史直链
直链是上传那一刻的快照,所以改了前缀之后,已经上传的图片仍是旧地址:
docker exec glimmer-api node apps/api/dist/cli/rebuild-urls.js # 先预演,只打印不改库
docker exec glimmer-api node apps/api/dist/cli/rebuild-urls.js --apply # 确认后落库(这条命令 v1.0.2 就已提供;本次它还会打印当前生效的前缀及其来源,便于自查。)
一个建议
如果只是想让链接更好看,推荐用 /img 这类自定义短前缀,而不是留空。
自定义前缀能靠路径前缀精确区分「图片」与「前端页面」;而留空之后,服务端只能靠「像不像图片路径」来猜,将来前端若出现同形态的路径就会冲突。留空是可用的,只是没有自定义前缀稳。
其它
nginx.conf的location /files/是写死的:换了前缀要同步改它,留空则无法用location匹配、只能回源 API(README 已注明);- 文档与
.env.example补上了这段前缀的说明与三种写法。
升级
cd <你的编排项目目录>
docker compose pull
docker compose up -d1Panel 等使用面板专用编排文件的场景:
docker compose -f docker-compose.1panel.yml pull
docker compose -f docker-compose.1panel.yml up -d数据无需任何迁移,./glimmer-data 原样使用。不配置前缀的部署,行为与以前完全一致。
镜像
| 镜像 | 标签 |
|---|---|
praming/glimmer-api |
1.0.3 · latest |
praming/glimmer-web |
1.0.3 · latest |
想固定版本:在 .env 里设 IMAGE_TAG=1.0.3。1.0.2 / 1.0.1 / 1.0.0 的标签保持不动,仍可回退。
镜像目前只构建 linux/amd64;ARM 设备(树莓派 / 部分 NAS)请改用源码本地构建:docker compose up -d --build。
链接
- README —— 部署步骤、配置清单、常见问题
- v1.0.2 发布说明
- 许可:AGPL-3.0
浮光 / Glimmer v1.0.2
补丁版本。修复「复制出来的图片直链打不开、后台图库也预览不出来」这一类问题,并补上换域名后的历史数据处理能力。
修复:直链域名配了却不生效
直链的域名此前实际只有两层来源:存储后端「访问域名」→ 环境变量 PUBLIC_BASE_URL。而后台「设置 → 命名与域名」里的自定义域名虽然能保存,却没有任何生成链接的代码读它 —— 改它对直链毫无影响。所以「我把后台域名改了,复制出来还是 localhost」既不是缓存、也不是没重启,而是那条路根本没接上。
没配过 PUBLIC_BASE_URL 的部署会一路回落到内置默认值 http://localhost:3000,于是每条直链都写成 http://localhost:3000/files/... —— 这个地址只有容器内部能访问,复制给别人打不开,后台图库同样预览不出来(两者用的是同一份地址)。
现在域名按下面的顺序取第一个有值的:
- 「设置 → 存储后端 → 访问域名」 —— 优先级最高,保存即生效;
- 「设置 → 命名与域名 → 自定义域名」 —— 全局兜底(本次起真正生效);
- 环境变量
PUBLIC_BASE_URL—— 最后回落。
关于结尾的 /files,两条约定务必分清:
- 第 1 项是原样使用 —— 本地存储要自己写全:
https://pic.example.com/files; - 第 2、3 项视为根地址,会自动补
/files—— 填https://pic.example.com即可。
(第 1 项保持原样是为了兼容把上传目录挂到别的路径的场景,例如让 Nginx 用 /media 对外。)
另外修掉一个会让升级「反而变糟」的隐患:早期版本首次启动时会把当时的默认值 http://localhost:3000 写进数据库的设置行。它以前从不参与链接生成,所以没人察觉;但一旦全局域名开始生效,它就会压住你在 .env 里真正配好的地址。新版启动时会自动清理这个被写死的默认值(只动这一个字段,S3 / WebDAV 的加密凭据原样保留),建新库时也不再写入。
新增:rebuild-urls 维护命令
直链是上传那一刻写死的快照,所以改完域名,已经上传的图片不会自动跟着变 —— 这正是「域名明明改对了,老图还是打不开」的原因。新版提供一条命令,按当前配置重算并回写历史记录:
# 1) 先预演:列出会改哪些记录、改成什么(默认就是预演,不写库)
docker exec glimmer-api node apps/api/dist/cli/rebuild-urls.js
# 2) 确认无误后真正写入(WAL 模式,与运行中的服务并存,无需停服)
docker exec glimmer-api node apps/api/dist/cli/rebuild-urls.js --apply
# 可选:只处理某个后端 / 调整对照显示条数
docker exec glimmer-api node apps/api/dist/cli/rebuild-urls.js --backend local --limit 50- 只改数据库里的链接字符串,不移动、不重新处理任何文件 —— 改错了把域名改回去再跑一次即可复原;
- 用的是与上传时完全相同的域名解析逻辑,不会出现「命令算的和实际生成的不一致」;
- 幂等,重复执行不会再有变化;
- 若它提示「后台自定义域名当前是
http://localhost:3000」(老库里的写死默认值),说明需要先升级并重启一次 API 让自动清理生效,或手工把域名改成真实地址。
现在这样修好你的图床
cd <你的编排项目目录>
docker compose pull && docker compose up -d # 拉到 1.0.2然后二选一:
- 到「设置 → 存储后端」把访问域名填成
https://你的域名/files(推荐,保存即生效,无需重启); - 或到「设置 → 命名与域名」把自定义域名填成
https://你的域名。
最后跑一次 rebuild-urls --apply 重写历史图片的直链,旧图立刻可用。
其它改进
- 设置页的输入提示补充了优先级与
/files约定,避免填错一层; - 文档区分了「后端访问域名(原样使用)」与「全局域名(自动补
/files)」两种写法。
升级
cd <你的编排项目目录>
docker compose pull
docker compose up -d1Panel 等使用面板专用编排文件的场景:
docker compose -f docker-compose.1panel.yml pull
docker compose -f docker-compose.1panel.yml up -d数据无需任何迁移,./glimmer-data 原样使用;启动时会自动清理设置里被写死的默认对外地址(日志可见)。
镜像
| 镜像 | 标签 |
|---|---|
praming/glimmer-api |
1.0.2 · latest |
praming/glimmer-web |
1.0.2 · latest |
想固定版本:在 .env 里设 IMAGE_TAG=1.0.2。1.0.1 与 1.0.0 的标签保持不动,仍可回退。
镜像目前只构建 linux/amd64;ARM 设备(树莓派 / 部分 NAS)请改用源码本地构建:docker compose up -d --build。
链接
- README —— 部署步骤、配置清单、常见问题
- v1.0.1 发布说明
- 许可:AGPL-3.0
浮光 / Glimmer v1.0.1
补丁版本。修复一处「部署后无法自行恢复」的缺陷:管理员密码忘了或登不上,此前只能删库重建。
修复:管理员密码无法找回
ADMIN_PASSWORD 只在数据库里还没有任何账号的那一次启动生效。账号一旦建立,密码哈希就落库了,之后改 .env、补 .env、删 .env 都不会再影响它 —— 而且这个忽略过程没有任何提示,只能反复试密码。配合「项目里没有找回密码的通道」,唯一的出路是删库。
现在:
1. 新增密码重置维护命令(随镜像发布,无需额外安装任何东西)
# 先看清库里有哪些账号(用户名、角色、是否被禁用)
docker exec glimmer-api node apps/api/dist/cli/reset-password.js --list
# 重置指定账号的密码
docker exec glimmer-api node apps/api/dist/cli/reset-password.js <用户名> <新密码>- 立即生效,不必重启容器:SQLite 处于 WAL 模式,命令可与运行中的 API 并存写入;登录时每次都从库里读哈希。
- 不必删库:已有的图片、记录、配置全部保留。
- 重置会一并撤销该账号的全部登录会话与 API 令牌,与界面上「修改密码」的语义一致 —— 否则重置挡不住已经拿到旧凭据的人。
- 账号被禁用时加
--enable可同时启用(用于把自己锁在门外的情况)。
2. 启动横幅不再静默忽略
配置了 ADMIN_PASSWORD 但账号已存在时,启动日志会明确打印:
⚠️ 已忽略 ADMIN_PASSWORD:管理员账号已存在,该变量只在数据库为空时生效
排查时一句 docker compose logs glimmer-api | grep 已忽略 即可确认。
3. 文档
README 与部署指南补充了「登录不上 / 忘记密码」的排查顺序(含密码管理器自动填充、中文全角字符、用户名区分大小写、连续失败触发的是限流提示而非凭据错误、面板部署时 .env 必须与编排文件同目录等)。
升级
cd <你的编排项目目录>
docker compose pull
docker compose up -d1Panel 等使用面板专用编排文件的场景:
docker compose -f docker-compose.1panel.yml pull
docker compose -f docker-compose.1panel.yml up -d数据无需任何迁移,./glimmer-data 原样使用。
镜像
| 镜像 | 标签 |
|---|---|
praming/glimmer-api |
1.0.1 · latest |
praming/glimmer-web |
1.0.1 · latest |
想固定版本:在 .env 里设 IMAGE_TAG=1.0.1。1.0.0 的标签保持不动,仍可回退。
镜像目前只构建 linux/amd64;ARM 设备(树莓派 / 部分 NAS)请改用源码本地构建:docker compose up -d --build。
链接
- README —— 部署步骤、配置清单、常见问题
- v1.0.0 发布说明
- 许可:AGPL-3.0
浮光 / Glimmer v1.0.0
首个正式版本:一个轻量、自建、够用的图床。
上传图片 → 自动压缩与格式转换 → 并行写入一个或多个存储后端 → 一键复制各种格式的链接 → 在图库中统一管理。整套服务只依赖一个 SQLite 文件与本地磁盘,不需要 Redis、消息队列或任何额外中间件。
它不开放注册,账号由管理员创建,适合个人或 2~3 人的小团队部署在自己的 VPS 上。
部署
mkdir glimmer && cd glimmer
curl -fsSLO https://raw.githubusercontent.com/praming/Glimmer/main/docker-compose.yml
docker compose up -d访问 http://<服务器IP>:3001,用 admin / change-me 登录 —— 请立即修改密码。
不需要创建 .env:所有配置都有可用默认值;用于加密存储后端凭据的密钥会在首次启动时自动生成并落盘到 glimmer-data/.secrets.json。
镜像
| 镜像 | 标签 |
|---|---|
praming/glimmer-api |
1.0.0 · latest |
praming/glimmer-web |
1.0.0 · latest |
想固定版本:在 .env 里设 IMAGE_TAG=1.0.0。
镜像目前只构建 linux/amd64;ARM 设备(树莓派 / 部分 NAS)请改用源码本地构建:docker compose up -d --build。
主要能力
存储
- 本地磁盘 / S3 兼容对象存储(AWS S3、MinIO、Cloudflare R2、阿里云 OSS、腾讯云 COS)/ 标准 WebDAV(Nextcloud、坚果云等)
- 一次上传可并行写入多个后端,单个后端失败不阻塞其余,可单独重试
图片处理
- 自动旋转 → 限制最大宽高(不放大)→ 剥离 EXIF → 按目标格式编码
- 输出
webp/avif/jpeg/png/gif,一次可生成多种;多帧 GIF 保留动画 - 上传立即返回
202,处理在后台队列完成,前端实时显示每个文件的进度与结果
上传体验
- 点击选择 / 拖拽(整页投放区)/ 粘贴,支持多文件队列
- 秒传去重:浏览器端先算原图 SHA-256 做预检,命中即跳过整段文件传输
- 直链 / Markdown / HTML / BBCode 四种链接一键复制,支持自定义命名模板
管理与安全
- 图库:网格 / 列表切换、搜索、按格式·后端·上传者·状态·日期筛选、批量删除、详情抽屉
- 关闭公开注册;口令以 Argon2id 哈希存储;
httpOnly+SameSite=Lax会话 Cookie;Bearer 令牌供脚本与 CI 使用(改密自动级联撤销) - 登录限流按来源 IP 与按账号两个维度、只统计失败次数,超限返回
429+Retry-After,且在口令校验之前就拒绝 - 访问统计(直链次数 / 出口流量 / Top 热门图 / 按天趋势)
- 失败任务按
30s → 2m → 8m → 32m指数退避自动重试,排期写入数据库,重启进程不丢任务
数据与升级
运行数据全部在 ./glimmer-data:
glimmer-data/
├── glimmer.db # SQLite 数据库(用户、图库记录、全局配置)
├── .secrets.json # 加密密钥(用于解密 S3 / WebDAV 凭据)
├── uploads/ # 本地存储后端的图片文件
└── tmp/ # 上传临时目录(处理完自动清理)
备份打包这个目录即可。.secrets.json 请务必一并保留 —— 删掉它,后台保存过的存储后端凭据就再也解不回来。
docker compose pull && docker compose up -d --no-build # 升级到新镜像
docker compose up -d --build # 从源码构建