From 71e7ffd93f8c74df3d3467eab4afb77e61d649c1 Mon Sep 17 00:00:00 2001 From: Vijit Singh Date: Fri, 21 Aug 2026 11:08:02 -0500 Subject: [PATCH] content: catch the site up to pithead v1.19 and the v2 appliance work MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The copy still described the v1.0 launch state. Since then pithead shipped nineteen minor releases and the old "road ahead" (Tor-by-default egress, operator alerts, trends, dashboard control, fleet, deploy-anywhere) all landed — so those move into the Pithead feature grid, the shipped waves retell the v1.0 → v1.19 arc, and the road ahead now showcases Pithead OS: the appliance image, A/B updates, first-boot wizard, and USB config channel in review on develop-v2 (pithead#1057). Also: - hero quick start matches the current README (config.minimal.json) - privacy copy updated: all runtime egress rides Tor behind a fail-closed firewall (shipped in v1.1); FAQ disk sizing matches current README - stat band: 11 services; drop the retired node-starter-stacks promise - the ★ flag becomes a star link on both project cards, showing each repo's star count baked at deploy time by scripts/refresh-releases.py (new data/stars.json — visitors still make zero third-party requests) Co-Authored-By: Claude Fable 5 --- assets/css/main.css | 7 ++ data/content.yaml | 140 ++++++++++++++++++------------------ data/releases.json | 4 +- data/stars.json | 4 ++ layouts/index.html | 3 +- scripts/refresh-releases.py | 25 +++++-- 6 files changed, 108 insertions(+), 75 deletions(-) create mode 100644 data/stars.json diff --git a/assets/css/main.css b/assets/css/main.css index cdaa380..28bde54 100644 --- a/assets/css/main.css +++ b/assets/css/main.css @@ -768,6 +768,13 @@ html.js .reveal.in { padding: 5px 11px; border-radius: 20px; white-space: nowrap; + transition: + border-color 0.15s ease, + transform 0.15s ease; +} +.project-flag:hover { + border-color: var(--orange); + transform: translateY(-1px); } .project-tagline { font-size: 20px; diff --git a/data/content.yaml b/data/content.yaml index 28f1ca5..5ad9b52 100644 --- a/data/content.yaml +++ b/data/content.yaml @@ -19,7 +19,7 @@ hero: p: true, text: "curl -fsSL https://github.com/p2pool-starter-stack/pithead/releases/latest/download/pithead.tar.gz | tar xz", } - - { p: true, text: "cd pithead && cp config.json.template config.json" } + - { p: true, text: "cd pithead && cp config.minimal.json config.json" } - { p: true, text: "./pithead setup" } - { p: false, text: "✓ Tor provisioned · kernel tuned · stack live over HTTPS" } cta_primary: { label: "Get Pithead", href: "https://github.com/p2pool-starter-stack/pithead" } @@ -42,8 +42,8 @@ beliefs: - belief: "Mine without telling the world." text: >- Monero, Tari, and P2Pool run as Tor hidden services by default — no port forwarding, no home IP - advertised to inbound peers. Your mining stays your business. Tor-first today, and honest about - the few outbound edges still on clearnet. + advertised to inbound peers. All runtime egress rides Tor too, and a host firewall drops any + direct clearnet dial. Your mining stays your business. - belief: "Keep what you earn." text: >- P2Pool pays block rewards straight to your wallet — no pool operator, no cut, no account. Even @@ -56,7 +56,7 @@ beliefs: # Mono stat band under the hero. stats: - - { value: "9", label: "services, one compose file" } + - { value: "11", label: "services, one compose file" } - { value: "2", label: "chains, merge-mined" } - { value: "1", label: "command to set up" } - { value: ":3333", label: "one endpoint for every rig" } @@ -98,7 +98,7 @@ projects: - { icon: "onion", title: "Private by default", - text: "Tor hidden services for Monero, Tari, and P2Pool — your router stays shut and your home IP is never advertised to an inbound peer.", + text: "Tor hidden services for Monero, Tari, and P2Pool, and all runtime egress routed over Tor — a fail-closed host firewall drops any direct clearnet dial. Your router stays shut, your home IP stays yours.", } - { icon: "pick", @@ -118,12 +118,27 @@ projects: - { icon: "chart", title: "A dashboard worth leaving open", - text: "Live hashrate, the P2Pool/XvB split shading in real time, the PPLNS window, an honest tier + explicit VIP status, and per-worker stats — over HTTPS on your LAN.", + text: "Live hashrate, the P2Pool/XvB split shading in real time, per-worker stats — and persistent trends: blocks found, pool luck, reject rates, and expected-vs-confirmed earnings after power costs.", + } + - { + icon: "gear", + title: "Control from the browser", + text: "Opt in to edit any setting from a guided form, retune each rig with versioned history, and one-click upgrade when a release lands — every change host-validated behind a login, with a full audit log.", + } + - { + icon: "bolt", + title: "An operator bot on call", + text: "Telegram alerts the moment a node or worker drops — and when it recovers — plus a daily digest, read-only status commands, and a Healthchecks dead-man's switch for the failure the box can't report itself.", + } + - { + icon: "stack", + title: "Encrypted backups", + text: "One command writes config, secrets, Tor onion keys, and the dashboard's history to an AES-256 archive — and restore brings the box back on new hardware with the same onion address.", } - { icon: "shield", title: "Hardened out of the box", - text: "Least-privilege containers, SHA256-verified pinned binaries, and tightly scoped Docker-socket proxies — read-only for stats, start/stop-only for failover.", + text: "Non-root containers, read-only filesystems, SHA256-verified pinned binaries, digest-pinned images, scoped Docker-socket proxies — and every release cosign-signed end to end.", } links: - { @@ -187,93 +202,81 @@ projects: href: "https://github.com/p2pool-starter-stack/rigforge/blob/main/docs/benchmarks.md", } -# High-level roadmap, sequenced from both repos' milestones. Pithead drives the version themes -# (v1.1 privacy through v1.6 deploy-anywhere, then v2 appliance); RigForge ships in lockstep. No -# dates; waves and versions only. +# High-level roadmap. The waves group pithead's nineteen post-1.0 releases into the themes the +# original roadmap promised (all shipped); the road ahead is the v2 appliance work in review on +# the develop-v2 branch (PR #1057). No dates; versions only. roadmap: eyebrow: "// the roadmap" - title: "v1.0 is live. Now, the road to the appliance era." + title: "Nineteen releases later: the road to the appliance era." sub: >- - Built in the open, issue by issue — no vaporware, no roadmap-for-sale. Both projects shipped v1.0 - and run on real hardware today. What's next is sequenced into small, themed releases — each one - landing a single focus — all the way to v2: flash a drive, boot, and mine. - waves_label: "v1.0 · shipped, wave by wave" + Built in the open, issue by issue — no vaporware, no roadmap-for-sale. Everything the v1 roadmap + promised has shipped, release by release, on real hardware. And what's next is already written: + Pithead OS, a flashable appliance, in review on the develop-v2 branch right now. + waves_label: "shipped · v1.0 → v1.19, theme by theme" waves: - { - n: "01", - name: "Correctness & data-safety", + n: "1.1", + name: "Privacy, by default", status: "Shipped", - text: "Killed the silent-failure bugs that burn early adopters — no surprise re-syncs, no no-op applies, no stale generated config, no vanished share history.", + text: "All runtime egress moved behind Tor with a fail-closed host firewall, every container dropped to non-root, and a Stack Topology panel maps every hop — Tor or clearnet — at a glance.", } - { - n: "02", - name: "Privacy & security", + n: "1.2", + name: "Operator alerts", status: "Shipped", - text: "Closed every clearnet DNS and stats leak, added optional stratum + dashboard auth, made the proxy fail closed on an empty token, and shut the SSRF door — with a privacy guide mapping every connection.", + text: "A Telegram bot pings the moment a node or worker drops — and when it recovers — plus a Healthchecks dead-man's switch for the one failure a monitor on the box can never report: the box itself going dark.", } - { - n: "03", - name: "The dashboard", + n: "1.3+", + name: "Trends & insight", status: "Shipped", - text: "The thing people screenshot — routed hashrate everywhere, an honest tier, explicit VIP status, a toggleable averaging window, and an operator-first layout.", + text: "Persistent time-series telemetry, a pool cadence & luck panel, and earnings calculators — later grown into cards that check every estimate against what the view-only wallets actually confirmed, after power costs.", } - { - n: "04", - name: "CI & test hardening", + n: "1.4+", + name: "Control & fleet", status: "Shipped", - text: "Every container image built in CI with hadolint, every script linted, and backup/restore plus host helpers under an expanded test suite.", + text: "Config editing and one-click signed upgrades from the dashboard, per-rig inspect and retune with versioned history, stratum TLS with per-rig pinning, and warm failover to a backup stack.", } - { - n: "05", - name: "Release gate & launch", + n: "1.12+", + name: "Deploy anywhere", status: "Shipped", - text: "A full end-to-end test on a real Ubuntu server, the GHCR release pipeline, and refreshed launch assets — tagged and live as v1.0.", + text: "Co-host behind an existing reverse proxy, let one stack's synced nodes serve others, and point the stack at a remote Monero or Tari node instead of running your own.", } ship: - title: "v1.0 — the whole operation, live on real hardware." - text: "End-to-end tested on a real Ubuntu server, packaged, versioned, and released in the open — both Pithead and RigForge shipped at v1.0." - beyond_label: "the road ahead · release by release" + title: "v1.19 — the whole operation, signed and live." + text: "Nineteen releases cut in the open — including two withdrawn and re-cut with the root cause documented in the changelog. Every bundle is now cosign-signed end to end, and the release pipeline refuses to cut an unsigned build." + beyond_label: "the road ahead · Pithead OS, in review on develop-v2" releases: - { - n: "1.1", - status: "Next", - name: "Privacy, by default", - text: "Route the P2Pool sidechain and the XvB donation upstream through Tor by default (benchmark-gated, with a documented opt-out), run every container as a non-root user, and add a component-health panel that shows each connection's Tor-vs-clearnet posture at a glance.", - } - - { - n: "1.2", - status: "Planned", - name: "Operator alerts", - text: "A Telegram ping the moment a node or worker drops — and when it recovers — plus an external Healthchecks dead-man's switch that catches a dead host or power loss the stack can't report itself, with outages flagged right on the chart.", - } - - { - n: "1.3", - status: "Planned", - name: "Trends & insight", - text: "Persistent time-series telemetry instead of last-value gauges: reject-rate trends, a pool cadence & luck panel, host-health badges (AVX2, HugePages, low disk), and Tari + XvB earnings calculators.", + n: "01", + status: "In review", + name: "Flash a drive, boot a mine", + text: "Pithead OS: a bootable appliance image with a read-only root, A/B system partitions, and an immutable Podman/Quadlet runtime — and everything that matters on one persistent data partition.", } - { - n: "1.4", - status: "Planned", - name: "Control from the dashboard", - text: "Change any setting from the dashboard and apply it safely — and a one-click, in-place upgrade the moment a new release lands. No SSH, no CLI, no hand-edited config.", + n: "02", + status: "In review", + name: "Updates that can't brick the box", + text: "Signed A/B updates: a new image lands on the spare slot, boots once, and commits only after the stack passes a health check. A slot that won't boot reverts on its own at the next power cycle.", } - { - n: "1.5", - status: "Planned", - name: "Fleet management", - text: "Read and edit each rig's XMRig config from the dashboard with versioned history, consume RigForge's richer per-worker feed (power, tune, firmware identity), and keep a primary and backup stack in sync.", + n: "03", + status: "In review", + name: "First boot without a manual", + text: "A brand-new box serves a first-boot wizard, the installer moves the running image onto an internal disk — keep or wipe your data — and a factory reset returns it to day one.", } - { - n: "1.6", - status: "Planned", - name: "Deploy anywhere", - text: "Co-hosting migration guides, relaxed network bindings for shared home servers, and a remote Tari base-node option to mirror remote Monero.", + n: "04", + status: "In review", + name: "Headless, to the last resort", + text: "Drop a config file on a USB stick and a headless box configures itself — no keyboard, no network step. The same channel doubles as the recovery path of last resort.", } ship_beyond: tag: "v2" name: "The appliance era" - text: "Flash a USB, boot, and mine. Self-provisioning appliance images for the stack host and RigForge miners, an immutable Podman/Quadlet runtime, and standalone Monero & Tari node-starter stacks." + text: "All of it is real code today — hundreds of commits on develop-v2 carrying the image, updater, installer, wizard, and factory reset — under adversarial review and a hardware test battery before the first image is cut. Watch it land in the open." donate: eyebrow: "// fuel the roadmap" title: "Built in the open. Funded by the people who run it." @@ -287,7 +290,7 @@ ethos: items: - { title: "Privacy is the default, not a setting", - text: "Inbound rides Tor hidden services — no port forwarding, your home IP never shown to a peer — and RPC stays localhost-bound. The few clearnet outbound paths left in v1.0 are documented, and go Tor-by-default in v1.1.", + text: "Inbound rides Tor hidden services — no port forwarding, your home IP never shown to a peer — RPC stays localhost-bound, and all runtime egress routes over Tor by default. The opt-in clearnet exceptions are documented in the privacy guide.", } - { title: "Least privilege, everywhere", @@ -331,9 +334,9 @@ faq: - q: "Do I have to forward ports or expose my home IP to mine Monero?" a: >- No. Pithead runs Monero, Tari, and P2Pool as Tor hidden services, so inbound peers reach you over - an onion address and your router stays shut. RPC is bound to localhost. A couple of outbound yield - paths still touch clearnet in v1.0 — every connection is mapped in the privacy guide, and they move - to Tor-by-default in v1.1. + an onion address and your router stays shut. RPC is bound to localhost, and all runtime egress + routes over Tor by default behind a fail-closed firewall — the few opt-in exceptions, like a + faster clearnet initial sync, are mapped in the privacy guide. - q: "What is P2Pool, and why mine to it instead of a centralized pool?" a: >- @@ -350,8 +353,9 @@ faq: - q: "What hardware do I need to mine Monero?" a: >- - For the stack host: Ubuntu Server 24.04, 16 GB+ RAM, and an SSD (~300 GB pruned; 2–4 TB for - set-and-forget). Mining itself is CPU-bound — Monero's RandomX runs on any modern AMD or Intel CPU, + For the stack host: Ubuntu Server 24.04, 16 GB+ RAM, and an SSD (~330 GB pruned / ~530 GB full + to start — the chains grow, so 2–4 TB is set-and-forget). Mining itself is CPU-bound — Monero's + RandomX runs on any modern AMD or Intel CPU, and chips with large L3 cache (Ryzen X3D, EPYC) shine. RigForge auto-detects your CPU and tunes the miner for you. diff --git a/data/releases.json b/data/releases.json index 1bdb498..ecf281c 100644 --- a/data/releases.json +++ b/data/releases.json @@ -1,4 +1,4 @@ { - "pithead": "v1.0.2", - "rigforge": "v1.0.1" + "pithead": "v1.19.2", + "rigforge": "v1.15.1" } diff --git a/data/stars.json b/data/stars.json new file mode 100644 index 0000000..b4f7099 --- /dev/null +++ b/data/stars.json @@ -0,0 +1,4 @@ +{ + "pithead": 35, + "rigforge": 3 +} diff --git a/layouts/index.html b/layouts/index.html index e3f8806..b08bf0c 100644 --- a/layouts/index.html +++ b/layouts/index.html @@ -117,6 +117,7 @@

{{ $c.projects.title }}

{{ range $c.projects.items }} {{ $ver := index hugo.Data.releases .id }} + {{ $stars := index hugo.Data.stars .id }}
{{ partial "icon.html" .mark }} @@ -126,7 +127,7 @@

{{ .name }}

{{ if $ver }}{{ $ver }}{{ end }} - {{ if .featured }}★ the star{{ end }} + ★ {{ with $stars }}{{ . }}{{ else }}Star{{ end }}

{{ .tagline }}

diff --git a/scripts/refresh-releases.py b/scripts/refresh-releases.py index d29e0fd..3d08ebf 100755 --- a/scripts/refresh-releases.py +++ b/scripts/refresh-releases.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -"""Refresh data/releases.json with each project's latest GitHub release tag. +"""Refresh data/releases.json (latest release tag) and data/stars.json (star count) per project. Run locally (`python3 scripts/refresh-releases.py`) to update the committed fallback, or in the deploy workflow to bake the current versions into the build. @@ -24,10 +24,10 @@ ORG = "p2pool-starter-stack" REPOS = ("pithead", "rigforge") DATA = pathlib.Path(__file__).resolve().parent.parent / "data" / "releases.json" +STARS = DATA.parent / "stars.json" -def latest_tag(repo: str) -> str: - url = f"https://api.github.com/repos/{ORG}/{repo}/releases/latest" +def api_json(url: str) -> dict: req = urllib.request.Request( url, headers={ @@ -39,13 +39,20 @@ def latest_tag(repo: str) -> str: if token: req.add_header("Authorization", f"Bearer {token}") with urllib.request.urlopen(req, timeout=15) as resp: - return json.load(resp).get("tag_name", "") + return json.load(resp) + + +def latest_tag(repo: str) -> str: + return api_json(f"https://api.github.com/repos/{ORG}/{repo}/releases/latest").get("tag_name", "") def main() -> int: data: dict[str, str] = {} + stars: dict[str, int] = {} if DATA.exists(): data = json.loads(DATA.read_text()) + if STARS.exists(): + stars = json.loads(STARS.read_text()) for repo in REPOS: try: @@ -57,8 +64,18 @@ def main() -> int: print(f"{repo}: no tag_name in response, keeping {data.get(repo)!r}", file=sys.stderr) except (urllib.error.URLError, OSError, ValueError) as exc: print(f"{repo}: keeping fallback {data.get(repo)!r} ({exc})", file=sys.stderr) + try: + count = api_json(f"https://api.github.com/repos/{ORG}/{repo}").get("stargazers_count") + if isinstance(count, int): + stars[repo] = count + print(f"{repo}: {count} stars") + else: + print(f"{repo}: no stargazers_count, keeping {stars.get(repo)!r}", file=sys.stderr) + except (urllib.error.URLError, OSError, ValueError) as exc: + print(f"{repo}: keeping star fallback {stars.get(repo)!r} ({exc})", file=sys.stderr) DATA.write_text(json.dumps(data, indent=2) + "\n") + STARS.write_text(json.dumps(stars, indent=2) + "\n") return 0