Files
FeedLite/config.example.php
T
laoyang cede838b5e FeedLite 初始提交:通用轻量级反馈系统(PHP + SQLite,零依赖)
- 前台:问题列表 / 详情 / 发布与回复(趣味问答验证码、蜜罐、IP 限流)
- 后台:先审后显、站点设置(站点标题/描述、附件存储、OSS 参数)、操作日志
- 附件:关闭 / 本机硬盘 / 阿里云 OSS 浏览器直传(ECS 实例 RAM 角色)三种模式
- 品牌资源:全套图标(favicon.ico / SVG / PNG 各尺寸 / manifest)
- 安全:CSRF、session 加固、.htaccess 屏蔽敏感文件、口令仅存哈希
- 配置:config.example.php 为模板,config.php 不入库
2026-09-28 20:34:37 +08:00

168 lines
9.6 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* FeedLite · 轻反馈 · 配置文件
* ------------------------------------------------------------------
* 部署后请务必修改 admin_password 与 api_token(及 ip_salt),
* 并按需填写下方的 smtp 段以开启"回复邮件通知"。
*/
return [
/* ---------------- 基本 ---------------- */
// SQLite 数据库文件路径。
// 放在站内 data/ 目录(已被 .htaccess 拒绝直接访问);也可改为站点目录之外的绝对路径。
'db_path' => __DIR__ . '/data/feedback.db',
'site_name' => '轻反馈',
'site_desc' => '欢迎在这里反馈使用问题、提出功能建议。任何人都可以提问与回复,无需注册;只需填写昵称与邮箱。',
// 展示用的官方邮箱(可留空)
'admin_email' => 'support@example.com',
// 站点根地址(用于邮件正文里的链接)。留空则按访问域名自动探测。
// 例如:'https://feedback.example.com'
'base_url' => '',
/* ---------------- 安全 ---------------- */
// 管理员口令:在"回复"表单里填入它,即以「官方」身份回复(高亮显示),并触发邮件通知。
// ★★ 请务必修改! ★★
'admin_password' => 'CHANGE_ME_admin',
// API 令牌:供自动化脚本 / AI 读取数据用。★ 请务必修改 ★
'api_token' => 'CHANGE_ME_api_token',
// 对访客 IP 做加盐哈希(数据库只保存哈希,不保存明文 IP)。★ 请修改为随机值 ★
'ip_salt' => 'CHANGE_ME_random_salt',
/* ---------------- 问题分类 ---------------- */
'categories' => [
'usage' => '使用问题',
'bug' => 'Bug 反馈',
'feature' => '功能建议',
'sync' => '同步问题',
'other' => '其他',
],
/* ---------------- 处理状态 ---------------- */
'statuses' => [
'open' => '待处理',
'doing' => '处理中',
'resolved' => '已解决',
'closed' => '已关闭',
],
/* ---------------- 邮件通知(SMTP) ---------------- */
'smtp' => [
'enabled' => false, // 填好下面参数后改为 true 才会真正发信
'host' => 'smtp.example.com', // 如 smtp.qiye.aliyun.com / smtp.exmail.qq.com
'port' => 465,
'secure' => 'ssl', // ssl(465)| tls(587 STARTTLS)| ''(25 不加密)
'user' => 'noreply@example.com',
'pass' => '', // 邮箱密码或"授权码"
'from' => 'noreply@example.com', // 发件地址(通常与 user 相同)
'from_name' => '轻反馈',
'timeout' => 15,
'verify_ssl' => true, // 若服务器缺少 CA 证书可临时设为 false
],
// 通知策略
'notify' => [
'enabled' => true, // 回复时是否尝试发送通知邮件
'on_every_reply' => true, // true=任何人回复都通知发帖人;false=仅"官方"回复才通知
'cooldown_seconds' => 300, // 同一帖同一收件人的通知节流(秒)
],
/* ---------------- 审核(先审后显) ----------------
* enabled = true:新提交的问题默认**不公开**,由管理员在 admin.php 审核;
* · 通过 → 公开显示(visible=1)
* · 关闭 → 判定"不是应用的问题",保持不公开,并把管理员填写的说明邮件发给提问人
* 审核后台入口:/feedback/admin.php(口令= admin_password)
*/
'moderation' => [
'enabled' => true,
'close_mail_subject' => '关于你反馈的问题《%s》', // %s 会替换成问题标题
],
/* ---------------- 附件上传(阿里云 OSS 直传) ----------------
* 浏览器把文件「直接」传到 OSS,不经过本站服务器 —— 因此不占用服务器磁盘、不消耗服务器带宽,
* 也就不会出现"硬盘被挤爆"的风险。服务器只做两件事:
* 1) 下发一段有时效的上传凭证(签名),限制能传到哪个路径、多大、什么类型;
* 2) 提交表单时校验对象确实存在且合规,并把元信息写进 SQLite。
*
* ★ 凭证方式:ECS 实例 RAM 角色(唯一支持的方式,服务器上不保存长期 AccessKey)
* 给这台 ECS 绑定一个 RAM 角色后,程序从内网元数据服务
* (http://100.100.100.200,链路本地地址、不出公网)读取一份「有时效、
* 会自动周期轮换」的临时凭证来签名。AccessKey 永不落盘,也永不进本文件。
*
* ★ 开通步骤(详见 README.md「5.1 开通与配置」):
* ① 创建 Bucket(读写权限建议「公共读」;想更严可用 private,本程序会自动签发访问 URL)
* ② RAM 建权限策略:只授予该 Bucket(某前缀下)的 oss:PutObject / oss:GetObject / oss:DeleteObject
* ③ RAM 建角色(如 FeedLiteOssRole)并赋予上一步的策略
* ④ ECS 控制台把该角色【授予本实例】
* ⑤ Bucket → 数据安全 → 跨域设置(CORS):来源填你的站点域名,方法勾 POST/GET/HEAD
* ⑥ 把 endpoint / bucket / instance_role 填到下面,最后 enabled = true
* ⑦(可选但强烈推荐)绑定自定义域名,避免默认域名带 Content-Disposition 被迫下载
*
* ★ 前提:站点必须运行在【阿里云 ECS】上并且已绑定 RAM 角色;
* 未绑定则取不到凭证,上传接口会明确报错(其它功能不受影响)。
*/
'oss' => [
'enabled' => false, // 填好参数后改为 true 才启用上传
'endpoint' => 'oss-cn-beijing.aliyuncs.com', // 不含 http://,如 oss-cn-hangzhou.aliyuncs.com
'bucket' => 'your-bucket-name',
// ★ ECS 实例 RAM 角色名 —— 必须与【ECS 实例实际绑定的角色名】逐字一致。
// 查法:curl http://100.100.100.200/latest/meta-data/ram/security-credentials/
// 注意:RAM 里"创建的角色名"和"授予实例后实例上生效的角色名"可能不同(如
// 建的是 MyOssRole,授予实例后生效名可能是系统预置策略对应的角色),以查询结果为准。
'instance_role' => '',
// ---- 以下一般不用改 ----
'metadata_url' => '', // 留空=http://100.100.100.200(ECS 内网元数据服务)
'metadata_v2' => false, // true=加固模式(先取一次性 token 再读元数据,防 SSRF 探测)
'metadata_ttl' => 600, // 加固模式 token 有效期(秒,最长 21600)
'credential_cache' => '', // 凭证缓存文件;留空=与数据库同目录的 oss.sts.php
'credential_refresh_margin' => 300, // 到期前多少秒就提前换新(秒)
'domain' => '', // 自定义访问域名,如 https://fb-img.example.com(留空用默认域名)
'url_scheme' => 'https', // 拼接访问地址时使用的协议
'prefix' => 'fb', // 对象键前缀:fb/2026/09/xxxxxxxx.jpg
'visibility' => 'public', // public=直接可读 | private=展示时生成签名 URL
'sign_ttl' => 600, // 上传凭证有效期(秒)
'link_ttl' => 604800, // private 模式下展示链接的有效期(秒)
'image_process' => true, // 列表缩略图使用 OSS 图片处理(免费额度内,省流量)
'verify' => true, // 提交时 HEAD 复核对象(防伪造/防超限)
'host_override' => '', // 仅特殊网关/联调使用;留空自动按 bucket.endpoint 拼接
],
/* ---------------- 附件限额 ----------------
* 单位:字节。原图上限指「压缩前」的原始文件大小(前端会先压缩到最长边 1600px)。
*/
'upload' => [
'image_max_per_post' => 4,
'image_max_bytes' => 5242880, // 5 MB / 张
'image_exts' => ['jpg', 'jpeg', 'png', 'webp', 'gif'],
'image_mimes' => ['image/jpeg', 'image/png', 'image/webp', 'image/gif'],
'image_max_side' => 1600, // 前端压缩后的最长边(像素)
'video_max_per_post' => 1,
'video_max_bytes' => 52428800, // 50 MB / 个
'video_exts' => ['mp4', 'mov', 'webm'],
'video_mimes' => ['video/mp4', 'video/quicktime', 'video/webm'],
'total_cap_bytes' => 1073741824, // 全站附件总量上限 1 GB,达到后暂停接收新上传
'retention_days' => 365, // 附件保留天数,超期由 cron.php 清理
'upload_per_hour' => 60, // 每 IP 每小时最多申请多少次上传凭证
],
/* ---------------- 反垃圾 ---------------- */
'rate_limit' => [
'thread_per_hour' => 5, // 每个 IP 每小时最多发起的主题数
'reply_per_hour' => 20, // 每个 IP 每小时最多回复数
],
'post_min_seconds' => 3, // 打开表单到提交不得少于该秒数(过快视为机器人)
/* ---------------- 列表 ---------------- */
'page_size' => 20,
];