Repository navigation
feat: add observer_cli for inspecting a node from a remote shell - #301
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
The dependency constraint allows 2.1 despite the issue’s explicit intent to exclude it.
1 open issue
What changed in this PR
Adds observer_cli to Flick’s release for live node inspection through a remote IEx shell, complementing metrics and traces.
Changes:
- Adds and locks observer_cli 2.0.0.
- Documents remote-shell access, inspection commands, and safe exit procedures.
| File | Description |
|---|---|
| mix.lock | Locks observer_cli and its existing recon dependency. |
| mix.exs | Includes observer_cli in the release. |
| AGENTS.md | Documents node inspection and distribution safety. |
Review effort: Balanced
|
Verified in production after the deploy went live at 14:47 UTC. From the Shell tab of
Render Shell works on the One new line appeared in the boot log: "No open ports detected on 0.0.0.0, continuing to scan..." It came 6 seconds after Bandit bound port 10000, and the service went live 5 seconds later. The previous deploy had no such line. The new loopback-only listeners are a plausible cause, but that is unconfirmed. Worth checking whether it recurs on the next deploy. |

Closes #300
This adds observer_cli 2.x to the release, so a remote IEx shell on production can show a live, top-style view of the node. Prometheus and Tempo show trends, but they don't show which processes hold memory or which mailboxes are backing up. The change also documents the remote shell itself in CLAUDE.md, since nothing described it before.
Risk is in how the node starts, not in the app
observer_cli starts no processes at boot. Its only dependency,
recon2.5.6, already ships in prod through Paraxial, so the lock gains one package.The larger change is
rel/env.sh.eex. Before this, EPMD and the distribution port listened on every interface, so other services on Render's private network could reach them, guarded only by the cookie. They now bind to loopback, and the node is namedflick@localhost. If that breaks boot on Render, the deploy fails its health check, and a revert undoes it completely. The start command'seval "Flick.Release.migrate"still runs, sinceevalstarts no distribution.No app behavior changes, and
mix precommitpasses with the suite unchanged at 190 passing. This deploys, because the release itself changes.How to demo it
Locally, as a prod release. If
epmd -namesshows no nodes, stop any running EPMD withepmd -killfirst. An EPMD started earlier keeps listening on every interface, so the binding check below would mislead. Build the release, then start it against your dev database on port 4010. The basic-auth and metrics credentials are checked at compile time, so they must match the dev defaults or boot aborts.MIX_ENV=prod mix release --overwrite DATABASE_URL=ecto://postgres:postgres@localhost/flick_dev \ SECRET_KEY_BASE=$(openssl rand -hex 64) \ BASIC_AUTH_ADMIN_USERNAME=flick-admin BASIC_AUTH_ADMIN_PASSWORD=unsafe-password \ METRICS_AUTH_USERNAME=flick-metrics METRICS_AUTH_PASSWORD=unsafe-metrics-password \ PHX_SERVER=true PORT=4010 \ _build/prod/rel/flick/bin/flick startIn a second terminal, attach and start it:
The home page shows system, memory, and a table of the busiest processes. Press
mto rank by memory. Pressqand then Enter to quit, then Ctrl+C andato leave the shell.http://localhost:4010still answers afterward. To check the binding, runlsof -nP -iTCP -sTCP:LISTEN | grep -E 'epmd|beam'. EPMD on 4369 and the distribution port show127.0.0.1, and EPMD may also show[::1]. Stop the node with_build/prod/rel/flick/bin/flick stop.In production, after merge. Open the Shell tab of the
flickservice in the Render dashboard and run the sameremotecommand and:observer_cli.start(). I have run the local path but not this one, so this step is the real check that Render's Shell works on thestarterplan.Worth a reviewer's attention
mix.lockholds 2.0.0, so 2.1 arrives only through a reviewed update.DNS_CLUSTER_QUERYis unset on Render, so nothing clusters today. A second instance would need this binding revisited.