{"id":31698706,"url":"https://github.com/tokenicrat/pelit","last_synced_at":"2026-05-14T12:33:20.412Z","repository":{"id":318469457,"uuid":"1068967322","full_name":"tokenicrat/pelit","owner":"tokenicrat","description":"小而美的私有图床","archived":false,"fork":false,"pushed_at":"2025-11-09T05:00:20.000Z","size":55,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-11-09T06:17:04.393Z","etag":null,"topics":["flask","image-hosting","kiss","typed-python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tokenicrat.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-03T07:36:39.000Z","updated_at":"2025-11-09T04:57:39.000Z","dependencies_parsed_at":"2025-10-07T12:19:37.873Z","dependency_job_id":"c0c5cb4d-4739-4c5f-8f17-976f4b32f06c","html_url":"https://github.com/tokenicrat/pelit","commit_stats":null,"previous_names":["tokenicrat/pelit"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/tokenicrat/pelit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tokenicrat%2Fpelit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tokenicrat%2Fpelit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tokenicrat%2Fpelit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tokenicrat%2Fpelit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tokenicrat","download_url":"https://codeload.github.com/tokenicrat/pelit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tokenicrat%2Fpelit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33025042,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-13T13:14:54.681Z","status":"online","status_checked_at":"2026-05-14T02:00:06.663Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["flask","image-hosting","kiss","typed-python"],"created_at":"2025-10-08T19:10:14.634Z","updated_at":"2026-05-14T12:33:20.405Z","avatar_url":"https://github.com/tokenicrat.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003e [!NOTE]\n\u003e ~~本项目作者想偷懒然后去写 R2 版~~，README 由 AI 生成（代码 0% AI 生成！），只做了最基本的检查，有问题请直接看代码，里面有详细的注释。\n\n# Pelit\n\n小而美的私有图床服务\n\n## 简介\n\nPelit 是一个轻量级的私有图床解决方案，基于 Flask 和 Gunicorn 构建。提供 API 接口，支持简易的文件上传、删除、列表和备份等功能，适合个人低负载使用。\n\n### 特性\n\n- 用 Python 和 Flask 开发，代码简明，手动 hack 适应需求很简单\n- 提供简易的防盗链、认证和备份功能\n- 支持（并推荐）容器化部署\n\n## 快速开始\n\n### 开发环境部署\n\n#### 1. 克隆仓库\n\n```bash\ngit clone https://github.com/tokenicrat/pelit.git\ncd pelit\n```\n\n#### 2. 安装依赖\n\n```bash\npip install -r requirements.txt\n```\n\n#### 3. 配置文件\n\n复制示例配置文件并修改：\n\n```bash\ncp examples/pelit.toml pelit.toml\n```\n\n编辑 `pelit.toml`，至少需要配置：\n\n```toml\nversion = \"0.1.0\"\n\n[network]\nbase_url = \"http://localhost:8000\"  # 你的服务地址\n\n[storage]\npath = \"./data\"  # 存储路径\n\n[auth]\nfrom_env = true  # 从环境变量读取密钥\n```\n\n#### 4. 设置环境变量\n\n```bash\nexport PELIT_AUTH=\"your-secret-key\"\nexport PELIT_CONFIG=\"./pelit.toml\"\n```\n\n#### 5. 启动服务\n\n使用内置工具启动：\n\n```bash\npython -m pelit.app\n```\n\n或使用 Gunicorn（推荐）：\n\n```bash\ngunicorn --config examples/gunicorn.conf.py wsgi:app\n```\n\n### 生产环境部署（Podman）\n\n#### 1. 准备配置文件和数据目录\n\n```bash\nmkdir -p ./data\ncp examples/pelit.toml ./config.toml\n# 编辑 config.toml 配置你的设置\n```\n\n#### 2. 使用 Podman Compose\n\n复制并修改 `examples/compose.yml`：\n\n```bash\ncp examples/compose.yml docker-compose.yml\n# 可以在 compose.yml 中提供密钥环境变量\n```\n\n启动：\n\n```bash\npodman compose up -d\n```\n\n#### 4. Nginx 反向代理（可选）\n\n参考 `examples/pelit.conf` 配置 Nginx：\n\n```nginx\nserver {\n    listen 443 ssl;\n    server_name your-domain.com;\n    \n    ssl_certificate /path/to/cert;\n    ssl_certificate_key /path/to/key;\n    \n    location / {\n        proxy_pass http://localhost:8000;\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n    }\n}\n```\n\n## 配置说明\n\n### 配置文件结构\n\n```toml\nversion = \"0.1.0\"\n\n[network]\n# 下载地址的 URL 前缀，用于生成完整的文件访问地址\nbase_url = \"https://your-domain.com\"\n\n# 反盗链功能（验证 Referer 请求头）\nhotlink_block = false\n# 白名单域名，支持 * 通配符\nhotlink_whitelist = [\"example-a.com\", \"*.example-b.com\"]\n\n[storage]\n# 文件存储路径\npath = \"/data\"\n\n# 存储空间警告阈值（MB），设为 0 禁用\nwarn = 1000\n# 存储空间最大限制（MB），超过后上传失败，设为 0 禁用\nmax = 2000\n\n[auth]\n# 从环境变量 PELIT_AUTH 读取密钥\nfrom_env = true\n\n# 或使用 SHA256 哈希后的密钥（16 进制格式）\n# hashed = \"9EBF8C8F69731148C2DD14C93EB021E58D2CDD253580576C92F6102EF4F0610C\"\n```\n\n### 环境变量\n\n| 变量名 | 说明 | 必需 |\n|--------|------|------|\n| `PELIT_CONFIG` | 配置文件路径 | 是 |\n| `PELIT_AUTH` | 认证密钥（当 `auth.from_env=true` 时） | 条件必需 |\n| `PELIT_VERBOSITY` | 日志级别：0=INFO, 1=WARN, 2=ERROR | 否 |\n| `PELIT_LOG` | 日志文件路径 | 否 |\n\n## API 接口\n\n### 认证\n\n所有需要认证的接口都需要在请求头中包含：\n\n```\nAuthorization: your-secret-key\n```\n\n或使用 Bearer 格式：\n\n```\nAuthorization: Bearer your-secret-key\n```\n\n### 上传文件\n\n**请求**\n\n```http\nPOST /upload/\u003cdirectory\u003e\nContent-Type: multipart/form-data\nAuthorization: your-secret-key\n\nfile: \u003cbinary-file\u003e\n```\n\n**响应**\n\n```json\n{\n  \"success\": true,\n  \"message\": \"保存成功\",\n  \"url\": \"https://your-domain.com/directory/filename.ext\",\n  \"warning\": \"存储空间已达警告值\"  // 可选字段\n}\n```\n\n**状态码**\n\n- `200` - 上传成功\n- `400` - 请求格式错误\n- `401` - 认证失败\n- `403` - 危险请求（路径遍历攻击）\n- `502` - 服务器错误\n\n### 删除文件\n\n**请求**\n\n```http\nDELETE /delete/\u003cdirectory\u003e/\u003cfilename\u003e\nAuthorization: your-secret-key\n```\n\n**响应**\n\n```json\n{\n  \"success\": true,\n  \"message\": \"删除成功\"\n}\n```\n\n**状态码**\n\n- `200` - 删除成功\n- `401` - 认证失败\n- `403` - 危险请求\n- `404` - 文件不存在\n- `502` - 服务器错误\n\n### 列出文件/目录\n\n**请求**\n\n```http\nGET /list\nGET /list/\u003cdirectory\u003e\nAuthorization: your-secret-key\n```\n\n**响应**\n\n```json\n{\n  \"success\": true,\n  \"message\": \"\",\n  \"list\": [\"file1.jpg\", \"file2.png\", \"subdirectory\"]\n}\n```\n\n**状态码**\n\n- `200` - 列举成功\n- `401` - 认证失败\n- `403` - 危险请求\n- `404` - 目录不存在\n- `502` - 服务器错误\n\n### 获取文件\n\n**请求**\n\n```http\nGET /\u003cdirectory\u003e/\u003cfilename\u003e\n```\n\n此接口会验证反盗链设置（如果启用）。\n\n**状态码**\n\n- `200` - 返回文件内容\n- `403` - 反盗链阻止或禁止访问\n- `404` - 文件不存在\n- `502` - 服务器错误\n\n### 创建备份\n\n**请求**\n\n```http\nGET /backup\nGET /backup/\u003cdirectory\u003e\nAuthorization: your-secret-key\n```\n\n**响应**\n\n```json\n{\n  \"success\": true,\n  \"url\": \"https://your-domain.com/backup-file.tar.gz\",\n  \"message\": \"备份任务创建成功\"\n}\n```\n\n备份任务会在后台异步执行，完成后可通过返回的 URL 下载。\n\n**状态码**\n\n- `200` - 备份任务创建成功\n- `401` - 认证失败\n\n## 命令行工具\n\nPelit 提供了命令行工具进行管理操作。\n\n**检查配置**\n\n```bash\npython -m pelit.app check -c /path/to/config.toml\n```\n\n**运行服务**\n\n```bash\npython -m pelit.app run -c /path/to/config.toml -v 0 -l /path/to/log\n```\n\n**参数说明**\n\n- `-c, --config` - 配置文件路径（必需）\n- `-v, --verbose` - 日志级别：0=INFO, 1=WARN, 2=ERROR\n- `-l, --log` - 日志文件路径\n\n### pelit 上传脚本\n\n`src/tools/pelit` 是一个 Bash 脚本，用于简化文件上传操作。\n\n**配置脚本**\n\n编辑脚本中的配置：\n\n```bash\nAPI_URL=\"https://your-domain.com\"\nAUTH=\"your-secret-key\"\n```\n\n**使用方法**\n\n```bash\n# 上传本地文件\n./pelit upload /path/to/file.jpg my-directory\n\n# 上传远程文件（通过 URL）\n./pelit upload https://example.com/image.png my-directory\n\n# 删除文件\n./pelit delete my-directory/file.jpg\n\n# 列出目录\n./pelit list my-directory\n./pelit list /  # 列出根目录\n```\n\n## 安全建议\n\n1. **使用强密钥**：生成随机的强密钥用于认证\n   ```bash\n   openssl rand -hex 32\n   ```\n\n2. **使用哈希密钥**：在生产环境建议使用 SHA256 哈希后的密钥\n   ```bash\n   echo -n \"your-secret-key\" | sha256sum\n   ```\n\n3. **启用 HTTPS**：使用 Nginx 等反向代理提供 SSL/TLS 加密\n\n4. **配置防盗链**：在配置文件中启用 `hotlink_block` 并设置白名单\n\n5. **限制存储空间**：设置 `storage.max` 防止磁盘被占满\n\n6. **定期备份**：使用 `/backup` 接口定期备份数据\n\n## 开发指南\n\n### 项目结构\n\n```\npelit/\n├── src/\n│   ├── pelit/\n│   │   ├── __init__.py\n│   │   ├── app.py           # Flask 应用创建\n│   │   ├── route.py         # 路由定义\n│   │   └── plib/            # 工具库\n│   │       ├── arg.py       # 参数解析\n│   │       ├── config.py    # 配置文件解析\n│   │       ├── log.py       # 日志模块\n│   │       ├── result.py    # Result 类型（Rust 风格）\n│   │       └── route_tool.py # 路由工具函数\n│   ├── tools/               # 命令行工具\n│   └── wsgi.py              # WSGI 入口\n├── examples/                # 示例配置\n├── Containerfile            # 容器镜像定义\n└── pyproject.toml           # 项目元数据\n```\n\n### 代码风格\n\n- 使用 Python 3.13 类型注解\n- 遵循 PEP 8 代码风格\n- 使用 Rust 风格的 Result 类型处理错误\n\n### 运行测试\n\n```bash\n# TODO: 添加测试用例\n```\n\n## 许可证\n\n本项目采用 [MIT 许可证](LICENSE)。\n\n## 贡献\n\n欢迎提交 Issue 和 Pull Request！\n\n- 仓库：https://github.com/tokenicrat/pelit\n- 问题反馈：https://github.com/tokenicrat/pelit/issues\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftokenicrat%2Fpelit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftokenicrat%2Fpelit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftokenicrat%2Fpelit/lists"}