# SiteStats 网站统计 · 安装手册

> 适用：宝塔面板（Linux）+ nginx 的服务器；支持 x86_64 与 arm64。
> 权限要求：root。安装完只占一个二进制 + 一个数据库目录，不动站点主配置。

---

## 一、前置条件

| 项 | 要求 |
|---|---|
| 系统 | Linux（CentOS / Ubuntu / Debian / 麒麟等均可），x86_64 或 arm64 |
| 面板 | 宝塔面板 + nginx（宝塔自带），站点已能正常访问 |
| 权限 | **必须 root**（写 /usr/local、/etc/systemd/system、改 nginx 注入都需要；脚本开头会自检，不是 root 会直接提示退出） |
| 磁盘 | 建议 ≥ 2GB 可用（明细库约 70 字节/请求，100 万请求 ≈ 70MB） |
| 网络 | 能访问公网（在线安装需要；离线包不需要） |
| CPU/内存 | 1 核 1G 可用；采集器常驻约 50~90MB（默认内存上限 256MB，超了自动降级） |

> 说明：SiteStats 通过 nginx 的 `access_log syslog:` 把访问日志实时推给采集器，
> 只往站点的 `extension/` 目录里加一个自己的文件，**站点主配置一行都不改**。

---

## 二、安装方式 A：在线一键安装（推荐）

在目标服务器上以 root 执行：

```bash
curl -fsSL https://download.gzmowo.cn/sitestats/install-online.sh | bash -s -- --inject-all
```

它会依次完成：

1. 识别系统架构，从下载地址取 `sitestats-linux-amd64`（或 arm64），并用 `SHA256SUMS` 校验；
2. 安装到 `/usr/local/sitestats/`；
3. 注册并启动两个 systemd 服务：`sitestats`（采集器）、`sitestats-web`（界面 + API）；
4. `--inject-all` 给**该服务器上全部站点**接入日志推送；
5. 打印访问方式与常用命令。

### 常用参数

| 参数 | 作用 |
|---|---|
| `--inject-all` | 给全部站点接入日志推送 |
| `--inject a.cn b.cn` | 只给指定域名接入 |
| `--no-inject` | 先不接入任何站点（装完再手动接） |
| `--uninstall` | 卸载（含撤销 nginx 注入） |

### 只想接一个站点试效果

```bash
curl -fsSL https://download.gzmowo.cn/sitestats/install-online.sh | bash -s -- --no-inject
sudo bash /usr/local/sitestats/inject-logs.sh --inject 你的域名.com
```

### 下载源打不开时

用环境变量换源（例如把安装包放到自己的服务器/内网地址）：

```bash
curl -fsSL http://你的地址/install-online.sh -o /tmp/install.sh
sudo SITESTATS_URL=http://你的地址 bash /tmp/install.sh --inject-all
```

---

## 三、安装方式 B：离线包安装（服务器不能上外网）

1. 在本机（或能上网的机器）下载对应架构的离线包：

```
https://download.gzmowo.cn/sitestats/sitestats-0.1.0-m3-linux-amd64.tar.gz
https://download.gzmowo.cn/sitestats/sitestats-0.1.0-m3-linux-arm64.tar.gz
https://download.gzmowo.cn/sitestats/SHA256SUMS      # 校验用
```

2. 上传并校验（在目标服务器执行）：

```bash
scp sitestats-0.1.0-m3-linux-amd64.tar.gz root@目标IP:/root/
sha256sum -c SHA256SUMS --ignore-missing      # 与下载目录里的 SHA256SUMS 比对
```

3. 解包安装：

```bash
tar xzf sitestats-0.1.0-m3-linux-amd64.tar.gz
cd sitestats-0.1.0-m3-linux-amd64
sudo bash install.sh --inject-all          # 或 --no-inject
```

离线包内容：`sitestats`（单个二进制，前端已内嵌）、`install.sh`、`install-online.sh`、
`inject-logs.sh`、`sitestats.service`、`sitestats-web.service`、`sitestats-log-format.conf`、`README.md`、`docs/`。

---

## 四、安装完成后（三步用起来）

### 1. 打开界面，设置访问密码

界面只监听本机 `127.0.0.1:8899`（不直接对公网开放）。先在服务器上验证：

```bash
curl -s http://127.0.0.1:8899/api/health
```

第一次打开界面会让你**设置访问密码**（至少 6 位，PBKDF2 加密存储；没有默认密码）。

### 2. 接入要统计的站点

```bash
sudo bash /usr/local/sitestats/inject-logs.sh --discover     # 看有哪些站点、是否已接入
sudo bash /usr/local/sitestats/inject-logs.sh --inject-all   # 全部接入
sudo bash /usr/local/sitestats/inject-logs.sh --status       # 看状态
```

注入后 nginx 会自动 reload（脚本先做 `nginx -t`，校验失败会**自动回滚**，不会弄坏你的站点）。

### 3. 用域名访问（宝塔建站 + 反向代理）

1. 宝塔 → 网站 → 添加站点：域名如 `stats.你的域名.com`（无需数据库/PHP）；
2. 该站点的「反向代理」→ 添加：目标 `http://127.0.0.1:8899`（或手工在站点配置里写
   `location / { proxy_pass http://127.0.0.1:8899; proxy_set_header Host $host; }`）；
3. 申请 Let's Encrypt 证书并开启强制 HTTPS（域名已备案用 HTTP-01；未备案域名 80 端口会被云厂商拦截，改用 DNS-01）。

---

## 四之二、安装完成后你会看到什么

安装脚本最后会打印一段信息（像宝塔装完那样），包含访问地址、密码状态和常用命令：

```
------------------------------------------------------------
SiteStats 0.1.0-m3 安装完成
  本机访问：  http://127.0.0.1:8899    （服务器上直接打开）
  内网访问：  http://10.1.24.16:8899
  外网访问：  http://134.175.155.58:8899
  已生成访问密码：a8uv9juxSt
  ⚠️ 当前只监听本机（127.0.0.1），内网/外网地址需先放开监听：
       sudo bash /usr/local/sitestats/install-online.sh --listen-public
     更稳妥：宝塔建站 + 反向代理 http://127.0.0.1:8899 ，用域名 + HTTPS 访问
------------------------------------------------------------
```

- **默认密码**：首次安装自动生成 10 位随机密码并打印；**重装/升级不会改掉你已设的密码**（会显示"沿用已设置的访问密码"）。
- 忘记密码：`sudo /usr/local/sitestats/sitestats passwd -db /var/lib/sitestats/sitestats.db -password 新密码`
- 内网/外网地址默认打不开是正常的：界面默认**只监听本机**（更安全）。要直接访问就加 `--listen-public`（会同时放行本机 ufw/firewalld；云服务器还需在控制台安全组放行该端口）；推荐用宝塔建站 + 反代。
- 想看当前状态：`bash /usr/local/sitestats/show-info.sh`（随时可再打印一次这段信息）。

## 四之三、端口被占用怎么办

安装时会检测监听端口（默认 **8899**）：

1. 端口空闲 → 直接用；
2. 端口是**上次装的 SiteStats 自己在用** → 继续用（重装/升级不会乱换端口）；
3. 端口被**其它程序**占用 → 自动往上找下一个可用端口，并打印
   `端口 8899 已被其它程序占用，自动改用 8900`，安装完的信息面板里也会显示真实端口。

指定端口或放开监听：

```bash
sudo bash install-online.sh --listen-public                 # 监听所有网卡（默认 8899）
sudo env SITESTATS_PORT=9000 bash install-online.sh          # 指定起始端口
```

---

## 四之四、反向代理配置（把界面挂到域名上）

推荐写法（宝塔：网站 → 设置 → 反向代理，或直接写进站点配置）：

```nginx
location / {
    proxy_pass http://127.0.0.1:8899;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_read_timeout 300s;
    client_max_body_size 50m;
}
```

**要点（含常见写法的问题）**

1. **必须挂在站点根目录**：用子域名（如 `stats.你的域名.com`），不要挂子目录。页面里的 `/app.js`、`/api/...` 都是绝对路径，挂成 `域名/stats/` 会整页 404。
2. `proxy_set_header Host`：推荐 `$host`（保留原始域名）。写成 `proxy_set_header Host 127.0.0.1;` **也能正常跑**（SiteStats 不按域名分流，实测 HTTP 200）。
3. `proxy_set_header Upgrade $http_upgrade;` / `Connection $connection_upgrade;`（宝塔模板里常见的两行）：SiteStats **不用 WebSocket**（界面每 10 秒轮询实时数据），删掉更干净。留着也不会报错 —— `$connection_upgrade` 由宝塔全局文件 `vhost/nginx/0.websocket.conf` 定义，本机实测带这两行请求返回 200。
4. 建议加 `proxy_read_timeout 300s`（导出大 CSV、跨月查询不会 502）与 `client_max_body_size 50m`。
5. 代理配好后**记得申请证书并开启 HTTPS**（界面登录密码会明文走代理，必须加密）。

**自检（服务器上执行，域名换成你的）**

```bash
# 从本机直接打 443，不走 DNS，确认代理链路通
curl -sI --resolve 你的域名.com:443:127.0.0.1 https://你的域名.com/ | head -1        # 期望 HTTP/2 200 或 200
curl -s  --resolve 你的域名.com:443:127.0.0.1 https://你的域名.com/api/health        # 期望 {"ok":true,...}
```

---

## 四之五、中心站点（多台服务器统一查看）

一台装 SiteStats 的服务器可以当**中心站**，把多台服务器的流量汇总到一起看。

**中心站这边（一次性）**

1. 打开界面 → 左栏「中心站点」→ 填个节点名（如 `aliyun-hk-01`）→ 点「添加节点」
2. 页面会给出**节点令牌**和一行**接入命令**，复制那行命令

**其它服务器这边（root 执行那行命令）**

```bash
curl -fsSL https://download.gzmowo.cn/sitestats/install-online.sh | sudo bash -s -- --center https://你的中心站域名 --token nd_xxxxxxxx
```

装完会多一个 `sitestats-report.service`（每 60 秒上报一次聚合数据）：

```bash
systemctl status sitestats-report     # 上报服务状态
sudo bash /usr/local/sitestats/show-info.sh   # 看「中心站点上报」是否已开启
journalctl -u sitestats-report -n 20  # 上报日志
```

**说明**

- 探针**只上报聚合值**（请求数/PV/UV/IP/蜘蛛/慢/流量/状态码/TOP 榜单），不上报原始日志
- 中心端「今日」数字与探针本机**完全一致**（直接存探针的日值），小时级数据来自分钟级上报
- 断网或中心站重启不会丢数据：上报失败会缓存在本地（保留 24 小时），恢复后自动补发
- 节点 3 分钟没有上报就显示「离线」，删节点即令牌失效
- 中心站**必须用 HTTPS**（令牌走请求头），反代配置见上一节

---

## 五、日常运维

| 操作 | 命令 |
|---|---|
| 查看状态 | `systemctl status sitestats sitestats-web` |
| 重启 | `systemctl restart sitestats sitestats-web` |
| 日志 | `tail -f /var/log/sitestats.log`、`journalctl -u sitestats-web -n 50` |
| 数据目录 | `/var/lib/sitestats/`（主库 `sitestats.db` + 按天明细 `detail-YYYYMMDD.db`） |
| 手动回放历史日志 | `sitestats replay -db /var/lib/sitestats/sitestats.db -detail -detail-dir /var/lib/sitestats -site 域名 /www/wwwlogs/域名.log` |
| 升级 | 重新执行一键安装命令即可（数据与密码保留） |
| 撤销日志注入 | `sudo bash /usr/local/sitestats/inject-logs.sh --rollback` |
| 卸载 | `systemctl disable --now sitestats sitestats-web && rm -rf /usr/local/sitestats /var/lib/sitestats && sudo bash /usr/local/sitestats/inject-logs.sh --rollback` |

> 注意：回放/导入历史日志前建议先 `systemctl stop sitestats`，导完再启动，避免与实时采集交叉。

---

## 六、常见问题

**1. 安装脚本报「下载失败」**
先测 `curl -I https://download.gzmowo.cn/sitestats/sitestats-linux-amd64`；若服务器不能上外网，改用离线包（方式 B），或用 `SITESTATS_URL` 指向内网镜像。

**2. 注入失败 / nginx 配置报错**
脚本自带保护：`nginx -t` 不通过会自动删除本次写入并回滚，站点主配置不会被改。常见原因是老版本宝塔站点配置里没有 `extension` include（脚本会提示"跳过"），或者域名过长（已在 v0.1.0-m3 修复 tag 长度问题）。执行 `bash /usr/local/sitestats/inject-logs.sh --discover` 查看每个站点的接入状态。

**3. 界面上只有部分站点**
接口是「发现全量站点」，但**只有执行过注入的站点才有日志进来**。新装站点后跑一次 `--inject-all`（或用 `--inject 新域名`）即可。

**4. 和宝塔「网站监控报表」插件冲突吗？**
两者都从 nginx 取日志，可以并存（我们的注入只加自己的 include）。但两个采集器会各自占一点内存/CPU，建议同一台机器只留一个。

**5. 内存/磁盘占用**
采集器常驻 50~90MB（默认内存上限 256MB，超限自动降级刷盘）；明细约 70 字节/请求（100 万请求 ≈ 70MB），默认明细保留 5GB / 天指标 30 天，可在设置里调整。

**6. 数据会不会丢**
天级汇总在进程重启后会自动接上（启动时先读库再累加），登录会话也持久化在库里，重启不掉线。

---

## 七、验收自检（装完建议跑一遍）

```bash
# 1) 服务都在跑
systemctl is-active sitestats sitestats-web

# 2) 采集器在监听（socket 方式）
ls -l /tmp/sitestats.sock

# 3) 造几条访问，看是否入库（把域名换成你的）
for i in 1 2 3; do curl -s -o /dev/null -H "Host: 你的域名.com" http://127.0.0.1/; done
sleep 8
sqlite3 /var/lib/sitestats/sitestats.db "select date,site_id,request,pv from metric_day order by date desc limit 3;"

# 4) 口径自检：天指标 = 维度合计 = 明细行数
sqlite3 /var/lib/sitestats/sitestats.db "select
 (select sum(request) from metric_day where date=(select max(date) from metric_day)) as 天请求,
 (select sum(request) from dim_uri   where date=(select max(date) from metric_day)) as 维度请求;"
```

---

## 八、安全与合规说明

- 界面默认只监听 `127.0.0.1`，不直接暴露公网；对外请走反向代理 + HTTPS；
- 访问密码加盐哈希存储，会话 30 天有效并持久化；退出即失效；
- 不修改站点主配置、不抓取请求体、不记录敏感头（可配置）；
- 项目许可证 MIT，可自由使用与二次开发；不与宝塔插件共享代码，只参考其统计口径。
