P2Pool now runs with --data-api /api --local-api. /api is an emptyDir shared with a new stats sidecar.
files/p2pool_stats.py is a small sidecar that uses only the Python standard library. It reads local/stratum, pool/stats and network/stats and copies an allowlist of numeric fields into one JSON document at /p2pool/stats.json. Each section is cached for 10s and flagged stale after 15 min without updates.
Fields: node hashrate (15m/1h/24h), connected miner count, shares, effort, the node's share of the PPLNS reward, sidechain hashrate and miners, and network difficulty, hashrate and reward.
Never published:local/stratum lists each worker's IP address and name (sometimes a wallet prefix), so the sidecar counts the workers but never copies them. Tests check this.
The endpoint returns 503 until P2Pool has written its node stats, so the website keeps its fallback text.
Service p2pool-stats (ClusterIP :8080), plus an Ingress that adds the single Exact path /p2pool/stats.json to monero_p2pool_stats_host, which defaults to www.eom.dev. ingress-nginx merges this path into the website's existing server block, so it reuses the website's TLS certificate and the homepage can fetch it same-origin. Set the host to "" to remove the Ingress.
The sidecar runs as nobody with a read-only root filesystem and all capabilities dropped.
Rollout notes
Adding the sidecar changes the pod template, so P2Pool restarts once and miners reconnect automatically. Shares already in the PPLNS window aren't lost: the sidechain keeps them.
The sidecar pulls python:3.13-alpine (configurable with monero_p2pool_stats_image).
After deploying, curl https://www.eom.dev/p2pool/stats.json should return JSON within about a minute.
Tests
python3 -m unittest discover -s tests: 10 tests pass locally. They cover allowlisting, no worker IPs or wallets in the output, missing, malformed, oversized and stale files, and that only one path is served. I also rendered the changed tasks with Jinja to check the args expression and the YAML structure. I did not run the playbook against the cluster.
Companion PR: DevOps/www adds the live mining section that reads this endpoint.
## What
- P2Pool now runs with `--data-api /api --local-api`. `/api` is an `emptyDir` shared with a new `stats` sidecar.
- `files/p2pool_stats.py` is a small sidecar that uses only the Python standard library. It reads `local/stratum`, `pool/stats` and `network/stats` and copies an **allowlist** of numeric fields into one JSON document at `/p2pool/stats.json`. Each section is cached for 10s and flagged `stale` after 15 min without updates.
- Fields: node hashrate (15m/1h/24h), connected miner count, shares, effort, the node's share of the PPLNS reward, sidechain hashrate and miners, and network difficulty, hashrate and reward.
- **Never published:** `local/stratum` lists each worker's IP address and name (sometimes a wallet prefix), so the sidecar counts the workers but never copies them. Tests check this.
- The endpoint returns 503 until P2Pool has written its node stats, so the website keeps its fallback text.
- `Service p2pool-stats` (ClusterIP :8080), plus an `Ingress` that adds the single **Exact** path `/p2pool/stats.json` to `monero_p2pool_stats_host`, which defaults to `www.eom.dev`. ingress-nginx merges this path into the website's existing server block, so it reuses the website's TLS certificate and the homepage can fetch it same-origin. Set the host to `""` to remove the Ingress.
- The sidecar runs as nobody with a read-only root filesystem and all capabilities dropped.
## Rollout notes
- Adding the sidecar changes the pod template, so **P2Pool restarts once** and miners reconnect automatically. Shares already in the PPLNS window aren't lost: the sidechain keeps them.
- The sidecar pulls `python:3.13-alpine` (configurable with `monero_p2pool_stats_image`).
- After deploying, `curl https://www.eom.dev/p2pool/stats.json` should return JSON within about a minute.
## Tests
`python3 -m unittest discover -s tests`: 10 tests pass locally. They cover allowlisting, no worker IPs or wallets in the output, missing, malformed, oversized and stale files, and that only one path is served. I also rendered the changed tasks with Jinja to check the args expression and the YAML structure. I did **not** run the playbook against the cluster.
Companion PR: DevOps/www adds the live mining section that reads this endpoint.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_018STDcc5BaYxPMNA9S8Wycs
Enable P2Pool's --data-api/--local-api and add a small stdlib-only sidecar
that copies an allowlist of numeric fields (node/sidechain hashrate,
connected miners, shares, network difficulty) to /p2pool/stats.json. Worker
IPs and wallet fragments in local/stratum are never served.
An Ingress adds that single path to the website host (www.eom.dev by
default), so the homepage can read it same-origin and reuse its TLS cert.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018STDcc5BaYxPMNA9S8Wycs
Enable P2Pool's --data-api/--local-api and add a small stdlib-only sidecar
that copies an allowlist of numeric fields (node/sidechain hashrate,
connected miners, shares, network difficulty) to /p2pool/stats.json. Worker
IPs and wallet fragments in local/stratum are never served.
An Ingress adds that single path to the website host (www.eom.dev by
default), so the homepage can read it same-origin and reuse its TLS cert.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018STDcc5BaYxPMNA9S8Wycs
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What
--data-api /api --local-api./apiis anemptyDirshared with a newstatssidecar.files/p2pool_stats.pyis a small sidecar that uses only the Python standard library. It readslocal/stratum,pool/statsandnetwork/statsand copies an allowlist of numeric fields into one JSON document at/p2pool/stats.json. Each section is cached for 10s and flaggedstaleafter 15 min without updates.local/stratumlists each worker's IP address and name (sometimes a wallet prefix), so the sidecar counts the workers but never copies them. Tests check this.Service p2pool-stats(ClusterIP :8080), plus anIngressthat adds the single Exact path/p2pool/stats.jsontomonero_p2pool_stats_host, which defaults towww.eom.dev. ingress-nginx merges this path into the website's existing server block, so it reuses the website's TLS certificate and the homepage can fetch it same-origin. Set the host to""to remove the Ingress.Rollout notes
python:3.13-alpine(configurable withmonero_p2pool_stats_image).curl https://www.eom.dev/p2pool/stats.jsonshould return JSON within about a minute.Tests
python3 -m unittest discover -s tests: 10 tests pass locally. They cover allowlisting, no worker IPs or wallets in the output, missing, malformed, oversized and stale files, and that only one path is served. I also rendered the changed tasks with Jinja to check the args expression and the YAML structure. I did not run the playbook against the cluster.Companion PR: DevOps/www adds the live mining section that reads this endpoint.
🤖 Generated with Claude Code
https://claude.ai/code/session_018STDcc5BaYxPMNA9S8Wycs
Jinja has no comment syntax inside {{ }}, so the comment would break templating. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018STDcc5BaYxPMNA9S8WycsView command line instructions
Checkout
From your project repository, check out a new branch and test the changes.