使用说明
面向部署者和日常使用者的完整参考。配置示例可直接复制使用,遇到问题先翻一遍这里。
项目简介
LitePic 面向个人站长、自托管用户和轻量团队,提供一个开箱即用的 PHP 图床后台。它不依赖复杂服务栈,把上传、缩略图、压缩、WebP / AVIF 转换、图库与相册、访问统计和 R2/S3 同步集中在一个简洁的单机应用里(嵌入式 SQLite,无需单独数据库服务)。
LitePic 的核心思路是 先保证图片成功入库,再异步处理耗时任务。压缩、转换、水印、缩略图或远程同步失败时,不会拖垮上传流程;系统会记录处理结果,方便后续排查和批量补处理。日常使用时,你可以直接复制 URL、HTML、Markdown、BBCode,也可以在图库中批量压缩、转换和删除。
核心功能
上传能力
支持单图/多图、拖拽、粘贴上传。上传页全屏布局,无额外滚动条,体验沉浸。
缩略图机制
上传后自动生成缩略图,图库列表优先展示缩略图,复制和查看使用原图地址。SVG 可识别宽高时显示分辨率,无法识别时显示「矢量图」。
自动压缩
支持 ImageMagick / GD / TinyPNG 三种压缩方式。不可压缩格式自动跳过,不阻塞上传。支持批量压缩与压缩比例回显。
格式转换
支持 JPG/JPEG/PNG/GIF 转换为 WebP 或 AVIF。可在设置中选择偏好格式,图库批量按钮与处理链路自动适配。
图库管理
支持批量选择、批量删除(带确认对话框防误触)、批量压缩、批量格式转换、复制多种链接格式。分页采用 POST→GET 重定向,刷新无提示。
统计分析
提供访问量、图片数、空间占用、文件类型分布、时间维度统计。概览页采用环形卡片 + 图表 + 表格组合设计。
Passkey 登录
除传统 API Key 登录外,支持 WebAuthn / Passkey 无密码登录。支持注册多个凭证,随时撤销。
R2/S3 远程存储
支持远程备份和云端存储两种用途。备份模式保留本站图片地址;云端存储模式会让复制链接、API 返回和图库图片优先使用 R2/S3 公网地址。
FrankenPHP 部署(推荐)
LitePic 默认推荐 FrankenPHP 经典模式(内置 Caddy + PHP)。仓库根目录已带 Caddyfile:敏感路径拒绝、php_ini 上传上限、try_files 兜底都已写好。 仍可用 Nginx + PHP-FPM(见仓库 nginx-litepic.conf),但新站优先按本节走。
不要开 worker mode。LitePic 的配置缓存与 Session 按「每请求独立 boot」设计;worker 常驻会导致设置变更不生效、登录态异常。
- 安装 FrankenPHP(二进制或 Docker
dunglas/frankenphp)。 - 解压 / clone LitePic 到站点目录,复制
.env.example→.env,改好SITE_URL。 - 创建可写目录,并把属主改成跑 PHP 的用户(见下方「目录权限」)。
- 用仓库自带
Caddyfile启动;生产用SERVER_NAME开自动 HTTPS。 - 浏览器打开站点,默认密码
12345678登录后立刻改密;大批量处理再加一行worker.phpcron。
本机 / VPS 启动
在 LitePic 根目录执行。未设 SERVER_NAME 时默认监听 :8080(无 TLS)。
cd /path/to/LitePic
cp -n .env.example .env
mkdir -p uploads data logs
# systemd 官方包通常以 frankenphp 用户运行:
sudo chown -R frankenphp:frankenphp uploads data logs
# 若用当前用户直接 frankenphp run,可改为:
# chown -R "$(id -u):$(id -g)" uploads data logs
chmod -R u+rwX,g+rwX uploads data logs# 生产:换成你的域名
SERVER_NAME=img.example.com frankenphp run --config ./Caddyfile
# 本地试跑
frankenphp run --config ./Caddyfile
# → http://127.0.0.1:8080[Unit]
Description=LitePic (FrankenPHP)
After=network.target
[Service]
Type=simple
User=frankenphp
Group=frankenphp
WorkingDirectory=/var/www/litepic
Environment=SERVER_NAME=img.example.com
ExecStart=/usr/bin/frankenphp run --config /var/www/litepic/Caddyfile
Restart=on-failure
[Install]
WantedBy=multi-user.targetDocker
挂载整个站点目录;SERVER_NAME 用于证书与虚拟主机。
docker run --rm -d \
--name litepic \
-p 80:80 -p 443:443 \
-v "$PWD":/app \
-e SERVER_NAME=img.example.com \
-w /app \
dunglas/frankenphp \
frankenphp run --config /app/CaddyfileCaddyfile 要点
完整文件见仓库根目录。下面摘录与上传、安全相关的关键项;改完后 frankenphp reload 或重启服务。
{
frankenphp {
php_ini {
upload_max_filesize 200M
post_max_size 220M
max_file_uploads 50
memory_limit 256M
max_input_time 600
}
}
servers {
timeouts {
read_body 10m
}
}
}
{$SERVER_NAME::8080} {
root * {$LITEPIC_ROOT:.}
request_body {
max_size 200MB
}
@denied {
path /.env* /.git* /.user.ini /data/* /logs/* /app/* /bin/*
path_regexp php_in_uploads (?i)^/uploads/.*\.php$
}
respond @denied 403
php_server
}php_ini替代 PHP-FPM 的.user.ini/php.ini。request_body max_size对齐大文件上传,避免 Caddy 先拦请求。@denied挡住.env、data/、logs/以及 uploads 下的 PHP。php_server负责「有文件则直出,否则进index.php」,自定义图床前缀依赖它。
目录权限(必看)
上传报「保存失败 / Permission denied」时,几乎都是目录属主 ≠ FrankenPHP 进程用户。 官方 systemd 单元默认 User=frankenphp;若用面板或脚本把 uploads chown 成 www-data 且权限为 755,进程就写不进去。
# 查看进程用户
ps aux | grep frankenphp
# 对齐可写目录(按实际用户改名)
sudo chown -R frankenphp:frankenphp /path/to/LitePic/uploads \
/path/to/LitePic/data /path/to/LitePic/logs
sudo chmod -R u+rwX,g+rwX /path/to/LitePic/uploads \
/path/to/LitePic/data /path/to/LitePic/logs异步队列 cron
上传只写原图并入队;缩略图 / 压缩 / 转换 / 水印由 worker 消费。建议每分钟跑一次:
* * * * * php /path/to/LitePic/worker.php >/dev/null 2>&1可配置项
下面是 LitePic 后台 设置 里的关键开关清单。保存后写入 SQLite 设置表(不是覆盖 .env); PHP-FPM 场景还会同步站点根目录 .user.ini。.env 主要用于首次导入默认值。 装好后进入 设置 → 基础 → 环境信息 可查看当前实际生效值。
| 自动压缩 | 上传后自动执行压缩(主要 JPG/JPEG/PNG)。压缩后端在「压缩方式」里三选一。 |
|---|---|
| 自动转换 | 上传后按偏好格式转换。需要 GD 的 imagewebp/imageavif,或 Imagick 支持对应格式;引擎在「转换引擎」里可选 auto / imagick / gd。 |
| 偏好格式 | 图库批量按钮与自动转换链路的首选目标(WebP / AVIF / JPG / PNG)。 |
| 保留原图 | 格式转换成功后是否保留原始文件。关闭后只留最终文件,节省空间。 |
| 转换引擎 | auto(Imagick 优先,失败回退 GD)/ imagick / gd。与压缩方式相互独立。 |
| 防盗链 | 开启后公网图片链接强制走 /i/<文件>,由 PHP 校验 Referer。详见 开启防盗链。 |
| 水印 | 上传后自动加文字或 PNG 图片水印。详见 水印设置。 |
| 最大上传大小 | 应用层 MAX_FILE_SIZE;还需对齐 FrankenPHP Caddyfile php_ini 或 PHP-FPM / Nginx 上限。详见 PHP 上传限制。 |
| 允许上传格式 | 可在后台增删扩展名(含 HEIC/HEIF 等,视服务器能力)。 |
| R2 / S3 | 支持「远程备份」(保留本站链接)和「云端存储」(链接走公网域名)。 |
| 登录方式 | 管理员密码(bcrypt)+ Passkey,详见 认证与安全。 |
检查实际生效值:进入 设置 → 基础 → 环境信息 可看 PHP 版本、GD / Imagick、AVIF/WebP/HEIC 能力、Web 服务器、上传上限等。
压缩方式选择
设置页的「压缩方式」只影响 JPG/JPEG/PNG 的压缩链路,与「转换引擎 / WebP·AVIF 转换」相互独立。
TinyPNG
走外部 TinyPNG API。需要 API Key 与外网。超过约 5MB 的大图、或 API 失败/超时,会自动回退 ImageMagick 本地压缩。
GD
PHP 常见内置扩展,部署简单,适合基础 JPG/PNG 压缩。画质与大图能力通常弱于 ImageMagick。
ImageMagick
走 Imagick 扩展(或本机 magick/convert)。适合更大图片与更稳的压缩;推荐生产环境安装 imagick。
转换策略:格式转换由「转换引擎」控制(默认 Imagick 优先、回退 GD)。单张转换可同步返回;图库批量选 2 张及以上时常进异步队列。
修改 PHP 上传限制
应用层上限在后台保存到 SQLite(键 MAX_FILE_SIZE / MAX_FILE_SIZE_MB),默认示例多为 20MB。真正拦大文件的是运行环境:FrankenPHP 看 Caddyfile 的 php_ini + request_body; PHP-FPM 看 php.ini / .user.ini,Nginx 还要 client_max_body_size。 三者取最严;仓库默认 Caddyfile 已放开到约 200MB,可按需下调。
- 进入 设置 → 基础,修改「最大上传大小(MB)」并保存。
- 确认 PHP
upload_max_filesize≥ 该值,且post_max_size略大。 - FrankenPHP:同步改 Caddyfile 后 reload;Nginx:再改
client_max_body_size。 - 重载服务后到 设置 → 基础 → 环境信息 核对「上传上限」。
FrankenPHP(推荐)
不走 .user.ini。数值需 ≥ 后台设置;下面与仓库默认 Caddyfile 对齐。
frankenphp {
php_ini {
upload_max_filesize 200M
post_max_size 220M
max_file_uploads 50
memory_limit 256M
}
}
request_body {
max_size 200MB
}frankenphp reload --config /path/to/LitePic/Caddyfile
# 或 systemctl reload frankenphpphp.ini / PHP-FPM
适用于自建环境、Docker、宝塔面板 PHP 配置页等,改完后需要重载当前 PHP-FPM。
upload_max_filesize = 200M
post_max_size = 220M
max_file_uploads = 50
memory_limit = 256M
max_execution_time = 600
max_input_time = 600sudo systemctl restart php8.3-fpm
sudo systemctl reload nginxNginx / Apache
Nginx 默认限制请求体大小,需要单独放开;Apache 的 .htaccess 仅在 mod_php 环境下支持 php_value。
server {
client_max_body_size 200m;
}php_value upload_max_filesize 200M
php_value post_max_size 220M
php_value memory_limit 256M
php_value max_execution_time 600.user.ini(PHP-FPM)
PHP-FPM 常用;后台保存上传相关设置时可能同步写入。FrankenPHP 请改 Caddyfile,不必依赖本文件。
open_basedir=/path/to/LitePic/:/tmp/:/proc/cpuinfo:/proc/meminfo:/proc/uptime:/etc/os-release
upload_max_filesize=200M
post_max_size=220M
max_file_uploads=50
memory_limit=256M验证:环境信息卡片的上传上限;或 php -i | grep -E "upload_max_filesize|post_max_size|memory_limit"。 未生效通常是服务未重载、Caddy/Nginx 请求体限制更严,或面板上层限制更低。
开启防盗链
LitePic 的防盗链由 PHP 在 /i/<文件> 路由上校验 Referer,不依赖写入 .htaccess,也不要求你先改 Nginx/Caddy 规则。 开启后,后台复制出的公网图片链接会统一走 /i/...(由 image.php → ImageServeService 提供)。
- 进入 设置 → 图片处理,填写「防盗链允许域名」(英文逗号分隔)。
- 开启「启用防盗链(开启后图片链接强制走
/i/<文件>由 PHP 校验 Referer)」,保存。 - 用新复制的链接测试:本站页面内嵌应正常;外站盗链应 403。
- (可选加固)若仍担心有人猜到物理路径直链
/uploads/...,可在 Web 服务器额外禁止公网访问该目录,或只允许本机反代——这是可选加固,不是当前防盗链的主路径。
工作原理
- 开关
HOTLINK_PROTECTION_ENABLED是唯一真相源。 - 开启后 URL 生成走
/i/<identifier>;请求时检查 Referer 是否落在站点域名或允许列表。 - FrankenPHP / Nginx 只需保证动态路由能进 PHP(仓库 Caddyfile 的
php_server已覆盖)。
注意
物理文件仍在 uploads/(或你配置的存储目录)。若 Web 服务器把该目录当静态文件直接公开,旧书签或猜路径仍可能绕过 Referer 校验。 需要严格隔离时,请在服务器层限制直链,并统一对外只暴露 /i/。
说明:Referer 防盗链适合拦普通外站引用,不能当鉴权。关闭防盗链后,链接样式回退到「图片链接格式」配置(例如存储目录前缀)。
允许无来源请求是什么意思?
图片防盗链主要依赖浏览器请求里的 Referer 判断来源。「无来源请求」就是请求里没有 Referer,常见于直接打开图片地址、复制 URL 到新标签页、隐私浏览器、浏览器插件隐藏来源,或聊天软件、App、代理/CDN 请求图片时没有传来源。
- 开启后:没有
Referer的请求会放行,用户可以直接打开图片链接;防盗链主要拦截带有外站Referer的盗链请求。 - 关闭后:没有
Referer的请求也会被拒绝,规则更严格,但直接打开图片链接、部分隐私浏览器或 App 访问图片可能失败。 - 建议默认开启。这样不影响正常分享图片链接,同时还能拦截大多数外站直接引用。
水印设置
文字水印默认使用白色文字,并在文字背后生成半透明磨砂底层。字体会优先使用服务器上的 Ubuntu 字体;没有 Ubuntu 字体时会回退到系统可用字体或 GD 内置字体。
- 进入 设置 → 图片处理,开启「启用水印」。
- 选择文字或 PNG 图片水印;文字水印可开「磨砂底层」并调透明度 / 内边距 / 圆角。
- 需要自定义字体时,上传
TTF/OTF(中文请用含中文字形的字体)。 - PNG 水印请用透明背景;配置后优先使用图片水印。
建议:PNG 图片水印请使用透明背景,并把最大宽度控制在原图宽度的 20% 到 30% 之间,避免遮挡图片主体。
开启 WebP 转换
WebP 转换由「转换引擎」完成:默认 auto(Imagick 优先,不可用则回退 GD imagewebp())。 「压缩方式」里的 ImageMagick / GD / TinyPNG 只影响压缩,不等于转换能力。
- 进入 设置 → 图片处理,将「转换优先格式」设为 WebP。
- 开启上传后自动转换(或图库批量转换),保存。
- 在 设置 → 基础 → 环境信息 确认 WebP 能力为已启用(GD 或 Imagick 任一即可)。
- 上传 JPG/PNG/GIF/HEIC 等源图测试。
Debian / Ubuntu
建议同时装 GD 与 Imagick,转换与压缩都更稳。
sudo apt update
sudo apt install -y php-gd php-imagick webp imagemagick
# FrankenPHP 用户:装对应 php-zts / 扩展后 reload frankenphp
sudo systemctl restart php8.3-fpm # 仅 PHP-FPM 场景检查 WebP 能力
php -m | grep -Ei "gd|imagick"
php -r 'var_dump(function_exists("imagewebp"));'
# Imagick:后台环境信息也会探测 WEBP 格式面板环境:启用 fileinfo、gd,有条件再装 imagick。 仅 GD 且 imagewebp() 为 false 时,需换带 WebP 的 PHP 构建,或改用 Imagick。
开启 AVIF 转换
AVIF 对环境要求更高。可用路径:GD imageavif()(常需 PHP 8.1+ 且编译支持),或 Imagick 支持 AVIF。 后台「AVIF 支持」徽章会同时认 GD 与 Imagick。
- 确认 PHP / 扩展能力(见下方命令)。
- 进入 设置 → 图片处理,偏好格式选 AVIF,开启自动或批量转换。
- 在环境信息确认「AVIF 支持」已启用。
- 上传测试图,查看处理报告 / 队列结果。
Debian / Ubuntu
sudo apt update
sudo apt install -y php-gd php-imagick imagemagick libavif-bin
sudo systemctl restart php8.3-fpm # PHP-FPM;FrankenPHP 则 reload 服务检查 AVIF 能力
php -v
php -r 'var_dump(function_exists("imageavif"));'
# 或看设置页环境信息「AVIF 支持」徽章排障:GD 无 imageavif 时,可装 Imagick+AVIF,或先用 WebP。批量多张 AVIF 常走异步队列。
上传后处理链路
上传请求只负责校验、落盘原图、写入元数据并入队,尽快返回。耗时工作由队列异步完成(响应后轻量 drain、心跳调度,或 cron 跑 worker.php)。
- 接收文件并完成格式 / 大小校验。
- 保存原图,写入
images表与原始文件名映射。 - 将后处理任务写入
import_queue(缩略图、压缩、转换、水印、远程同步等按配置入队)。 - Worker 消费队列:缩略图 → 压缩 / 格式转换 →(可选)删原图 → 水印 → 最终缩略图 → R2/S3 同步。
- 任一步失败只记报告 / 失败队列,不回滚已成功入库的原图。
注意:目前没有自动 EXIF 清理。大批量上传请配置 cron: cd /path/to/LitePic && php worker.php >> logs/worker.log 2>&1。
认证与安全
管理员密码登录
后台密码优先以 bcrypt 哈希存储(改密后写入设置表)。登录成功后写入会话 Cookie;默认密码 12345678,首次登录会强制修改。
Passkey 登录
基于 WebAuthn,支持指纹 / Face ID / 硬件密钥。在 设置 → 账号 注册或撤销凭证。生产环境需 HTTPS。
- 可在 设置 → 账号 创建多个第三方 API Token,供外部上传接口使用;只在创建时显示一次,可随时撤销。
- TinyPNG API Key 支持多 Key 轮询,并记录调用状态。
- 后台写操作受 CSRF Token 保护。
- 建议生产启用 HTTPS,Token 只放在服务端。
接口与外部接入
上传、导出、后台图片操作与 WordPress 插件说明见 litepic.io/api。
Token 在实例后台创建:登录 → 设置 → 账号 → 新建 API Token。只显示一次。
运维与排障
- 如出现「未压缩 / 未转 WebP / 未转 AVIF」,可在开启调试后查看
logs/YYYY-MM-DD.log的 upload post-process 记录。 - 上传报「保存失败」且日志有
Permission denied:把uploads/data/logs属主改成 FrankenPHP 进程用户(多为frankenphp),详见 FrankenPHP 部署。 - 旧数据迁移后,可使用设置中的扫描功能重建图库数据、缩略图与统计数据。
- 当对象存储配置不完整时,系统会回退为本地可用模式,上传不会被中断。
- 若 AVIF 转换失败,请确认 PHP 版本 ≥ 8.1,且 GD 已编译 AVIF 支持(
php -r 'var_dump(function_exists("imageavif"));')或已装 Imagick + AVIF。