本项目基于journey-ad/Moe-Counter,使用ChatGPT Codex二次开发,与上游项目不同,新增了鉴权机制和管理员后台面板,此外 Fox-Counter 不允许公开请求自动创建计数器。管理员必须登录 Web 管理面板后创建唯一标识名,也可任意修改现有的计数器数据。
相关源代码及发行包下载请移步https://github.com/YumengOvO/Fox-Counter欢迎大家下载使用!
Fox-Counter
Fox-Counter 是基于 Moe-Counter 二次开发的自托管图片访客计数服务。
与上游项目不同,Fox-Counter 不允许公开请求自动创建计数器。管理员必须登录 Web 管理面板后创建唯一标识名;已经创建的计数器仍可被博客、文档或其他公开页面匿名访问和计数。
功能
- 单管理员 Web 登录
- 仅后台可创建计数器
- 查看、搜索、修改和删除计数器
- 后台主题预览与 SVG、HTML、Markdown 代码生成
- 公开 SVG 与 JSON 计数接口
- SQLite 和 MongoDB 存储
- 原 Moe-Counter 主题及显示参数
分支特色
后台管理面板
管理员可以在统一面板中创建、搜索和维护计数器,公开请求无法绕过后台自动创建新计数器。

嵌入代码生成器
在后台调整主题和显示参数、实时预览效果,并直接复制 SVG URL、HTML 或 Markdown 嵌入代码。

Docker Compose 快速部署(推荐)
Compose 直接使用公开镜像 ghcr.io/yumengovo/fox-counter:latest,支持 linux/amd64 和 linux/arm64,部署机器无需安装 Node.js 或在本地构建镜像。
1. 创建 .env
在 docker-compose.yml 同目录新建 .env,复制以下完整模板。必须替换管理员用户名、密码、SESSION_SECRET 和生产环境域名:
# 可选:固定镜像版本;保持注释时使用 latest
# FOX_COUNTER_IMAGE=ghcr.io/yumengovo/fox-counter:1.0.0
# 必填:单管理员登录凭据,请替换全部占位值
ADMIN_USERNAME=replace-with-admin-username
ADMIN_PASSWORD=replace-with-a-long-random-password
# 必填:至少 32 个字符,且必须与 ADMIN_PASSWORD 不同
SESSION_SECRET=replace-with-at-least-32-random-characters
# 生产环境填写对外 HTTPS 地址,用于生成计数器链接;不要以 / 结尾
APP_SITE=https://counter.example.com
# 宿主机映射端口;容器内固定监听 3000
APP_PORT=3000
# 管理员登录有效期,单位为小时
ADMIN_SESSION_TTL_HOURS=12
# 生产 HTTPS 设为 true;仅本地纯 HTTP 调试时设为 false
COOKIE_SECURE=true
# 数据库类型:sqlite 或 mongodb
DB_TYPE=sqlite
# SQLite 数据文件;Docker Compose 已将 /app/data 持久化
DB_PATH=/app/data/count.db
# MongoDB 专用连接串;使用 SQLite 时保持注释
# 请显式指定数据库名;Compose 网络内可使用 MongoDB 服务名
# DB_URL=mongodb://mongo:27017/fox-counter
# 计数写库间隔,单位为秒;0 表示即时安排刷新
DB_INTERVAL=60
# 日志级别:debug、info、warn、error 或 none
LOG_LEVEL=info
# 可选 Google Analytics G-Tag ID;不使用时保持注释
# GA_ID=G-XXXX
也可以直接复制仓库模板:
cp .env.example .env
Windows PowerShell:
Copy-Item .env.example .env
不要将真实密码或 Secret 写入 docker-compose.yml、源码、日志、URL 或 Git。可使用 openssl rand -hex 32 生成随机 SESSION_SECRET。
2. Docker Compose 配置
仓库提供的 docker-compose.yml 已包含逐项注释,核心配置如下:
services:
fox-counter:
# 默认使用公开 GHCR 镜像,可通过 .env 中的 FOX_COUNTER_IMAGE 固定版本
image: ${FOX_COUNTER_IMAGE:-ghcr.io/yumengovo/fox-counter:latest}
pull_policy: always
restart: unless-stopped
ports:
# 左侧为宿主机端口;容器内固定监听 3000
- "${APP_PORT:-3000}:3000"
volumes:
# SQLite 数据持久化到 Docker 命名卷
- fox-counter-data:/app/data
environment:
APP_PORT: "3000"
APP_SITE: "${APP_SITE:-}"
DB_TYPE: "${DB_TYPE:-sqlite}"
DB_PATH: "${DB_PATH:-/app/data/count.db}"
DB_URL: "${DB_URL:-}"
DB_INTERVAL: "${DB_INTERVAL:-60}"
ADMIN_USERNAME: "${ADMIN_USERNAME:?Set ADMIN_USERNAME in .env}"
ADMIN_PASSWORD: "${ADMIN_PASSWORD:?Set ADMIN_PASSWORD in .env}"
SESSION_SECRET: "${SESSION_SECRET:?Set SESSION_SECRET in .env (at least 32 characters)}"
ADMIN_SESSION_TTL_HOURS: "${ADMIN_SESSION_TTL_HOURS:-12}"
COOKIE_SECURE: "${COOKIE_SECURE:-}"
LOG_LEVEL: "${LOG_LEVEL:-info}"
GA_ID: "${GA_ID:-}"
volumes:
fox-counter-data:
使用命名卷可以避免非 root 容器在 Linux 上遇到宿主机目录写入权限问题。默认卷名为 fox-counter_fox-counter-data,更新或重建容器不会删除其中的 SQLite 数据。
3. 一条命令启动
pull_policy: always 会自动检查并拉取所选镜像,因此直接启动即可:
docker compose up -d
服务默认访问地址为 http://localhost:3000。查看状态、健康检查和日志:
docker compose ps
docker compose logs -f fox-counter
4. 升级镜像
docker compose pull
docker compose up -d
默认跟随 latest;生产环境也可以通过 FOX_COUNTER_IMAGE 固定到明确版本标签。
NSFW 内容警告
[!WARNING]
gelbooru-h和moebooru-h两个主题包含 NSFW 元素。部署到公开生产环境前,请根据受众和当地法规评估是否适合保留;如不适合,请删除以下主题目录:
- 仓库内:
assets/theme/gelbooru-h、assets/theme/moebooru-h- Docker 容器内:
/app/assets/theme/gelbooru-h、/app/assets/theme/moebooru-h直接在运行中的容器内删除只对当前容器生效;重新创建或升级容器后会恢复。需要长期移除时,请在自定义镜像的构建过程中删除这两个目录。
使用计数器
管理员创建 my-blog 后,可直接嵌入:
<img src="https://counter.example.com/@my-blog" alt="my-blog" />
Markdown:

显示参数继续通过查询字符串传递:
/@my-blog?theme=moebooru&padding=7&offset=0&align=top&scale=1&pixelated=1&darkmode=auto
不存在的标识名返回 HTTP 404,不会被自动创建。
本地运行
需要 Node.js 22+ 和 pnpm 10+。
pnpm install
copy .env.example .env
pnpm start
打开:
- 首页:
http://localhost:3000/ - 管理面板:
http://localhost:3000/admin - 健康检查:
http://localhost:3000/heart-beat
配置
复制 .env.example 为 .env,至少修改管理员密码和 Session 密钥:
APP_PORT=3000
DB_TYPE=sqlite
DB_INTERVAL=60
ADMIN_USERNAME=admin
ADMIN_PASSWORD=replace-with-a-strong-password
SESSION_SECRET=replace-with-at-least-32-random-characters
ADMIN_SESSION_TTL_HOURS=12
主要环境变量:
| 变量 | 说明 | 默认值 |
|---|---|---|
APP_SITE |
对外访问地址 | 根据请求推断 |
APP_PORT |
服务端口 | 3000 |
DB_TYPE |
sqlite 或 mongodb |
sqlite |
DB_PATH |
自定义 SQLite 数据库文件路径 | data/count.db |
DB_URL |
MongoDB 连接字符串 | mongodb://127.0.0.1:27017 |
DB_INTERVAL |
计数写库间隔秒数,0 为实时 |
0 |
ADMIN_USERNAME |
单管理员用户名 | admin |
ADMIN_PASSWORD |
单管理员密码,必须配置 | 无 |
SESSION_SECRET |
Cookie 签名密钥,至少 32 字符 | 无 |
ADMIN_SESSION_TTL_HOURS |
登录有效期(小时) | 12 |
COOKIE_SECURE |
强制 Cookie 仅通过 HTTPS 发送 | 根据 APP_SITE 判断 |
LOG_LEVEL |
日志级别 | info |
生产环境应使用强密码、独立随机的 SESSION_SECRET 和 HTTPS。若 HTTPS 由反向代理终止,设置 APP_SITE=https://... 或 COOKIE_SECURE=true。
接口行为
| 路径 | 访问权限 | 行为 |
|---|---|---|
GET /@:name |
公开 | 已存在时计数并返回 SVG,否则 404 |
GET /get/@:name |
公开 | 与 /@:name 相同 |
GET /record/@:name |
公开 | 已存在时计数并返回 JSON,否则 404 |
GET /admin |
管理员 | 管理面板 |
/api/admin/* |
管理员 | 计数器管理与无计数预览 |
本项目按需求不包含访客去重或防刷机制。任何人都可以重复访问已存在的公开计数器。
Credits
Fox-Counter 基于 journey-ad 的 Moe-Counter,并保留其主题资源及贡献者成果。
License
MIT License,主题资源遵循其各自许可。
Comments NOTHING