Skip to content

Releases: praming/Glimmer

浮光 / Glimmer v1.0.5

Choose a tag to compare

@praming praming released this 21 Sep 04:27

补丁版本。修掉「换台设备登录后设置不跟着走」的三个问题 —— 其中两个是真 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 -d

1Panel 等使用面板专用编排文件的场景:

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.dbuploads/.secrets.json 一样属于必须备份的内容。

镜像

镜像 标签
praming/glimmer-api 1.0.5 · latest
praming/glimmer-web 1.0.5 · latest

想固定版本:在 .env 里设 IMAGE_TAG=1.0.51.0.4 / 1.0.3 / 1.0.2 / 1.0.1 / 1.0.0 的标签保持不动,仍可回退。

镜像目前只构建 linux/amd64;ARM 设备(树莓派 / 部分 NAS)请改用源码本地构建:docker compose up -d --build

链接

浮光 / Glimmer v1.0.4

Choose a tag to compare

@praming praming released this 19 Sep 07:07

补丁版本。修掉 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 -d

1Panel 等使用面板专用编排文件的场景:

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.41.0.3 / 1.0.2 / 1.0.1 / 1.0.0 的标签保持不动,仍可回退。

镜像目前只构建 linux/amd64;ARM 设备(树莓派 / 部分 NAS)请改用源码本地构建:docker compose up -d --build

链接

浮光 / Glimmer v1.0.3

Choose a tag to compare

@praming praming released this 19 Sep 01:51

补丁版本。让图片直链里的 /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,改成按当前前缀动态认领请求 —— 这正是「保存即生效、无需重启」的原因;
  • 链接生成跟着前缀走,并把它纳入适配器缓存签名(否则会重演「改完配置、链接却还是旧值」的静默失效);
  • 前端容器完全不感知前缀,只按「末段带图片扩展名」判断哪些请求要转发给后端 —— 所以以后无论你把前缀改成什么,前端都不用动。

两种配置方式

位置 说明
后台「设置 → 命名与域名 → 直链路径前缀」 推荐。保存即生效;留空即挂在根路径
.envFILES_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.conflocation /files/ 是写死的:换了前缀要同步改它,留空则无法用 location 匹配、只能回源 API(README 已注明);
  • 文档与 .env.example 补上了这段前缀的说明与三种写法。

升级

cd <你的编排项目目录>
docker compose pull
docker compose up -d

1Panel 等使用面板专用编排文件的场景:

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.31.0.2 / 1.0.1 / 1.0.0 的标签保持不动,仍可回退。

镜像目前只构建 linux/amd64;ARM 设备(树莓派 / 部分 NAS)请改用源码本地构建:docker compose up -d --build

链接

浮光 / Glimmer v1.0.2

Choose a tag to compare

@praming praming released this 18 Sep 08:59

补丁版本。修复「复制出来的图片直链打不开、后台图库也预览不出来」这一类问题,并补上换域名后的历史数据处理能力。

修复:直链域名配了却不生效

直链的域名此前实际只有两层来源:存储后端「访问域名」→ 环境变量 PUBLIC_BASE_URL。而后台「设置 → 命名与域名」里的自定义域名虽然能保存,却没有任何生成链接的代码读它 —— 改它对直链毫无影响。所以「我把后台域名改了,复制出来还是 localhost」既不是缓存、也不是没重启,而是那条路根本没接上。

没配过 PUBLIC_BASE_URL 的部署会一路回落到内置默认值 http://localhost:3000,于是每条直链都写成 http://localhost:3000/files/... —— 这个地址只有容器内部能访问,复制给别人打不开,后台图库同样预览不出来(两者用的是同一份地址)。

现在域名按下面的顺序取第一个有值的

  1. 「设置 → 存储后端 → 访问域名」 —— 优先级最高,保存即生效;
  2. 「设置 → 命名与域名 → 自定义域名」 —— 全局兜底(本次起真正生效);
  3. 环境变量 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 -d

1Panel 等使用面板专用编排文件的场景:

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.21.0.11.0.0 的标签保持不动,仍可回退。

镜像目前只构建 linux/amd64;ARM 设备(树莓派 / 部分 NAS)请改用源码本地构建:docker compose up -d --build

链接

浮光 / Glimmer v1.0.1

Choose a tag to compare

@praming praming released this 18 Sep 07:52

补丁版本。修复一处「部署后无法自行恢复」的缺陷:管理员密码忘了或登不上,此前只能删库重建。

修复:管理员密码无法找回

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 -d

1Panel 等使用面板专用编排文件的场景:

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.11.0.0 的标签保持不动,仍可回退。

镜像目前只构建 linux/amd64;ARM 设备(树莓派 / 部分 NAS)请改用源码本地构建:docker compose up -d --build

链接

浮光 / Glimmer v1.0.0

Choose a tag to compare

@praming praming released this 18 Sep 06:51

首个正式版本:一个轻量、自建、够用的图床。

上传图片 → 自动压缩与格式转换 → 并行写入一个或多个存储后端 → 一键复制各种格式的链接 → 在图库中统一管理。整套服务只依赖一个 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                             # 从源码构建

链接