docs: 修正初始密码说明,容器编排支持直接注入全部环境变量
首次运行密码逻辑已变(DEFAULT_PASS 留空时生成 43 字符随机密码到
data/.initial_admin_password,只写一次、不落日志、不重置已有账号),
原 README 仍写「密码 123456」,改为准确描述并给出查看命令。
- README:重写「初始账号与密码」为生成规则表;新增「配置方式」章节,
说明可用 .env / compose environment / docker run -e 三种方式,
并列出常用变量表;修正上传格式(SVG/BMP 不再被接受);补 R2 存储类型
- docker-compose.yml:environment 段展开为全部可配置变量,统一用
${VAR:-default} 由同目录 .env 替换,端口映射跟随 SERVER_PORT
- .env.example:新增,覆盖全部变量并标注必改项,替代无模板状态
- AUDIT_REPORT:M5 标记为已彻底移除(模板留空 + 文档全部改口径)
- .gitignore:修正上批写入时产生的乱码注释行
验证:go build / go vet 通过;docker compose config 在无 .env 时
回落到安全默认值(DEFAULT_PASS 空、8080、TRUSTED_PROXIES 空);
实测进程环境变量优先于自动生成的 .env(模板写 http 的 APP_URL,
注入 https 后会话 Cookie 带 Secure;空 DEFAULT_PASS 走随机生成)。
This commit is contained in:
1 parent
aa52a7900b
commit
0c60708ab1
5 files changed
+203
-18
No files matched your search
@@ -0,0 +1,63 @@
|
||||
# 初春图床 oneImg 环境变量示例
|
||||
#
|
||||
# 用法(二选一):
|
||||
# A. 本文件重命名为 .env 放在 docker-compose.yml 同目录,docker compose
|
||||
# 会自动读取它并替换 compose 里的 ${VAR} 占位符。
|
||||
# B. 直接用 docker run 时,把下面的 KEY=VALUE 写成 -e KEY=VALUE。
|
||||
#
|
||||
# 优先级:这里/编排里注入的值 > 容器内自动生成的 /app/.env
|
||||
# 应用首次启动会在工作目录生成 .env 模板,但 godotenv 不覆盖已存在的
|
||||
# 进程环境变量,所以容器里注入的值始终生效。
|
||||
#
|
||||
# 所有项都有内置默认值,全部留空也能启动;下面只列需要按部署环境改的几项。
|
||||
|
||||
# ── 必改 ─────────────────────────────────────────────────────────
|
||||
# 站点对外地址:API 返回的图片 URL 固定取自该值(不再反射请求 Host)。
|
||||
# 公网部署必须改成实际地址,否则返回的图片链接不可用。
|
||||
APP_URL=https://img.example.com
|
||||
|
||||
# 监听端口,改这里时 compose 的端口映射会同步变化。
|
||||
SERVER_PORT=8080
|
||||
|
||||
# ── 初始管理员 ───────────────────────────────────────────────────
|
||||
DEFAULT_USER=admin
|
||||
# 留空(推荐):仅在首次创建管理员时生成 43 字符随机密码,写入
|
||||
# /app/data/.initial_admin_password(权限 0600),不打印到日志。
|
||||
# 查看:docker compose exec oneimg cat /app/data/.initial_admin_password
|
||||
# 非空:直接作为初始密码。仅在数据库里还没有任何用户时生效,
|
||||
# 已有账号的密码不会因为改这里而被重置。
|
||||
DEFAULT_PASS=
|
||||
|
||||
# ── 密钥 ─────────────────────────────────────────────────────────
|
||||
# 留空自动生成。CONFIG_SECRET 用于加密存储凭证和图片文件:留空时自动生成并
|
||||
# 持久化到 data/.config_secret(跟着 ./data 卷走,重建容器不变)。
|
||||
# 一旦启用加密存储就不能更换,否则历史内容无法解密。
|
||||
# 显式配置时 CONFIG_SECRET 必须 >= 32 字符,否则启动直接失败。
|
||||
SESSION_SECRET=
|
||||
CONFIG_SECRET=
|
||||
|
||||
# ── 数据库 ───────────────────────────────────────────────────────
|
||||
# sqlite | mysql | postgres
|
||||
DB_TYPE=sqlite
|
||||
SQLITE_PATH=./data/data.db
|
||||
# 仅 mysql/postgres 需要:
|
||||
# DB_HOST=localhost
|
||||
# DB_PORT=3306
|
||||
# DB_USER=root
|
||||
# DB_PASSWORD=
|
||||
# DB_NAME=oneimg
|
||||
# CA 证书路径;留空使用系统 CA。证书验证默认开启,路径错误会拒绝启动。
|
||||
# DB_CA_CERT_PATH=./ca/isrgrootx1.pem
|
||||
# DB_SKIP_CERT_VERIFY=false
|
||||
|
||||
# ── 上传 ─────────────────────────────────────────────────────────
|
||||
UPLOAD_ROOT=./uploads
|
||||
# 单文件上限(字节),程序内另有 32MB 硬上限
|
||||
MAX_FILE_SIZE=10485760
|
||||
# SVG 不再作为普通图片接受;留空默认 jpeg/png/gif/webp
|
||||
ALLOWED_TYPES=image/jpeg,image/png,image/gif,image/webp
|
||||
|
||||
# ── 反向代理 ─────────────────────────────────────────────────────
|
||||
# 逗号分隔 IP/CIDR。仅这些来源的 X-Forwarded-For 会被采信为客户端 IP,
|
||||
# 留空表示不信任任何代理(直连部署保持留空)。
|
||||
TRUSTED_PROXIES=
|
||||
+1
-1
@@ -27,7 +27,7 @@ frontend/node_modules/
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# v3.5.5 审计构建产物与会话测试文件
|
||||
# Local build artifacts and session test files (v3.5.6)
|
||||
/release/
|
||||
/cookies.txt
|
||||
/login.json
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
| M2 | `backend/routes/routes.go` CORS | AllowOriginFunc 放行任意 `http://localhost:*/127.0.0.1:*` 且 AllowCredentials:true → 受害者 localhost 任意端口恶意页可带 cookie 读全部已登录 GET 接口 | localhost 放行仅当 APP_URL 本身是 localhost/127.0.0.1/::1 时(新增 isLocalhostURL helper) |
|
||||
| M3 | TG 通知(ImageUpload/ImageURLUpload/LegacyUpload 4 处调用点) | MigrateSecrets 已把 TGBotToken 加密为 `enc:v1:...`,但 4 处直接拿密文调 telegram API → 必然 401 静默失败(功能坏死) | 新建 `backend/controllers/notify.go` `sendTGNotification(settingRow, data)`:GetSecret 解密后发送,空/错记日志返回;4 调用点全部替换 |
|
||||
| M4 | 上传 DoS:`main.go` 无 ReadTimeout + `UploadLimits.go` 全局仅 2 槽 | 慢速 multipart body 无限占槽,2 连接即全局上传 DoS;FallbackDirectUpload 完全不受槽约束 | `wrapUploadBody(c, max)` = MaxBytesReader + stallAbortBody(60s 空闲中断,经 http.ResponseController 设 body deadline,gin v1.11 responseWriter Unwrap 已验证可穿透)+ 槽持有 15 分钟 time.AfterFunc 兜底自动释放;三个入口(ImageUpload/ImageURLUpload/FallbackDirectUpload)全部接入;FallbackDirectUpload 补 acquireUploadRequest 槽 |
|
||||
| M5 | `.env` DEFAULT_PASS=123456 模板默认 | 部署沿用即 admin/123456 | 属部署模板问题:**文档化**(见二-1),代码层 DefaultPass 为空时已走随机生成路径 |
|
||||
| M5 | `.env` DEFAULT_PASS=123456 模板默认 | 部署沿用即 admin/123456 | **已彻底移除**:v3.5.6 起代码模板 `DEFAULT_PASS=` 留空、README/README.txt/.env.example 全部改为"随机生成"口径,本机 `.env` 中的历史值也已清除;代码层 DefaultPass 为空时走 `data/.initial_admin_password` 随机生成路径 |
|
||||
|
||||
### Low
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
## 二、未修复/文档化项(有意接受的取舍)
|
||||
|
||||
1. **`.env` 模板 DEFAULT_PASS=123456**:生产部署务必修改或删除该行;留空时首启自动生成 32 字节随机密码写入 `data/.initial_admin_password`(0600,不落日志)——这是推荐路径。
|
||||
1. **`.env` 模板 DEFAULT_PASS 现已留空**(v3.5.6 起):留空时仅在数据库还没有任何用户时生成 43 字符随机密码(32 字节随机数 base64url)写入 `data/.initial_admin_password`(0600,不落日志)——这是推荐路径;非空则直接作为初始密码。该文件只写一次,重启不覆盖,也不会重置已有账号密码。历史模板里的 `DEFAULT_PASS=123456` 若仍留在部署的 `.env` 中会被当作初始密码,需删除。
|
||||
2. **CONFIG_SECRET 部署要求**:文件加密密钥(securestorage)在 CONFIG_SECRET 为空时回退 SESSION_SECRET(域分离前缀是公开常量)。当前版本 CONFIG_SECRET 总非空(自动生成持久化 `data/.config_secret`),回退不可达;但生产建议显式独立配置两者,且 CONFIG_SECRET 现已强制 ≥32 字符。
|
||||
3. **公开图片代理无速率限制**(Proxy.go 流式路径):带宽/上游配额 DoS 向量。建议反代层 limit_req;代码层不加(公开端点限流易误伤合法流量)。
|
||||
4. **safefetch ProxyFromEnvironment**:配置了 HTTP(S)_PROXY 环境变量时拨号级 IP 校验校验的是代理地址而非目标。powverify 已显式 Proxy:nil;其他出站点在代理部署下需知悉此语义。
|
||||
|
||||
@@ -69,7 +69,7 @@ OneImg 是一个功能完整的自托管图床与图片管理系统。它的核
|
||||
- **拖拽上传**:将图片拖入上传区域即可
|
||||
- **批量选择**:一次选择多张图片,配合实时进度条
|
||||
- **URL 远程上传**:输入图片链接,服务端拉取后入库
|
||||
- 支持格式:JPEG / PNG / GIF / WebP / SVG / BMP
|
||||
- 支持格式:JPEG / PNG / GIF / WebP(按实际图片字节校验,不信任浏览器声明的 MIME)
|
||||
|
||||
### 存储架构
|
||||
|
||||
@@ -78,6 +78,7 @@ OneImg 是一个功能完整的自托管图床与图片管理系统。它的核
|
||||
| 存储类型 | 说明 |
|
||||
|----------|------|
|
||||
| 本地磁盘 | 默认存储,数据直接落盘 |
|
||||
| Cloudflare R2 | 独立存储类型,支持专用端点与 CDN、浏览器直传 |
|
||||
| S3 兼容 | 支持 Cloudflare R2、阿里云 OSS 等 S3 协议存储 |
|
||||
| FTP | 传统 FTP 服务器 |
|
||||
| WebDAV | 支持 Nextcloud、坚果云等 WebDAV 服务 |
|
||||
@@ -149,6 +150,7 @@ OneImg 是一个功能完整的自托管图床与图片管理系统。它的核
|
||||
git clone https://github.com/onexru/oneimg.git
|
||||
cd oneimg
|
||||
docker compose up -d
|
||||
docker compose exec oneimg cat /app/data/.initial_admin_password
|
||||
```
|
||||
|
||||
启动后访问 `http://localhost:8080`
|
||||
@@ -159,19 +161,35 @@ docker compose up -d
|
||||
docker run -d \
|
||||
--name oneimg \
|
||||
-p 8080:8080 \
|
||||
-e APP_URL=https://img.example.com \
|
||||
-v /data/oneimg:/app/data \
|
||||
-v /data/oneimg-uploads:/app/uploads \
|
||||
--restart unless-stopped \
|
||||
onexru/oneimg-oneimg
|
||||
|
||||
# 查看首次启动生成的随机管理员密码
|
||||
docker exec oneimg cat /app/data/.initial_admin_password
|
||||
```
|
||||
|
||||
### 默认账号
|
||||
### 初始账号与密码
|
||||
|
||||
```text
|
||||
账号:admin
|
||||
密码:123456
|
||||
账号:admin(由 DEFAULT_USER 决定)
|
||||
密码:首次启动自动生成,见 data/.initial_admin_password
|
||||
```
|
||||
|
||||
> 首次部署后请立即修改默认密码,并根据实际环境调整 `.env` 配置。
|
||||
密码生成规则:
|
||||
|
||||
| `DEFAULT_PASS` | 行为 |
|
||||
|---|---|
|
||||
| 留空(推荐) | 仅在数据库中还没有任何用户时,生成 43 字符随机密码写入 `data/.initial_admin_password`(权限 `0600`),**不打印到日志** |
|
||||
| 非空 | 直接使用该值作为初始管理员密码 |
|
||||
|
||||
- 该文件只在首次创建管理员时写入;之后重启不会覆盖,也不会重置已有账号的密码。
|
||||
- 密码**不会**出现在启动日志里,必须读取该文件获取。
|
||||
- 登录后请立即修改密码,并删除该文件。
|
||||
|
||||
> ⚠️ 历史 `.env` 模板里曾有 `DEFAULT_PASS=123456`,若你的 `.env` 还保留这一行,它会被当作初始密码注入。请删除该行或改成强密码。仓库现在提供的模板已改为留空。
|
||||
|
||||
---
|
||||
|
||||
@@ -206,7 +224,50 @@ docker run -d \
|
||||
|
||||
### 配置方式
|
||||
|
||||
通过环境变量或项目根目录下的 `.env` 文件进行调整,关键配置项包括存储后端凭证、安全策略、上传限制等。
|
||||
所有配置都可以**直接在容器编排里设置**,不需要进容器改 `/app/.env`。
|
||||
|
||||
**Docker Compose**:编辑 `docker-compose.yml` 的 `environment` 段,或把 `.env.example` 复制为 `.env`(compose 会自动读取并替换 `${VAR}`):
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
vim .env # 至少改 APP_URL
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
**docker run**:用 `-e` 逐个传入,例如:
|
||||
|
||||
```bash
|
||||
docker run -d --name oneimg -p 8080:8080 \
|
||||
-e APP_URL=https://img.example.com \
|
||||
-e DEFAULT_USER=admin \
|
||||
-e MAX_FILE_SIZE=20971520 \
|
||||
-e TRUSTED_PROXIES=172.17.0.0/16 \
|
||||
-v /data/oneimg:/app/data \
|
||||
-v /data/oneimg-uploads:/app/uploads \
|
||||
onexru/oneimg-oneimg
|
||||
```
|
||||
|
||||
**优先级**:编排注入的环境变量 > 容器内自动生成的 `/app/.env`。
|
||||
|
||||
应用首次启动时若发现工作目录没有 `.env` 会自动生成一份模板,但加载时(godotenv)**不会覆盖已存在的环境变量**,所以容器注入的值始终生效,容器内 `.env` 只用来补全未注入的默认项。这也意味着容器里那份 `.env` 可以完全不管。
|
||||
|
||||
> 早期版本会把 `.env` 文件放在容器内,重建容器即丢失;现在密钥类的自动生成值都落在 `./data` 挂载卷里(`data/.config_secret`、`data/.initial_admin_password`),持久化与重建都不会变。
|
||||
|
||||
常用变量:
|
||||
|
||||
| 变量 | 默认值 | 说明 |
|
||||
|---|---|---|
|
||||
| `APP_URL` | `http://localhost:8080` | **公网必改**。API 返回的图片 URL 取自该值 |
|
||||
| `SERVER_PORT` | `8080` | 监听端口 |
|
||||
| `DB_TYPE` | `sqlite` | `sqlite` / `mysql` / `postgres` |
|
||||
| `DEFAULT_USER` / `DEFAULT_PASS` | `admin` / 空 | 初始管理员;`DEFAULT_PASS` 留空则随机生成 |
|
||||
| `SESSION_SECRET` | 空(自动生成) | 会话签名密钥 |
|
||||
| `CONFIG_SECRET` | 空(自动生成) | 配置与图片加密密钥,显式设置必须 ≥32 字符且不可更换 |
|
||||
| `MAX_FILE_SIZE` | `10485760` | 单文件上限(字节),另有 32MB 硬上限 |
|
||||
| `ALLOWED_TYPES` | jpeg/png/gif/webp | 允许的 MIME,逗号分隔 |
|
||||
| `TRUSTED_PROXIES` | 空 | 反代信任的 IP/CIDR,留空表示不信任任何代理 |
|
||||
|
||||
完整清单见 [`.env.example`](.env.example)。
|
||||
|
||||
---
|
||||
|
||||
|
||||
+70
-9
@@ -1,21 +1,82 @@
|
||||
# 初春图床 oneImg —— 容器编排
|
||||
#
|
||||
# 所有可配置项都已在下面的 environment 中暴露,无需进入容器改 /app/.env:
|
||||
# 直接改本文件,或用同目录的 .env 提供值(docker compose 会自动读取它做变量替换)。
|
||||
#
|
||||
# 优先级:本文件的 environment / .env > 容器内自动生成的 /app/.env
|
||||
# 应用启动时若发现 /app/.env 不存在会自动生成一份模板,但 godotenv 不会覆盖
|
||||
# 已存在的进程环境变量,因此这里注入的值始终生效,容器内 .env 只用于补全默认值。
|
||||
#
|
||||
# 因此容器内 /app/.env 可以完全不管;需要持久化的只有 ./data 与 ./uploads。
|
||||
|
||||
services:
|
||||
oneimg:
|
||||
build: .
|
||||
# 也可改用官方镜像:image: onexru/oneimg-oneimg
|
||||
# 或加载离线包:docker load -i oneImg_Docker_amd64_v3.5.6.tar(镜像名 oneimg:v3.5.6-amd64)
|
||||
ports:
|
||||
- "8080:8080"
|
||||
- "${SERVER_PORT:-8080}:${SERVER_PORT:-8080}"
|
||||
environment:
|
||||
# 站点对外访问地址:v4.5.5 起 API 返回的图片 URL 固定取自 APP_URL,
|
||||
# 不再反射请求 Host(Host/X-Forwarded-Host 注入已在上游修复)。
|
||||
# 部署时必须设为实际公网地址,如 http://31.57.10.10:18080
|
||||
- APP_URL=http://localhost:8080
|
||||
# 反向代理信任列表(可选):仅在 nginx 等反代后部署时配置,
|
||||
# 留空表示不信任任何代理的 X-Forwarded-For
|
||||
# - TRUSTED_PROXIES=172.17.0.0/16
|
||||
# ── 服务器 ───────────────────────────────────────────────
|
||||
# 监听端口(镜像内 EXPOSE 8080,改动时上面的 ports 会跟着变)
|
||||
- SERVER_PORT=${SERVER_PORT:-8080}
|
||||
# 站点对外访问地址。API 返回的图片 URL 固定取自该值,不再反射请求 Host,
|
||||
# 公网部署必须改成实际地址,如 https://img.example.com
|
||||
- APP_URL=${APP_URL:-http://localhost:8080}
|
||||
|
||||
# ── 数据库 ───────────────────────────────────────────────
|
||||
# sqlite | mysql | postgres
|
||||
- DB_TYPE=${DB_TYPE:-sqlite}
|
||||
- SQLITE_PATH=${SQLITE_PATH:-./data/data.db}
|
||||
# 用 mysql/postgres 时额外填下面几项(sqlite 下会被忽略)
|
||||
- DB_HOST=${DB_HOST:-localhost}
|
||||
- DB_PORT=${DB_PORT:-3306}
|
||||
- DB_USER=${DB_USER:-root}
|
||||
- DB_PASSWORD=${DB_PASSWORD:-}
|
||||
- DB_NAME=${DB_NAME:-oneimg}
|
||||
# CA 证书路径。留空使用系统 CA;证书验证默认开启,路径错误会拒绝启动。
|
||||
- DB_CA_CERT_PATH=${DB_CA_CERT_PATH:-./ca/isrgrootx1.pem}
|
||||
- DB_SKIP_CERT_VERIFY=${DB_SKIP_CERT_VERIFY:-false}
|
||||
- DB_MAX_OPEN_CONNS=${DB_MAX_OPEN_CONNS:-10}
|
||||
- DB_MAX_IDLE_CONNS=${DB_MAX_IDLE_CONNS:-2}
|
||||
- DB_CONN_MAX_LIFETIME=${DB_CONN_MAX_LIFETIME:-30m}
|
||||
- DB_CONN_MAX_IDLE_TIME=${DB_CONN_MAX_IDLE_TIME:-5m}
|
||||
|
||||
# ── 上传 ─────────────────────────────────────────────────
|
||||
- UPLOAD_ROOT=${UPLOAD_ROOT:-./uploads}
|
||||
# 单文件上限(字节),上限被程序内 32MB 硬限制再收一次
|
||||
- MAX_FILE_SIZE=${MAX_FILE_SIZE:-10485760}
|
||||
# SVG 不再作为普通图片接受上传;留空则默认 jpeg/png/gif/webp
|
||||
- ALLOWED_TYPES=${ALLOWED_TYPES:-image/jpeg,image/png,image/gif,image/webp}
|
||||
|
||||
# ── 初始管理员 ───────────────────────────────────────────
|
||||
- DEFAULT_USER=${DEFAULT_USER:-admin}
|
||||
# 留空(推荐):仅在首次创建管理员时生成 43 字符随机密码,写入
|
||||
# ./data/.initial_admin_password(权限 0600),不打印到日志。
|
||||
# docker compose exec oneimg cat /app/data/.initial_admin_password
|
||||
# 非空:直接使用该值作为初始密码。
|
||||
# ⚠ 若同目录 .env 里残留 DEFAULT_PASS=123456,会被注入成管理员密码,请删除该行。
|
||||
- DEFAULT_PASS=${DEFAULT_PASS:-}
|
||||
|
||||
# ── 密钥 ─────────────────────────────────────────────────
|
||||
# 留空自动生成。SESSION_SECRET 已存在时用于签发会话;
|
||||
# CONFIG_SECRET 用于加密存储凭证与图片文件,留空时自动生成并持久化到
|
||||
# data/.config_secret(随 ./data 卷保留,重建容器不会变),
|
||||
# 一旦启用加密存储就不可更换,否则历史内容无法解密。
|
||||
# 显式配置时 CONFIG_SECRET 必须 >= 32 字符,否则启动直接失败。
|
||||
- SESSION_SECRET=${SESSION_SECRET:-}
|
||||
- CONFIG_SECRET=${CONFIG_SECRET:-}
|
||||
|
||||
# ── 反向代理 ─────────────────────────────────────────────
|
||||
# 逗号分隔 IP/CIDR。仅这些来源的 X-Forwarded-For 会被采信为客户端 IP;
|
||||
# 留空表示不信任任何代理(直连部署保持留空)。
|
||||
- TRUSTED_PROXIES=${TRUSTED_PROXIES:-}
|
||||
volumes:
|
||||
- ./data:/app/data
|
||||
- ./uploads:/app/uploads
|
||||
restart: unless-stopped
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
max-file: "3"
|
||||
Reference in new issue
Block a user