• 0 Posts
  • 4 Comments
Joined 16 days ago
Cake day: July 12th, 2026

  • Here’s the shape, if it saves you the fiddling. Put it in the compose file rather than a cron:

    healthcheck:
      test: ["CMD-SHELL", "wget -qO- http://localhost:3000/api/v1/trending >/dev/null || exit 1"]
      interval: 5m
      timeout: 10s
      retries: 3
    restart: unless-stopped
    

    Port and path to match your setup, and use wget rather than curl unless you know the image ships curl, since a healthcheck that fails because the binary is missing looks exactly like a service that is down.

    One catch: Docker marks a container unhealthy but won’t restart it for you. Either pair it with something like autoheal, which watches for that state, or keep your cron and have it check first and restart only on failure.

    Either way you get the thing the blind hourly restart can’t give you: a log of how often it actually fired. Never, and you didn’t need the restarts. Constantly, and there’s a real bug worth chasing rather than a schedule papering over it.


  • That line predates invidious-companion. When the player and signature handling still lived in the main process, a periodic kick was the honest workaround, and the docs never really caught up after companion split it out.

    What I’d push back on is the blind hourly restart, because it hides exactly the failure you just had. A companion image sitting a version behind shows up as things half-working, and a scheduled restart makes that go away for an hour at a time, so you never trace it. If you’re going to script something, script a check instead: hit an endpoint that actually plays a video, restart only when that fails, and log it when it does. Then a restart tells you something happened.

    Small thing that would have caught your case: docker compose pull with no service name pulls all three, and docker compose images prints the digests you’re actually running.


  • Before you redo the rest by hand, check whether the broken ones share a format. Black frames that render fine on the phones but not in a desktop browser usually mean the original file is intact and it was the server-side preview that failed to generate, with the phones quietly decoding the original themselves. HEIC and HEVC and 10-bit HDR are the usual suspects, since those lean on libheif and ffmpeg on the server and older builds choke on them.

    If that’s the cause, re-uploading only “works” because it reruns preview generation, so you’re really just triggering a fresh encode. Grep the museum logs around one of the bad files for a decode error, and see whether a rescan or clearing the thumbnail cache regenerates them in place. That would save you doing the whole library one file at a time.


  • The bland logs are themselves a data point. If the journal just stops mid-line with nothing unusual before it, that points at a hard hang or a power cut rather than something userspace did, because a kernel oops normally leaves a trace behind. There’s also a catch-22 in the SD theory: a card that’s failing can’t reliably write the log that would prove it’s failing.

    Two things worth doing before the card swap, both cheap. Check vcgencmd get_throttled: bit 16 stays set if undervoltage happened at any point since boot, so you get an answer on power-versus-card without having to catch the crash live. And switch on the hardware watchdog, bcm2835_wdt plus RuntimeWatchdogSec in systemd, so the Pi resets itself instead of waiting for someone to pull the plug. That doesn’t fix the cause, but it stops every crash from becoming an outage that lasts until you’re back home.


DeviceShelf Server alerts you when a device appears, disappears or opens a port. Tuning those rules used to mean editing config on the server itself. The desktop and mobile apps can now read and write a connected server’s alert policy: which events fire, the thresholds behind them, quiet hours, and whether things arrive as single alerts or as a digest. What never travels back to the client are the ntfy, Gotify, webhook and SMTP credentials. You can retune the alerting from your phone and still not be holding the secrets.


Disclosure: I’m the developer of DeviceShelf, a local-first network scanner. This isn’t a sales pitch. The Server edition is a paid product, but I want to talk through how one feature is built, because I think the design is the interesting part.

The headless Server edition now speaks MCP (Model Context Protocol), so an assistant like Claude Desktop can answer questions straight from your live network data: what’s online right now, anything new or offline since yesterday, which certificates are expiring, how tonight differs from last week’s snapshot.

The part I actually care about is keeping it fenced in, because giving a language model a read of your network inventory deserves some paranoia.

Everything stays on your LAN. The MCP endpoint runs inside the Server, on the same port as the API, behind a bearer token, reachable only on your LAN. No cloud connector, no remote OAuth. The only thing that ever leaves is whatever the AI client you connected decides to send.

Reads are the default, writes are opt-in twice. There are 14 read-only tools: inventory, recent changes, alarms, per-device history and uptime, a one-call security overview for expiring certs and CVEs, and snapshot diffs. The 8 action tools (rename a device, ack an alarm, create a check in plain language, trigger a scan) stay off until you flip a separate env switch, and a second switch makes the impactful ones ask for a yes first via MCP elicitation.

Device strings are treated as hostile input. Hostnames, banners and cert subjects are untrusted: bidi and zero-width spoofing characters are stripped, values are truncated, and the model is told to treat them as data. Prompt injection through a hostname a rogue device set to something clever is a real risk, and stripping the spoofing chars plus flagging the strings as data is the boring, correct answer. On top of that: auth required, a scoped token that can’t touch the admin API, rate-limiting, audit logging by tool name, and an Origin allowlist against DNS rebinding.

Off by default, fully additive, available from server 1.5.3. Full write-up with client configs (Claude Desktop, Cursor, VS Code, Windsurf, Cline, Gemini CLI) is on the blog: https://deviceshelf.app/blog/2026-07-01-ask-your-ai-about-your-network/

Curious where other self-hosters draw the line here — would you give an LLM read access to your inventory at all, and would you ever turn the write side on?