mirror of
https://github.com/tildeclub/site.git
synced 2026-03-10 05:50:17 +00:00
This document provides a comprehensive guide on generating and publishing sanitized traffic statistics for user directories on a web server. It includes instructions for opting in, file permissions, and troubleshooting common issues.
177 lines
5.0 KiB
Markdown
177 lines
5.0 KiB
Markdown
---
|
||
title: Userdir traffic stats (sanitized analytics)
|
||
category: web
|
||
---
|
||
|
||
So you want traffic stats for your `~/public_html` site, This stats system generates a **sanitized** report per user from the server’s nginx logs, then lets you publish it *only if you choose to*.
|
||
|
||
## What this gives you
|
||
|
||
* Daily totals: requests, pageviews, unique visitors (hashed per-day), bytes
|
||
* “Top pages” list (query strings removed)
|
||
* Referrers by **domain only** (no full URLs)
|
||
* Browser/user-agent buckets (Chrome/Firefox/Bot/etc.)
|
||
* HTTP status code counts
|
||
* Optionally: a nice HTML dashboard generated by `goaccess`
|
||
|
||
No raw IPs are shown in the report.
|
||
|
||
## Opt-in (required)
|
||
|
||
Nothing is generated for you unless you opt in.
|
||
|
||
Create the opt-in flag:
|
||
|
||
```sh
|
||
mkdir -p ~/.config/tilde-stats
|
||
touch ~/.config/tilde-stats/enabled
|
||
```
|
||
|
||
That’s it. The nightly job will include you from then on.
|
||
|
||
## Where the files are written
|
||
|
||
Reports are generated into:
|
||
|
||
* `~/.local/share/tilde-stats/index.html`
|
||
* `~/.local/share/tilde-stats/stats.json`
|
||
|
||
These files are **not automatically public**.
|
||
|
||
## Publishing the report on your website
|
||
|
||
There are two ways to publish the report:
|
||
|
||
* **Copy (recommended)**: keeps `~/.local` private and uses normal web permissions.
|
||
* **Symlink (works, but requires permissions)**: points your website at `~/.local/...`, which means nginx must be able to traverse those dot-directories.
|
||
|
||
Your stats page will be:
|
||
|
||
* `https://tilde.club/~YOURNAME/stats/`
|
||
|
||
### Recommended: copy into `~/public_html/stats/`
|
||
|
||
```sh
|
||
mkdir -p ~/public_html/stats
|
||
cp -f ~/.local/share/tilde-stats/index.html ~/public_html/stats/index.html
|
||
cp -f ~/.local/share/tilde-stats/stats.json ~/public_html/stats/stats.json
|
||
chmod 644 ~/public_html/stats/index.html ~/public_html/stats/stats.json
|
||
```
|
||
|
||
### Alternative: symlink into `~/public_html/stats/` (requires permissions)
|
||
|
||
```sh
|
||
mkdir -p ~/public_html/stats
|
||
ln -sf ~/.local/share/tilde-stats/index.html ~/public_html/stats/index.html
|
||
ln -sf ~/.local/share/tilde-stats/stats.json ~/public_html/stats/stats.json
|
||
```
|
||
|
||
If you use symlinks, nginx must be able to **traverse** the real path under `~/.local/...` (see permissions below).
|
||
|
||
## Permissions (important, because Linux will happily sabotage you)
|
||
|
||
For nginx to serve a file, it must be able to:
|
||
|
||
* **traverse** every directory in the path (execute bit, `+x`)
|
||
* **read** the file (`+r`)
|
||
|
||
### Minimum permissions for userdir websites
|
||
|
||
If your `~/public_html` site already works, you probably already have this, but here’s the standard expectation:
|
||
|
||
```sh
|
||
chmod 711 ~
|
||
```
|
||
|
||
`chmod 711 ~` lets the web server traverse your home directory without listing it.
|
||
|
||
### If you are COPYING files (recommended)
|
||
|
||
Make sure your published files are world-readable:
|
||
|
||
```sh
|
||
chmod 644 ~/public_html/stats/index.html ~/public_html/stats/stats.json
|
||
```
|
||
|
||
Your `~/.local/share/tilde-stats/` directory can stay private.
|
||
|
||
### If you are SYMLINKING to `~/.local/share/tilde-stats/` (current reality)
|
||
|
||
Because the report lives in a dot-directory path, nginx must be able to traverse:
|
||
|
||
* `~`
|
||
* `~/.local`
|
||
* `~/.local/share`
|
||
* `~/.local/share/tilde-stats`
|
||
|
||
And it must be able to read the report files themselves.
|
||
|
||
Use these permissions:
|
||
|
||
```sh
|
||
chmod 711 ~/.local ~/.local/share ~/.local/share/tilde-stats
|
||
chmod 644 ~/.local/share/tilde-stats/index.html ~/.local/share/tilde-stats/stats.json
|
||
```
|
||
|
||
Notes:
|
||
|
||
* `711` is better than `755` for dot-directories since it allows traversal but not directory listing.
|
||
* If the generator writes the files with private permissions, you may need to re-apply the `chmod 644` on the two report files after regeneration if you are serving them directly from `~/.local`.
|
||
|
||
## Updating / regenerating
|
||
|
||
Stats are generated by an admin-run job (typically nightly). You don’t need to run anything manually.
|
||
|
||
If you publish via **copy**, re-run the copy commands after the nightly update to refresh the public version.
|
||
|
||
If you publish via **symlink**, the page updates automatically (as long as permissions allow nginx to read it).
|
||
|
||
## Disabling / opting out
|
||
|
||
Remove the opt-in flag:
|
||
|
||
```sh
|
||
rm -f ~/.config/tilde-stats/enabled
|
||
```
|
||
|
||
No new reports will be generated for you after that.
|
||
|
||
(Any old published copies or symlinks you created are your responsibility to delete.)
|
||
|
||
## Troubleshooting
|
||
|
||
### “My stats page 403s / 404s”
|
||
|
||
* Confirm the public files exist:
|
||
|
||
```sh
|
||
ls -l ~/public_html/stats/
|
||
```
|
||
|
||
* Confirm permissions all the way down the path:
|
||
|
||
```sh
|
||
namei -l ~/public_html/stats/index.html
|
||
```
|
||
|
||
If you’re using symlinks into `~/.local`, also check the target path:
|
||
|
||
```sh
|
||
namei -l ~/.local/share/tilde-stats/index.html
|
||
```
|
||
|
||
Every directory in that output should have `x` for others (traversable), and the file should have `r` for others.
|
||
|
||
### “The report exists in ~/.local/share but isn’t public”
|
||
|
||
That’s expected. It’s private until you copy or link it into `~/public_html`.
|
||
|
||
### “My report is empty”
|
||
|
||
Either:
|
||
|
||
* No traffic in the selected window, or
|
||
* You opted in recently and the next scheduled run hasn’t happened yet.
|
||
|
||
(Servers do not read minds, only logs.)
|