Running It For Real is a 14-part deep dive into everything between “it decodes on my laptop” and “it has been feeding a public Broadcastify channel for six months without me touching it.” GopherTrunk ships as a single static binary; this series is about running that binary as a real service — the auth posture you pick before it leaves your LAN, the metrics and logs that tell you it’s healthy, the diagnostics that catch a failing dongle before it costs you a call, the feature flags that keep optional subsystems off until you want them, the aggregator uploads, and the Docker/systemd plumbing that keeps it up.
Where RF Front End ended on the diagnostics-and-metrics payoff for the radio layer, this series is that same instinct applied to the whole daemon. And where Build in the Open covered CI, releases, and securing the repository, this is the operational half — securing and running the thing the repository produces.
Every post reads three ways: a TL;DR + cheat-sheet for skimmers, bold headers, tables, and diagrams for the medium read, and full prose with real code for the deep read.
New here? The Hardening and Opt-in features docs are the operator reference; this series is the design behind them, plus the Containers & Deployment module for first principles.<ol class="post-list series-list"><li class="post-card"> <h2 class="post-card__title">Running It For Real, Part 1: From a Laptop Demo to a 24/7 Service</h2> <p class="post-card__meta"> Deep dives </p><p class="post-card__desc">What actually changes when GopherTrunk stops being a laptop demo and becomes an unattended 24/7 service — the daemon lifecycle, dependency-ordered construction and teardown, graceful shutdown, the supervised spawn model, and the operator mindset behind the whole series.</p></li><li class="post-card"> <h2 class="post-card__title">Running It For Real, Part 2: Auth Posture — Closed-LAN, Auto, Required</h2> <p class="post-card__meta"> Deep dives </p><p class="post-card__desc">How GopherTrunk’s mutation-endpoint auth works — the disabled/auto/required modes, why the default flipped to disabled for closed-LAN deployments, the loopback and trusted-network bypasses, constant-time token comparison, and hot token rotation without a restart.</p></li><li class="post-card"> <h2 class="post-card__title">Running It For Real, Part 3: TLS & Sitting Behind a Reverse Proxy</h2> <p class="post-card__meta"> Deep dives </p><p class="post-card__desc">How GopherTrunk terminates TLS on its HTTP and gRPC listeners, why plain TCP stays the default, the both-or-neither cert/key rule, the permissive-by-default CORS allow-list, and the loopback-upstream reverse-proxy pattern with nginx or Caddy.</p></li><li class="post-card"> <h2 class="post-card__title">Running It For Real, Part 4: Metrics That Matter — Prometheus & SDR Tiles</h2> <p class="post-card__meta"> Deep dives </p><p class="post-card__desc">How GopherTrunk’s Prometheus registry is built — bus-driven counters versus scrape-time snapshot collectors, the SDR tiles worth alerting on (IQ power, clip ratio, gain, lock state), why calls_started beats calls_total, and the opt-in FEC histograms.</p></li><li class="post-card"> <h2 class="post-card__title">Running It For Real, Part 5: Structured Logs — Event, Message & Power</h2> <p class="post-card__meta"> Deep dives </p><p class="post-card__desc">How GopherTrunk writes three purpose-built logs off one event bus — the JSONL event log for machines, the human-readable decoded-message log, and the decode-gated power log — plus the panic-recovery guard that turns a crashing goroutine into a logged, survivable event.</p></li><li class="post-card"> <h2 class="post-card__title">Running It For Real, Part 6: The Diagnostics Reporter</h2> <p class="post-card__meta"> Deep dives </p><p class="post-card__desc">How GopherTrunk prepends a host/SDR snapshot to every error surface — the boxed boot banner, the memoized Collector that enumerates dongles at most once, the cheap-versus-costly split in SysInfo, the full error-chain verbose trace, and the non-TTY-safe reporter.</p></li><li class="post-card"> <h2 class="post-card__title">Running It For Real, Part 7: SDR Doctor & Preflight</h2> <p class="post-card__meta"> Deep dives </p><p class="post-card__desc">How GopherTrunk catches a bad dongle, wrong USB driver, or broken config before it costs a call — the read-only sdr doctor that inspects per-device driver binding, the preflight that validates directories and TLS files before the listener binds, and the gain-sanity warnings.</p></li><li class="post-card"> <h2 class="post-card__title">Running It For Real, Part 8: The Opt-In Feature Matrix</h2> <p class="post-card__meta"> Deep dives </p><p class="post-card__desc">How GopherTrunk decides what runs by default versus what stays off until you ask — the three kinds of feature gate, why headless-safe defaults matter, and the one config rule that keeps optional subsystems from surprising a 24/7 daemon.</p></li><li class="post-card"> <h2 class="post-card__title">Running It For Real, Part 9: Broadcast Backends I — Broadcastify</h2> <p class="post-card__meta"> Deep dives </p><p class="post-card__desc">Operating a Broadcastify Calls feed on a 24/7 daemon — where the API key and system ID live, how the two-leg upload retries with exponential backoff, how a rejection surfaces, and the counters that tell you a feed went quiet before your listeners do.</p></li><li class="post-card"> <h2 class="post-card__title">Running It For Real, Part 10: Broadcast Backends II — RdioScanner, OpenMHz, Icecast</h2> <p class="post-card__meta"> Deep dives </p><p class="post-card__desc">Operating the other three call destinations on a 24/7 daemon — RdioScanner and OpenMHz credentials and endpoints riding the shared retry loop, and why Icecast is the odd one out that drops instead of retrying, reconnects on its own, and needs a source password kept off disk.</p></li><li class="post-card"> <h2 class="post-card__title">Running It For Real, Part 11: Grant Webhooks & External Integrations</h2> <p class="post-card__meta"> Deep dives </p><p class="post-card__desc">Firing an HTTP webhook the instant a control-channel grant is decoded — the push form of GET /api/v1/grants for home automation, dashboards, and alerting, with a bounded queue that drops before it ever stalls the decoder, a shared JSON schema, and per-grant retry/backoff.</p></li><li class="post-card"> <h2 class="post-card__title">Running It For Real, Part 12: Docker & RTL-SDR USB Pass-Through</h2> <p class="post-card__meta"> Deep dives </p><p class="post-card__desc">Containerizing the pure-Go daemon and passing a real RTL-SDR through the container boundary — the multi-stage zero-CGO build, the three things a dongle needs inside a container (host udev, DVB blacklist, device mapping), and why least-privilege beats –privileged.</p></li><li class="post-card"> <h2 class="post-card__title">Running It For Real, Part 13: systemd Hardening & the Windows Installer</h2> <p class="post-card__meta"> Deep dives </p><p class="post-card__desc">A hardened systemd unit that sandboxes the daemon down to one USB device and a state directory, and the Inno Setup Windows installer that separates program from data, seeds a config, bundles the Zadig driver, and preserves your captures on uninstall.</p></li><li class="post-card"> <h2 class="post-card__title">Running It For Real, Part 14: Staying Up — Health, Watchdogs & the Ops Payoff</h2> <p class="post-card__meta"> Deep dives </p><p class="post-card__desc">The finale — the health endpoint that tells a probe the daemon is doing work not just running, the heartbeat that makes a stop never silent, the soft memory limit that dodges the OOM killer, and the USB watchdog that reacquires a dropped dongle without a restart.</p></li></ol><p class="blog-feed-link"> See all deep dives or subscribe via RSS. </p>