<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://boubli.github.io/AMUD-Dashboard/blog</id>
    <title>AMUD Dashboard Blog</title>
    <updated>2026-02-25T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://boubli.github.io/AMUD-Dashboard/blog"/>
    <subtitle>AMUD Dashboard Blog</subtitle>
    <icon>https://boubli.github.io/AMUD-Dashboard/img/AMUD-logo.png</icon>
    <rights>Copyright © 2026 AMUD Dashboard</rights>
    <entry>
        <title type="html"><![CDATA[Where Your Plex Token Actually Lives in AMUD Dashboard]]></title>
        <id>https://boubli.github.io/AMUD-Dashboard/blog/encrypted-secrets-at-rest</id>
        <link href="https://boubli.github.io/AMUD-Dashboard/blog/encrypted-secrets-at-rest"/>
        <updated>2026-02-25T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[AES-GCM encrypted integration creds in SQLite, .amud-secrets-key on disk. What gets encrypted and what doesn't.]]></summary>
        <content type="html"><![CDATA[<p>Storing <code>X-Plex-Token=abc123</code> in plain text in a yaml file on disk always felt wrong. Storing it in plain text in SQLite felt equally wrong.</p>
<p>AMUD Dashboard encrypts integration secrets <strong>at rest</strong> with AES-GCM. Plex, Jellyfin, Proxmox API tokens, Home Assistant tokens — encrypted blob in the database, not readable if someone copies <code>amud.db</code> without the key.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-keyfile">The keyfile<a href="https://boubli.github.io/AMUD-Dashboard/blog/encrypted-secrets-at-rest#the-keyfile" class="hash-link" aria-label="Direct link to The keyfile" title="Direct link to The keyfile" translate="no">​</a></h2>
<p><code>.amud-secrets-key</code> on the host. Derived key material for encryption/decryption at runtime.</p>
<p><strong>Back it up with your database.</strong> Restore DB without key = your tokens are toast. You'll re-enter them in settings. Annoying but not catastrophic.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="whats-not-encrypted">What's not encrypted<a href="https://boubli.github.io/AMUD-Dashboard/blog/encrypted-secrets-at-rest#whats-not-encrypted" class="hash-link" aria-label="Direct link to What's not encrypted" title="Direct link to What's not encrypted" translate="no">​</a></h2>
<p>App URLs, card names, layout stuff — none of that's secret. Your Jellyfin URL being <code>http://10.0.0.5:8096</code> isn't the sensitive part. The API key is.</p>
<p>Password <strong>hashes</strong> use Argon2id separately. Different layer. Same philosophy: don't store usable secrets in recoverable form.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="threat-model-realistic">Threat model (realistic)<a href="https://boubli.github.io/AMUD-Dashboard/blog/encrypted-secrets-at-rest#threat-model-realistic" class="hash-link" aria-label="Direct link to Threat model (realistic)" title="Direct link to Threat model (realistic)" translate="no">​</a></h2>
<p>This stops "someone copied my backup drive" from leaking your Proxmox token. It doesn't stop someone with root on your running server — they own the box anyway.</p>
<p>Homelab threat model. Not banking.</p>
<p>Full security writeup: <a class="" href="https://boubli.github.io/AMUD-Dashboard/docs/security">/docs/security</a></p>
<p>Rotate tokens in integrations settings if you think the DB leaked. Same as any other dashboard.</p>]]></content>
        <author>
            <name>Youssef Boubli</name>
            <email>bbb.vloger@gmail.com</email>
            <uri>https://github.com/boubli</uri>
        </author>
        <category label="Security" term="Security"/>
        <category label="Rust" term="Rust"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Why AMUD Dashboard Uses SQLite Instead of Postgres (Yes, Really)]]></title>
        <id>https://boubli.github.io/AMUD-Dashboard/blog/sqlite-wal-not-postgres</id>
        <link href="https://boubli.github.io/AMUD-Dashboard/blog/sqlite-wal-not-postgres"/>
        <updated>2026-02-23T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Embedded DB for embedded dashboard. WAL mode, single-file backup, no extra container for config storage.]]></summary>
        <content type="html"><![CDATA[<p>"Why not Postgres?"</p>
<p>Because then I'd need to run Postgres.</p>
<p>AMUD Dashboard is a dashboard. Config storage is a few hundred KB of apps, settings, and encrypted tokens. Running a whole separate database server for that is like buying a warehouse to store a shoebox.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="sqlite-with-wal">SQLite with WAL<a href="https://boubli.github.io/AMUD-Dashboard/blog/sqlite-wal-not-postgres#sqlite-with-wal" class="hash-link" aria-label="Direct link to SQLite with WAL" title="Direct link to SQLite with WAL" translate="no">​</a></h2>
<p>Write-Ahead Logging lets readers (the web UI loading settings) coexist with writers (you saving a new app card) without the lock contention that makes people hate SQLite in web apps from 2010.</p>
<p>For a single-tenant homelab dashboard with one admin clicking settings occasionally? Perfect fit.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="operational-wins">Operational wins<a href="https://boubli.github.io/AMUD-Dashboard/blog/sqlite-wal-not-postgres#operational-wins" class="hash-link" aria-label="Direct link to Operational wins" title="Direct link to Operational wins" translate="no">​</a></h2>
<ul>
<li class=""><strong>Zero extra container</strong> — <code>amud.db</code> sits next to the binary</li>
<li class=""><strong>Backup</strong> — <code>cp amud.db backup.db</code></li>
<li class=""><strong>Restore</strong> — swap file, restart</li>
<li class=""><strong>Inspect</strong> — <code>sqlite3 amud.db</code> when debugging</li>
</ul>
<p>I've done all of these at 1am. Postgres would add connection strings, another service to monitor, another thing to backup separately.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="when-id-reach-for-postgres">When I'd reach for Postgres<a href="https://boubli.github.io/AMUD-Dashboard/blog/sqlite-wal-not-postgres#when-id-reach-for-postgres" class="hash-link" aria-label="Direct link to When I'd reach for Postgres" title="Direct link to When I'd reach for Postgres" translate="no">​</a></h2>
<p>Multi-tenant SaaS. Hundreds of concurrent writers. Horizontal scaling. AMUD Dashboard is explicitly none of those — see roadmap "won't do SaaS."</p>
<p>Homelab tool. Homelab database. Match the complexity to the problem.</p>
<p><a class="" href="https://boubli.github.io/AMUD-Dashboard/docs/intro">/docs/intro</a></p>]]></content>
        <author>
            <name>Youssef Boubli</name>
            <email>bbb.vloger@gmail.com</email>
            <uri>https://github.com/boubli</uri>
        </author>
        <category label="Rust" term="Rust"/>
        <category label="Homelab" term="Homelab"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[I Migrated From Homepage to AMUD Dashboard — What I Lost and Gained]]></title>
        <id>https://boubli.github.io/AMUD-Dashboard/blog/migrated-from-homepage</id>
        <link href="https://boubli.github.io/AMUD-Dashboard/blog/migrated-from-homepage"/>
        <updated>2026-02-21T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Honest post-Homepage review. GitOps YAML vs browser config. No sugarcoating.]]></summary>
        <content type="html"><![CDATA[<p>I ran Homepage for a year. Liked it. Still recommend it for the right person.</p>
<p>Switching to AMUD Dashboard wasn't "Homepage bad, AMUD Dashboard good." It was "I'm tired of this specific workflow."</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-i-lost">What I lost<a href="https://boubli.github.io/AMUD-Dashboard/blog/migrated-from-homepage#what-i-lost" class="hash-link" aria-label="Direct link to What I lost" title="Direct link to What I lost" translate="no">​</a></h2>
<ul>
<li class=""><strong>Git-tracked config</strong> — every service change was a commit. That's gone. AMUD Dashboard lives in SQLite, not <code>services.yaml</code> in a repo.</li>
<li class=""><strong>Community widget YAML</strong> — Homepage's widget library is huge. AMUD Dashboard has built-in Plex/Jellyfin/HA/Proxmox stuff but not the long tail of community widgets.</li>
<li class=""><strong>Docker-only mental model</strong> — Homepage fits the "everything in compose" crowd perfectly.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-i-gained">What I gained<a href="https://boubli.github.io/AMUD-Dashboard/blog/migrated-from-homepage#what-i-gained" class="hash-link" aria-label="Direct link to What I gained" title="Direct link to What I gained" translate="no">​</a></h2>
<ul>
<li class=""><strong>UI edits at midnight</strong> — add a card from my phone browser. No SSH, no git pull on the host.</li>
<li class=""><strong>Native Proxmox LXC control</strong> — not a widget bolted on. First-class CTID binding and power actions.</li>
<li class=""><strong>RAM</strong> — meaningful on a crowded Proxmox node.</li>
<li class=""><strong>One-file backup</strong> — <code>amud.db</code> instead of yaml + env + secrets scattered around.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="who-should-stay-on-homepage">Who should stay on Homepage<a href="https://boubli.github.io/AMUD-Dashboard/blog/migrated-from-homepage#who-should-stay-on-homepage" class="hash-link" aria-label="Direct link to Who should stay on Homepage" title="Direct link to Who should stay on Homepage" translate="no">​</a></h2>
<p>You like GitOps. You generate configs from Ansible. You want fifty community widgets. YAML doesn't make you twitch.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="who-should-try-amud-dashboard">Who should try AMUD Dashboard<a href="https://boubli.github.io/AMUD-Dashboard/blog/migrated-from-homepage#who-should-try-amud-dashboard" class="hash-link" aria-label="Direct link to Who should try AMUD Dashboard" title="Direct link to Who should try AMUD Dashboard" translate="no">​</a></h2>
<p>Proxmox primary. YAML fatigue. Want live LXC status without shell scripts. Okay with "config in a database" as the trade.</p>
<p>Migration tip: screenshot your Homepage layout, recreate cards in AMUD Dashboard while watching TV. Took me about forty minutes for ~25 services. Your mileage varies.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token plain">curl -sSL https://raw.githubusercontent.com/boubli/AMUD-Dashboard/main/setup-amud.sh | bash</span><br></div></code></pre></div></div>]]></content>
        <author>
            <name>Youssef Boubli</name>
            <email>bbb.vloger@gmail.com</email>
            <uri>https://github.com/boubli</uri>
        </author>
        <category label="Homelab" term="Homelab"/>
        <category label="Self-Hosted" term="Self-Hosted"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Why AMUD Dashboard Is Two Binaries Instead of One Blob]]></title>
        <id>https://boubli.github.io/AMUD-Dashboard/blog/why-two-binaries</id>
        <link href="https://boubli.github.io/AMUD-Dashboard/blog/why-two-binaries"/>
        <updated>2026-02-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Server in LXC, agent on the hypervisor host. Separation of privileges and why the Unix socket exists.]]></summary>
        <content type="html"><![CDATA[<p>"Why not one binary?"</p>
<p>Because on Proxmox the dashboard server lives in an <strong>unprivileged LXC</strong> and the thing that talks to <code>/proc</code>, the Docker socket, and the PVE API on port 8006 needs to live on the <strong>host</strong>.</p>
<p>Different trust boundaries. Different privilege levels.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="amud-server">amud-server<a href="https://boubli.github.io/AMUD-Dashboard/blog/why-two-binaries#amud-server" class="hash-link" aria-label="Direct link to amud-server" title="Direct link to amud-server" translate="no">​</a></h2>
<ul>
<li class="">Serves HTTP/WebSockets</li>
<li class="">Owns SQLite</li>
<li class="">Runs as unprivileged <code>amud</code> user in the LXC</li>
<li class="">Never needs root</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="amud-agent">amud-agent<a href="https://boubli.github.io/AMUD-Dashboard/blog/why-two-binaries#amud-agent" class="hash-link" aria-label="Direct link to amud-agent" title="Direct link to amud-agent" translate="no">​</a></h2>
<ul>
<li class="">Reads host hardware</li>
<li class="">Queries Proxmox API</li>
<li class="">Optionally reads Docker socket</li>
<li class="">Runs on hypervisor host with the permissions that requires</li>
</ul>
<p>They talk over <code>/opt/amud/run/amud.sock</code>. Bind-mounted into the LXC on Proxmox installs. Shared Docker volume in container deployments.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="challenge-response-auth">Challenge-response auth<a href="https://boubli.github.io/AMUD-Dashboard/blog/why-two-binaries#challenge-response-auth" class="hash-link" aria-label="Direct link to Challenge-response auth" title="Direct link to Challenge-response auth" translate="no">​</a></h2>
<p>The socket isn't world-writable chaos. Agent proves it knows <code>AMUD_AGENT_SECRET</code> before the server accepts telemetry. Stops random local processes from feeding fake metrics.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="could-i-merge-them">Could I merge them?<a href="https://boubli.github.io/AMUD-Dashboard/blog/why-two-binaries#could-i-merge-them" class="hash-link" aria-label="Direct link to Could I merge them?" title="Direct link to Could I merge them?" translate="no">​</a></h2>
<p>On single-box Docker or bare-metal where server and agent share a host, they're still separate processes for isolation. Server crash doesn't take down polling. Agent restart doesn't drop active web sessions.</p>
<p>Might be over-engineered for a homelab. I'd rather over-engineer the security boundary than under-engineer it.</p>
<p><a class="" href="https://boubli.github.io/AMUD-Dashboard/docs/ARCHITECTURE">/docs/ARCHITECTURE</a></p>]]></content>
        <author>
            <name>Youssef Boubli</name>
            <email>bbb.vloger@gmail.com</email>
            <uri>https://github.com/boubli</uri>
        </author>
        <category label="Rust" term="Rust"/>
        <category label="Proxmox" term="Proxmox"/>
        <category label="Homelab" term="Homelab"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[AMUD Dashboard Is Open Source — Here's How to Actually Help]]></title>
        <id>https://boubli.github.io/AMUD-Dashboard/blog/contribute-to-amud</id>
        <link href="https://boubli.github.io/AMUD-Dashboard/blog/contribute-to-amud"/>
        <updated>2026-02-17T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Stars, issues, PRs, themes, docs. Homelab projects grow from real users reporting real weird setups.]]></summary>
        <content type="html"><![CDATA[<p>AMUD Dashboard isn't a startup. It's a homelab tool I built because I wanted it. But it gets better when other people break it in ways I didn't imagine.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="fastest-help-star-the-repo">Fastest help: star the repo<a href="https://boubli.github.io/AMUD-Dashboard/blog/contribute-to-amud#fastest-help-star-the-repo" class="hash-link" aria-label="Direct link to Fastest help: star the repo" title="Direct link to Fastest help: star the repo" translate="no">​</a></h2>
<p><a href="https://github.com/boubli/AMUD-Dashboard" target="_blank" rel="noopener noreferrer" class="">github.com/boubli/AMUD-Dashboard</a></p>
<p>Stars help GitHub discovery and lists like awesome-selfhosted. Sounds shallow. Matters anyway.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="try-it-and-tell-me-your-stack">Try it and tell me your stack<a href="https://boubli.github.io/AMUD-Dashboard/blog/contribute-to-amud#try-it-and-tell-me-your-stack" class="hash-link" aria-label="Direct link to Try it and tell me your stack" title="Direct link to Try it and tell me your stack" translate="no">​</a></h2>
<p>Proxmox version, RAM numbers, screenshot of your dashboard. <a href="https://github.com/boubli/AMUD-Dashboard/discussions" target="_blank" rel="noopener noreferrer" class="">GitHub Discussions</a> is the place. "Works on my weird ARM NAS" posts are gold.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="bug-reports-that-get-fixed-fast">Bug reports that get fixed fast<a href="https://boubli.github.io/AMUD-Dashboard/blog/contribute-to-amud#bug-reports-that-get-fixed-fast" class="hash-link" aria-label="Direct link to Bug reports that get fixed fast" title="Direct link to Bug reports that get fixed fast" translate="no">​</a></h2>
<ul>
<li class="">Steps to reproduce</li>
<li class=""><code>journalctl -u amud-agent -n 50</code> output</li>
<li class="">Whether you're Docker or native LXC</li>
</ul>
<p>Vague "doesn't work" issues sit longer. Fair warning.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pr-areas">PR areas<a href="https://boubli.github.io/AMUD-Dashboard/blog/contribute-to-amud#pr-areas" class="hash-link" aria-label="Direct link to PR areas" title="Direct link to PR areas" translate="no">​</a></h2>
<table><thead><tr><th>Area</th><th>Stack</th></tr></thead><tbody><tr><td>amud-server</td><td>Rust, Axum</td></tr><tr><td>amud-agent</td><td>Rust, Tokio</td></tr><tr><td>UI</td><td>HTML, Alpine.js, CSS</td></tr><tr><td>Docs</td><td>Docusaurus, Markdown</td></tr><tr><td>Themes</td><td>CSS variables</td></tr></tbody></table>
<p>Roadmap: <a class="" href="https://boubli.github.io/AMUD-Dashboard/docs/roadmap">/docs/roadmap</a> — ARM64 CI, webhooks, multi-node agents on the list.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="submit-a-theme">Submit a theme<a href="https://boubli.github.io/AMUD-Dashboard/blog/contribute-to-amud#submit-a-theme" class="hash-link" aria-label="Direct link to Submit a theme" title="Direct link to Submit a theme" translate="no">​</a></h2>
<p>CSS file + preview screenshot → PR to <code>docs/static/themes/</code> → shows up in <a class="" href="https://boubli.github.io/AMUD-Dashboard/themes">/themes</a>.</p>
<p>That's a contribution normies can do without touching Rust. Please do.</p>
<p>Thanks for reading this series. Go break something and file an issue.</p>]]></content>
        <author>
            <name>Youssef Boubli</name>
            <email>bbb.vloger@gmail.com</email>
            <uri>https://github.com/boubli</uri>
        </author>
        <category label="Homelab" term="Homelab"/>
        <category label="Self-Hosted" term="Self-Hosted"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Why I Picked Rust for a Dashboard That Sits Idle All Day]]></title>
        <id>https://boubli.github.io/AMUD-Dashboard/blog/why-rust-for-homelab-daemon</id>
        <link href="https://boubli.github.io/AMUD-Dashboard/blog/why-rust-for-homelab-daemon"/>
        <updated>2026-02-15T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[GC pauses, static binaries, Tokio concurrency. Developer brain dump on language choice for AMUD.]]></summary>
        <content type="html"><![CDATA[<p>A homelab dashboard is a weird workload. It idles 99% of the time but still needs to poll metrics every few seconds, hold WebSocket connections, encrypt secrets, and never leak memory over months of uptime.</p>
<p>That's systems programming territory. Not "spin up Express and call it a day" territory.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-not-node">Why not Node<a href="https://boubli.github.io/AMUD-Dashboard/blog/why-rust-for-homelab-daemon#why-not-node" class="hash-link" aria-label="Direct link to Why not Node" title="Direct link to Why not Node" translate="no">​</a></h2>
<p>I've run plenty of Node homelab tools. V8 heap sitting at 80–150MB for a bookmark page hurts when that box also runs Jellyfin and Sonarr. GC pauses during telemetry polling are rare but annoying when you're staring at a graph that stutters.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-not-go">Why not Go<a href="https://boubli.github.io/AMUD-Dashboard/blog/why-rust-for-homelab-daemon#why-not-go" class="hash-link" aria-label="Direct link to Why not Go" title="Direct link to Why not Go" translate="no">​</a></h2>
<p>Go would've been fine honestly. I picked Rust because I wanted memory safety without a GC, static binaries with embedded assets (<code>include_str!</code> for UI templates), and Tokio's async model for concurrent integration polls.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-stack-that-stuck">The stack that stuck<a href="https://boubli.github.io/AMUD-Dashboard/blog/why-rust-for-homelab-daemon#the-stack-that-stuck" class="hash-link" aria-label="Direct link to The stack that stuck" title="Direct link to The stack that stuck" translate="no">​</a></h2>
<ul>
<li class=""><strong>Axum</strong> — HTTP + WebSockets</li>
<li class=""><strong>rusqlite</strong> — embedded config, WAL mode</li>
<li class=""><strong>hyper + rustls</strong> — Proxmox HTTPS</li>
<li class=""><strong>hyperlocal</strong> — Docker socket</li>
<li class=""><strong>Argon2id</strong> — passwords</li>
</ul>
<p>Compile once, drop binary on host, run. No runtime install step.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="trade-offs-ill-admit">Trade-offs I'll admit<a href="https://boubli.github.io/AMUD-Dashboard/blog/why-rust-for-homelab-daemon#trade-offs-ill-admit" class="hash-link" aria-label="Direct link to Trade-offs I'll admit" title="Direct link to Trade-offs I'll admit" translate="no">​</a></h2>
<p>Rust compile times are slow. Contributor pool is smaller than JS. I occasionally fight the borrow checker at 2am.</p>
<p>For a long-running daemon on a 256MB LXC though? I'd make the same call again.</p>
<p>Architecture: <a class="" href="https://boubli.github.io/AMUD-Dashboard/docs/ARCHITECTURE">/docs/ARCHITECTURE</a></p>
<p>Want to hack on it: <a href="https://github.com/boubli/AMUD-Dashboard" target="_blank" rel="noopener noreferrer" class="">github.com/boubli/AMUD-Dashboard</a></p>]]></content>
        <author>
            <name>Youssef Boubli</name>
            <email>bbb.vloger@gmail.com</email>
            <uri>https://github.com/boubli</uri>
        </author>
        <category label="Rust" term="Rust"/>
        <category label="Homelab" term="Homelab"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Deploying AMUD Dashboard Through Portainer (For Clickers Not SSHers)]]></title>
        <id>https://boubli.github.io/AMUD-Dashboard/blog/portainer-deploy</id>
        <link href="https://boubli.github.io/AMUD-Dashboard/blog/portainer-deploy"/>
        <updated>2026-02-13T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Stack template, matching AMUD_AGENT_SECRET, Docker socket mount. GUI homelab crowd deserves dashboards too.]]></summary>
        <content type="html"><![CDATA[<p>I live in SSH. Some of you live in Portainer. Both are valid.</p>
<p>AMUD Dashboard deploys as a stack: <code>amud_app</code> + <code>amud_agent</code> + <code>amud_run</code> volume.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="portainer-steps">Portainer steps<a href="https://boubli.github.io/AMUD-Dashboard/blog/portainer-deploy#portainer-steps" class="hash-link" aria-label="Direct link to Portainer steps" title="Direct link to Portainer steps" translate="no">​</a></h2>
<ol>
<li class=""><strong>Stacks → Add stack</strong> → name it <code>amud</code></li>
<li class="">Paste the compose from <a class="" href="https://boubli.github.io/AMUD-Dashboard/docs/installation/docker">/docs/installation/docker</a></li>
<li class="">Set <code>AMUD_AGENT_SECRET</code> to something long and random</li>
<li class=""><strong>Same secret in both services</strong> — write it down</li>
<li class="">Deploy</li>
</ol>
<p>Agent needs <code>/var/run/docker.sock:ro</code> and <code>AMUD_DOCKER=1</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="after-deploy">After deploy<a href="https://boubli.github.io/AMUD-Dashboard/blog/portainer-deploy#after-deploy" class="hash-link" aria-label="Direct link to After deploy" title="Direct link to After deploy" translate="no">​</a></h2>
<p><code>http://your-host:8000</code> → login → change password → add cards in UI.</p>
<p>Bind <code>./data</code> to a host path you snapshot. That's your backup.</p>
<p>Portainer-specific notes: <a class="" href="https://boubli.github.io/AMUD-Dashboard/docs/installation/portainer">/docs/installation/portainer</a></p>
<p>Docker path uses a bit more RAM than native Proxmox LXC. Trade-off for convenience.</p>]]></content>
        <author>
            <name>Youssef Boubli</name>
            <email>bbb.vloger@gmail.com</email>
            <uri>https://github.com/boubli</uri>
        </author>
        <category label="Docker" term="Docker"/>
        <category label="Homelab" term="Homelab"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Turning an Old Tablet Into a Homelab Status Board]]></title>
        <id>https://boubli.github.io/AMUD-Dashboard/blog/wall-mounted-dashboard</id>
        <link href="https://boubli.github.io/AMUD-Dashboard/blog/wall-mounted-dashboard"/>
        <updated>2026-02-11T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Grid density, guest mode, theme gallery wallpapers, kiosk browser tips. AMUD Dashboard was basically made for wall mounts.]]></summary>
        <content type="html"><![CDATA[<p>I've got an old iPad on a desk mount running AMUD Dashboard in guest mode. Shows CPU, which lights are on, if Plex is streaming, whether the *arr stack is actually running. Wife approves because it doesn't look like a terminal.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="appearance-settings-that-matter">Appearance settings that matter<a href="https://boubli.github.io/AMUD-Dashboard/blog/wall-mounted-dashboard#appearance-settings-that-matter" class="hash-link" aria-label="Direct link to Appearance settings that matter" title="Direct link to Appearance settings that matter" translate="no">​</a></h2>
<p><strong>Settings → Appearance</strong></p>
<ul>
<li class=""><strong>Grid columns:</strong> 4–5 on a landscape tablet</li>
<li class=""><strong>Glass opacity:</strong> lower = cleaner in bright rooms</li>
<li class=""><strong>Background:</strong> grab a 2K wallpaper from <a class="" href="https://boubli.github.io/AMUD-Dashboard/themes">/themes</a></li>
<li class=""><strong>Custom CSS:</strong> Nord or Everforest for low glare</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-to-put-on-the-board">What to put on the board<a href="https://boubli.github.io/AMUD-Dashboard/blog/wall-mounted-dashboard#what-to-put-on-the-board" class="hash-link" aria-label="Direct link to What to put on the board" title="Direct link to What to put on the board" translate="no">​</a></h2>
<ul>
<li class="">Home Assistant card (lights + temp)</li>
<li class="">Plex/Jellyfin with live stream badge</li>
<li class="">Host CPU/RAM bars</li>
<li class="">Key services with RUNNING status</li>
</ul>
<p>Skip the admin controls on a shared display. Guest account.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="kiosk-browsers">Kiosk browsers<a href="https://boubli.github.io/AMUD-Dashboard/blog/wall-mounted-dashboard#kiosk-browsers" class="hash-link" aria-label="Direct link to Kiosk browsers" title="Direct link to Kiosk browsers" translate="no">​</a></h2>
<ul>
<li class=""><strong>Android:</strong> Fully Kiosk Browser</li>
<li class=""><strong>iPad:</strong> Guided Access</li>
<li class=""><strong>Linux SBC:</strong> Chromium <code>--kiosk</code></li>
</ul>
<p>Point at your HTTPS URL (see the reverse proxy post). WebSockets need to work or the graphs lie.</p>
<p>That's it. Old hardware, new purpose, zero YAML.</p>]]></content>
        <author>
            <name>Youssef Boubli</name>
            <email>bbb.vloger@gmail.com</email>
            <uri>https://github.com/boubli</uri>
        </author>
        <category label="Homelab" term="Homelab"/>
        <category label="Themes" term="Themes"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Guest Mode So Your Family Doesn't Stop the Plex Container]]></title>
        <id>https://boubli.github.io/AMUD-Dashboard/blog/admin-vs-guest</id>
        <link href="https://boubli.github.io/AMUD-Dashboard/blog/admin-vs-guest"/>
        <updated>2026-02-09T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Admin sees power controls. Guest sees links and optional telemetry. Kitchen tablet stays safe.]]></summary>
        <content type="html"><![CDATA[<p>Put a dashboard on a kitchen wall tablet. Someone will eventually tap the wrong button.</p>
<p>AMUD Dashboard has <strong>Admin</strong> and <strong>Guest</strong> roles. Guests get links. Admins get the keys to the kingdom.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-guests-can-do">What guests can do<a href="https://boubli.github.io/AMUD-Dashboard/blog/admin-vs-guest#what-guests-can-do" class="hash-link" aria-label="Direct link to What guests can do" title="Direct link to What guests can do" translate="no">​</a></h2>
<ul>
<li class="">Open app URLs</li>
<li class="">See the layout you configured</li>
<li class="">Optionally see host CPU/RAM if you enable <strong>Guest system telemetry visibility</strong> under <strong>Settings → Privacy &amp; Access</strong></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-guests-cant-do">What guests can't do<a href="https://boubli.github.io/AMUD-Dashboard/blog/admin-vs-guest#what-guests-cant-do" class="hash-link" aria-label="Direct link to What guests can't do" title="Direct link to What guests can't do" translate="no">​</a></h2>
<ul>
<li class="">Edit cards or settings</li>
<li class="">Start/stop containers</li>
<li class="">See container names/VMIDs on sensitive telemetry</li>
<li class="">Mess with integrations</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="wall-tablet-setup">Wall tablet setup<a href="https://boubli.github.io/AMUD-Dashboard/blog/admin-vs-guest#wall-tablet-setup" class="hash-link" aria-label="Direct link to Wall tablet setup" title="Direct link to Wall tablet setup" translate="no">​</a></h2>
<ol>
<li class="">Create a Guest user</li>
<li class="">Enable public telemetry if you want the pretty graphs</li>
<li class="">Log the tablet into Guest</li>
<li class="">Stop worrying</li>
</ol>
<p>Admins keep full power controls on linked LXCs. Guests just see whether stuff is running without the big red stop button.</p>
<p><a class="" href="https://boubli.github.io/AMUD-Dashboard/docs/configuration">/docs/configuration</a></p>]]></content>
        <author>
            <name>Youssef Boubli</name>
            <email>bbb.vloger@gmail.com</email>
            <uri>https://github.com/boubli</uri>
        </author>
        <category label="Homelab" term="Homelab"/>
        <category label="Security" term="Security"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Why Your App Cards Are Stuck on CHECKING...]]></title>
        <id>https://boubli.github.io/AMUD-Dashboard/blog/fix-checking-badge</id>
        <link href="https://boubli.github.io/AMUD-Dashboard/blog/fix-checking-badge"/>
        <updated>2026-02-07T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[CPU bars work but LXC badges don't? It's almost always the Proxmox API token. Here's how to read agent logs and fix it.]]></summary>
        <content type="html"><![CDATA[<p>Top bar shows live CPU. App cards say <strong>CHECKING...</strong> forever.</p>
<p>Welcome to the most common AMUD Dashboard support question. Good news: it's usually one of like four things.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="read-the-agent-logs-first">Read the agent logs first<a href="https://boubli.github.io/AMUD-Dashboard/blog/fix-checking-badge#read-the-agent-logs-first" class="hash-link" aria-label="Direct link to Read the agent logs first" title="Direct link to Read the agent logs first" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token plain">journalctl -u amud-agent --no-pager -n 20</span><br></div></code></pre></div></div>
<p>Look for <code>[LXC]</code> lines:</p>
<table><thead><tr><th>Log</th><th>Meaning</th></tr></thead><tbody><tr><td><code>PVE_API_TOKEN not set</code></td><td>Token missing from systemd env</td></tr><tr><td><code>Successfully fetched 0 containers</code></td><td>Privilege Separation still on</td></tr><tr><td><code>HTTP 401</code></td><td>Wrong token secret</td></tr><tr><td><code>HTTP 500/595</code></td><td>Bad node hostname in config</td></tr></tbody></table>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="fix-the-token-in-systemd">Fix the token in systemd<a href="https://boubli.github.io/AMUD-Dashboard/blog/fix-checking-badge#fix-the-token-in-systemd" class="hash-link" aria-label="Direct link to Fix the token in systemd" title="Direct link to Fix the token in systemd" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token plain">nano /etc/systemd/system/amud-agent.service</span><br></div></code></pre></div></div>
<p>Under <code>[Service]</code>:</p>
<div class="language-ini codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ini codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token plain">Environment="PVE_API_TOKEN=PVEAPIToken=amud@pve!amud-token=YOUR-SECRET"</span><br></div></code></pre></div></div>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token plain">systemctl daemon-reload &amp;&amp; systemctl restart amud-agent</span><br></div></code></pre></div></div>
<p>Also paste the same token in the UI under <strong>Settings → Proxmox VE</strong>. Both places. Yes, redundant. Yes, necessary.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="privilege-separation">Privilege Separation<a href="https://boubli.github.io/AMUD-Dashboard/blog/fix-checking-badge#privilege-separation" class="hash-link" aria-label="Direct link to Privilege Separation" title="Direct link to Privilege Separation" translate="no">​</a></h2>
<p>When creating the API token in Proxmox, <strong>uncheck Privilege Separation</strong>. I cannot stress this enough. Spent two hours on this once. Not proud.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="ctid-wrong">CTID wrong<a href="https://boubli.github.io/AMUD-Dashboard/blog/fix-checking-badge#ctid-wrong" class="hash-link" aria-label="Direct link to CTID wrong" title="Direct link to CTID wrong" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token plain">pct list</span><br></div></code></pre></div></div>
<p>Make sure the app card ID matches reality.</p>
<p>Full troubleshooting bible: <a class="" href="https://boubli.github.io/AMUD-Dashboard/docs/troubleshooting">/docs/troubleshooting</a></p>]]></content>
        <author>
            <name>Youssef Boubli</name>
            <email>bbb.vloger@gmail.com</email>
            <uri>https://github.com/boubli</uri>
        </author>
        <category label="Proxmox" term="Proxmox"/>
        <category label="Homelab" term="Homelab"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Back Up Your Entire Dashboard in One File]]></title>
        <id>https://boubli.github.io/AMUD-Dashboard/blog/backup-amud-db</id>
        <link href="https://boubli.github.io/AMUD-Dashboard/blog/backup-amud-db"/>
        <updated>2026-02-05T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[amud.db is your whole config. Copy it. Don't forget .amud-secrets-key if you use encrypted integrations.]]></summary>
        <content type="html"><![CDATA[<p>I've seen people maintain elaborate backup scripts for YAML dashboards — git repos, env files, secret sidecars, three different paths.</p>
<p>AMUD Dashboard backup:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token plain">cp /opt/amud/data/amud.db ~/backups/amud-$(date +%F).db</span><br></div></code></pre></div></div>
<p>Done. Apps, tabs, settings, users, encrypted creds (encrypted blob in DB).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="restore">Restore<a href="https://boubli.github.io/AMUD-Dashboard/blog/backup-amud-db#restore" class="hash-link" aria-label="Direct link to Restore" title="Direct link to Restore" translate="no">​</a></h2>
<ol>
<li class="">Stop <code>amud-server</code></li>
<li class="">Replace <code>amud.db</code></li>
<li class="">Start <code>amud-server</code></li>
</ol>
<p>Your dashboard is exactly as it was. I've used this to clone a test setup to prod. Worked first try.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="dont-forget-the-keyfile">Don't forget the keyfile<a href="https://boubli.github.io/AMUD-Dashboard/blog/backup-amud-db#dont-forget-the-keyfile" class="hash-link" aria-label="Direct link to Don't forget the keyfile" title="Direct link to Don't forget the keyfile" translate="no">​</a></h2>
<p>Integrations use <code>.amud-secrets-key</code> for AES-GCM. Backup it <strong>with</strong> the database. Restore DB without key = encrypted tokens become useless noise.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="cron-it-and-forget-it">Cron it and forget it<a href="https://boubli.github.io/AMUD-Dashboard/blog/backup-amud-db#cron-it-and-forget-it" class="hash-link" aria-label="Direct link to Cron it and forget it" title="Direct link to Cron it and forget it" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token plain">0 3 * * * cp /opt/amud/data/amud.db /mnt/nas/backups/amud-$(date +\%F).db</span><br></div></code></pre></div></div>
<p>Keep a week of dailies. Homelab disasters always happen on the day you skipped backups.</p>
<p>More: <a class="" href="https://boubli.github.io/AMUD-Dashboard/docs/troubleshooting">/docs/troubleshooting</a></p>]]></content>
        <author>
            <name>Youssef Boubli</name>
            <email>bbb.vloger@gmail.com</email>
            <uri>https://github.com/boubli</uri>
        </author>
        <category label="Homelab" term="Homelab"/>
        <category label="Self-Hosted" term="Self-Hosted"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Running AMUD Dashboard on Bare Metal (No Docker, No LXC)]]></title>
        <id>https://boubli.github.io/AMUD-Dashboard/blog/bare-metal-linux-install</id>
        <link href="https://boubli.github.io/AMUD-Dashboard/blog/bare-metal-linux-install"/>
        <updated>2026-02-03T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Dedicated amud system user, /opt/amud layout, systemd units. Lowest overhead if you have a spare NUC.]]></summary>
        <content type="html"><![CDATA[<p>Sometimes you have a spare NUC or mini PC that does one job: show the dashboard on a wall and nothing else.</p>
<p>Docker on that box is overhead you don't need.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="directory-layout">Directory layout<a href="https://boubli.github.io/AMUD-Dashboard/blog/bare-metal-linux-install#directory-layout" class="hash-link" aria-label="Direct link to Directory layout" title="Direct link to Directory layout" translate="no">​</a></h2>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token plain">/opt/amud/run   → Unix socket</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">/opt/amud/data  → amud.db</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">/opt/amud/ui    → templates</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="dont-run-as-root">Don't run as root<a href="https://boubli.github.io/AMUD-Dashboard/blog/bare-metal-linux-install#dont-run-as-root" class="hash-link" aria-label="Direct link to Don't run as root" title="Direct link to Don't run as root" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token plain">sudo groupadd --system amud</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">sudo useradd --system -g amud -s /sbin/nologin amud</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">sudo mkdir -p /opt/amud/run /opt/amud/data /opt/amud/ui</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">sudo chown -R amud:amud /opt/amud</span><br></div></code></pre></div></div>
<p>Server runs as <code>amud</code>. Agent typically needs more privileges for host metrics — see the full guide for the permission model.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="binaries">Binaries<a href="https://boubli.github.io/AMUD-Dashboard/blog/bare-metal-linux-install#binaries" class="hash-link" aria-label="Direct link to Binaries" title="Direct link to Binaries" translate="no">​</a></h2>
<p>Grab latest from <a href="https://github.com/boubli/AMUD-Dashboard/releases" target="_blank" rel="noopener noreferrer" class="">GitHub Releases</a>. Drop <code>amud-server</code> and <code>amud-agent</code> in <code>/usr/local/bin/</code>, set up systemd units, go.</p>
<p>Works on Debian, Ubuntu, Fedora, Arch — anything with systemd.</p>
<p>Full walkthrough: <a class="" href="https://boubli.github.io/AMUD-Dashboard/docs/installation/linux">/docs/installation/linux</a></p>
<p>When I'd pick this over Proxmox LXC: dedicated dashboard hardware, no hypervisor, absolute minimum RAM.</p>]]></content>
        <author>
            <name>Youssef Boubli</name>
            <email>bbb.vloger@gmail.com</email>
            <uri>https://github.com/boubli</uri>
        </author>
        <category label="Homelab" term="Homelab"/>
        <category label="Self-Hosted" term="Self-Hosted"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[AMUD Dashboard vs Heimdall vs Homepage vs Homarr (I'll Be Honest)]]></title>
        <id>https://boubli.github.io/AMUD-Dashboard/blog/amud-vs-heimdall-homepage-homarr</id>
        <link href="https://boubli.github.io/AMUD-Dashboard/blog/amud-vs-heimdall-homepage-homarr"/>
        <updated>2026-02-01T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[I built AMUD Dashboard so I'm biased. Here's when you'd still pick something else.]]></summary>
        <content type="html"><![CDATA[<p>I built AMUD. I'm biased. Here's the honest comparison anyway.</p>
<table><thead><tr><th></th><th style="text-align:center">AMUD</th><th style="text-align:center">Heimdall</th><th style="text-align:center">Homepage</th><th style="text-align:center">Homarr</th></tr></thead><tbody><tr><td>Runtime</td><td style="text-align:center">Rust binary</td><td style="text-align:center">PHP/Laravel</td><td style="text-align:center">Node/React</td><td style="text-align:center">Next.js</td></tr><tr><td>Config</td><td style="text-align:center">SQLite + UI</td><td style="text-align:center">DB + UI</td><td style="text-align:center">YAML</td><td style="text-align:center">UI + files</td></tr><tr><td>Idle RAM</td><td style="text-align:center">~26–35MB (PVE native)</td><td style="text-align:center">~150MB</td><td style="text-align:center">varies</td><td style="text-align:center">200MB+</td></tr><tr><td>Proxmox LXC control</td><td style="text-align:center">native</td><td style="text-align:center">no</td><td style="text-align:center">widgets</td><td style="text-align:center">limited</td></tr><tr><td>YAML required</td><td style="text-align:center">never</td><td style="text-align:center">no</td><td style="text-align:center">yes</td><td style="text-align:center">partial</td></tr></tbody></table>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pick-heimdall-if">Pick Heimdall if<a href="https://boubli.github.io/AMUD-Dashboard/blog/amud-vs-heimdall-homepage-homarr#pick-heimdall-if" class="hash-link" aria-label="Direct link to Pick Heimdall if" title="Direct link to Pick Heimdall if" translate="no">​</a></h2>
<p>You want simple bookmarks and PHP on your server doesn't bother you. No live telemetry needed.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pick-homepage-if">Pick Homepage if<a href="https://boubli.github.io/AMUD-Dashboard/blog/amud-vs-heimdall-homepage-homarr#pick-homepage-if" class="hash-link" aria-label="Direct link to Pick Homepage if" title="Direct link to Pick Homepage if" translate="no">​</a></h2>
<p>You live in Git, love YAML, want the widget ecosystem. You're good at debugging indent errors. Respect.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pick-homarr-if">Pick Homarr if<a href="https://boubli.github.io/AMUD-Dashboard/blog/amud-vs-heimdall-homepage-homarr#pick-homarr-if" class="hash-link" aria-label="Direct link to Pick Homarr if" title="Direct link to Pick Homarr if" translate="no">​</a></h2>
<p>You want the polished drag-drop UI and don't care about RAM. *arr integration out of the box matters to you.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pick-amud-dashboard-if">Pick AMUD Dashboard if<a href="https://boubli.github.io/AMUD-Dashboard/blog/amud-vs-heimdall-homepage-homarr#pick-amud-dashboard-if" class="hash-link" aria-label="Direct link to Pick AMUD Dashboard if" title="Direct link to Pick AMUD Dashboard if" translate="no">​</a></h2>
<ul>
<li class="">Proxmox is your hypervisor and you want native LXC status + power controls</li>
<li class="">You refuse to maintain YAML for a link portal</li>
<li class="">You want Plex/Jellyfin/HA/host metrics without gluing shell scripts</li>
<li class="">~26MB idle on Proxmox sounds nice</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-amud-dashboard-wont-become">What AMUD Dashboard won't become<a href="https://boubli.github.io/AMUD-Dashboard/blog/amud-vs-heimdall-homepage-homarr#what-amud-dashboard-wont-become" class="hash-link" aria-label="Direct link to What AMUD Dashboard won't become" title="Direct link to What AMUD Dashboard won't become" translate="no">​</a></h2>
<p>SaaS. YAML-first config. Node/PHP dependency. It's a homelab tool. Stays that way.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token plain">curl -sSL https://raw.githubusercontent.com/boubli/AMUD-Dashboard/main/setup-amud.sh | bash</span><br></div></code></pre></div></div>
<p><a href="https://github.com/boubli/AMUD-Dashboard" target="_blank" rel="noopener noreferrer" class="">GitHub</a> · <a class="" href="https://boubli.github.io/AMUD-Dashboard/themes">Themes</a></p>]]></content>
        <author>
            <name>Youssef Boubli</name>
            <email>bbb.vloger@gmail.com</email>
            <uri>https://github.com/boubli</uri>
        </author>
        <category label="Homelab" term="Homelab"/>
        <category label="Self-Hosted" term="Self-Hosted"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Putting AMUD Dashboard Behind Nginx Without Breaking Live Metrics]]></title>
        <id>https://boubli.github.io/AMUD-Dashboard/blog/reverse-proxy-websockets</id>
        <link href="https://boubli.github.io/AMUD-Dashboard/blog/reverse-proxy-websockets"/>
        <updated>2026-01-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[If your CPU graphs freeze at 0%, your reverse proxy probably isn't forwarding WebSocket upgrades. Fix inside.]]></summary>
        <content type="html"><![CDATA[<p>Deployed AMUD Dashboard behind Nginx, opened the page, everything looked fine except the CPU bar was stuck at 0% like the server was dead. Server wasn't dead. Nginx just ate the WebSocket upgrade.</p>
<p>AMUD Dashboard streams telemetry over WebSockets. Your reverse proxy <strong>must</strong> forward upgrade headers or you get a pretty but useless dashboard.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="nginx-snippet-that-actually-works">Nginx snippet that actually works<a href="https://boubli.github.io/AMUD-Dashboard/blog/reverse-proxy-websockets#nginx-snippet-that-actually-works" class="hash-link" aria-label="Direct link to Nginx snippet that actually works" title="Direct link to Nginx snippet that actually works" translate="no">​</a></h2>
<div class="language-nginx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-nginx codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token plain">location / {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    proxy_pass http://127.0.0.1:8000;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    proxy_set_header Host $host;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    proxy_set_header X-Real-IP $remote_addr;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    proxy_set_header X-Forwarded-Proto $scheme;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    proxy_http_version 1.1;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    proxy_set_header Upgrade $http_upgrade;</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    proxy_set_header Connection "upgrade";</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="https-cookies">HTTPS cookies<a href="https://boubli.github.io/AMUD-Dashboard/blog/reverse-proxy-websockets#https-cookies" class="hash-link" aria-label="Direct link to HTTPS cookies" title="Direct link to HTTPS cookies" translate="no">​</a></h2>
<p>Once you're on HTTPS:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token plain">AMUD_SECURE_COOKIES=1</span><br></div></code></pre></div></div>
<p>Restart the server. Forget this and you'll chase phantom login bugs.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="caddy">Caddy<a href="https://boubli.github.io/AMUD-Dashboard/blog/reverse-proxy-websockets#caddy" class="hash-link" aria-label="Direct link to Caddy" title="Direct link to Caddy" translate="no">​</a></h2>
<div class="language-caddy codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-caddy codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token plain">amud.homelab.local {</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    reverse_proxy localhost:8000</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></div></code></pre></div></div>
<p>Usually just works. Caddy's the easy mode.</p>
<p>Full configs: <a class="" href="https://boubli.github.io/AMUD-Dashboard/docs/installation/reverse-proxy">/docs/installation/reverse-proxy</a></p>
<p>After setup: login works, graphs move, LXC badges update. If not, browser console first. Always browser console first.</p>]]></content>
        <author>
            <name>Youssef Boubli</name>
            <email>bbb.vloger@gmail.com</email>
            <uri>https://github.com/boubli</uri>
        </author>
        <category label="Homelab" term="Homelab"/>
        <category label="Security" term="Security"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Securing a Dashboard That Knows Where Everything Lives]]></title>
        <id>https://boubli.github.io/AMUD-Dashboard/blog/securing-homelab-dashboard</id>
        <link href="https://boubli.github.io/AMUD-Dashboard/blog/securing-homelab-dashboard"/>
        <updated>2026-01-28T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Argon2id passwords, encrypted integration secrets, CSRF, rate limiting — what AMUD Dashboard actually ships with.]]></summary>
        <content type="html"><![CDATA[<p>Your dashboard is a map to your entire homelab. Treat it like one.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="passwords">Passwords<a href="https://boubli.github.io/AMUD-Dashboard/blog/securing-homelab-dashboard#passwords" class="hash-link" aria-label="Direct link to Passwords" title="Direct link to Passwords" translate="no">​</a></h2>
<p><strong>Argon2id</strong> hashes in SQLite. Not SHA-256 alone, not md5 (please). Older installs with legacy SHA-256 get transparently re-hashed on next login.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="sessions">Sessions<a href="https://boubli.github.io/AMUD-Dashboard/blog/securing-homelab-dashboard#sessions" class="hash-link" aria-label="Direct link to Sessions" title="Direct link to Sessions" translate="no">​</a></h2>
<p>32-byte random tokens, 24h lifetime, <code>HttpOnly</code>, <code>SameSite=Strict</code>. Behind HTTPS set <code>AMUD_SECURE_COOKIES=1</code> or you're leaving cookies exposed on misconfigured proxies.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="brute-force">Brute force<a href="https://boubli.github.io/AMUD-Dashboard/blog/securing-homelab-dashboard#brute-force" class="hash-link" aria-label="Direct link to Brute force" title="Direct link to Brute force" translate="no">​</a></h2>
<p>5 failed logins per username in 5 minutes. Enough to stop dumb scripts, not enough to lock you out forever if you typo once.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="integration-secrets">Integration secrets<a href="https://boubli.github.io/AMUD-Dashboard/blog/securing-homelab-dashboard#integration-secrets" class="hash-link" aria-label="Direct link to Integration secrets" title="Direct link to Integration secrets" translate="no">​</a></h2>
<p>Plex tokens, Jellyfin keys, Proxmox API tokens, HA tokens — <strong>AES-GCM encrypted at rest</strong> with a host keyfile (<code>.amud-secrets-key</code>). Backup that file with your database or restores get awkward.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="csrf--csp">CSRF + CSP<a href="https://boubli.github.io/AMUD-Dashboard/blog/securing-homelab-dashboard#csrf--csp" class="hash-link" aria-label="Direct link to CSRF + CSP" title="Direct link to CSRF + CSP" translate="no">​</a></h2>
<p>State-changing requests need CSRF tokens. CSP with per-request nonces on scripts. Boring security stuff that matters when your dashboard is internet-facing behind a reverse proxy.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="production-checklist">Production checklist<a href="https://boubli.github.io/AMUD-Dashboard/blog/securing-homelab-dashboard#production-checklist" class="hash-link" aria-label="Direct link to Production checklist" title="Direct link to Production checklist" translate="no">​</a></h2>
<ul>
<li class="">Change <code>admin</code> / <code>password</code> (seriously)</li>
<li class="">HTTPS + <code>AMUD_SECURE_COOKIES=1</code></li>
<li class="">Restricted Proxmox API user, not root</li>
<li class="">Backup <code>amud.db</code> and <code>.amud-secrets-key</code></li>
</ul>
<p>Full doc: <a class="" href="https://boubli.github.io/AMUD-Dashboard/docs/security">/docs/security</a></p>]]></content>
        <author>
            <name>Youssef Boubli</name>
            <email>bbb.vloger@gmail.com</email>
            <uri>https://github.com/boubli</uri>
        </author>
        <category label="Security" term="Security"/>
        <category label="Self-Hosted" term="Self-Hosted"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[12 Free Themes Because Orange Glass Isn't for Everyone]]></title>
        <id>https://boubli.github.io/AMUD-Dashboard/blog/twelve-free-themes</id>
        <link href="https://boubli.github.io/AMUD-Dashboard/blog/twelve-free-themes"/>
        <updated>2026-01-26T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Copy-paste CSS from the theme gallery. Dracula, Nord, Catppuccin, Cyberpunk Neon, and eight more with preview screenshots.]]></summary>
        <content type="html"><![CDATA[<p>The default AMUD Dashboard look is orange glass. I like it. My partner said it looked like a Cheetos-themed spaceship cockpit. Fair.</p>
<p>So I built a <a class="" href="https://boubli.github.io/AMUD-Dashboard/themes">theme gallery</a> with twelve ready-made CSS themes and actual dashboard preview screenshots so you can pick before you paste.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="included-themes">Included themes<a href="https://boubli.github.io/AMUD-Dashboard/blog/twelve-free-themes#included-themes" class="hash-link" aria-label="Direct link to Included themes" title="Direct link to Included themes" translate="no">​</a></h2>
<p>Dracula, Nord, Catppuccin Mocha, Tokyo Night, Gruvbox Dark, Cyberpunk Neon, Solarized Dark, Rose Pine, Everforest, Monokai, One Dark, Sunset Warm.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="apply-one-in-three-clicks">Apply one in three clicks<a href="https://boubli.github.io/AMUD-Dashboard/blog/twelve-free-themes#apply-one-in-three-clicks" class="hash-link" aria-label="Direct link to Apply one in three clicks" title="Direct link to Apply one in three clicks" translate="no">​</a></h2>
<ol>
<li class="">Open <a class="" href="https://boubli.github.io/AMUD-Dashboard/themes">/themes</a></li>
<li class="">Hit <strong>Copy CSS</strong></li>
<li class=""><strong>Settings → Appearance → Custom CSS</strong> → paste → save</li>
</ol>
<p>Instant. No restart. No import-from-URL (that feature got cut on purpose — copy-paste is safer and works offline).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="wallpapers-too">Wallpapers too<a href="https://boubli.github.io/AMUD-Dashboard/blog/twelve-free-themes#wallpapers-too" class="hash-link" aria-label="Direct link to Wallpapers too" title="Direct link to Wallpapers too" translate="no">​</a></h2>
<p>Each theme has a bundled 2K wallpaper. <strong>Copy wallpaper URL</strong> → paste into background image setting. Makes wall tablets look intentional instead of "sysadmin panel accidentally left on."</p>
<p>Broke the layout with bad CSS? Been there. Recovery guide: <a class="" href="https://boubli.github.io/AMUD-Dashboard/docs/troubleshooting">/docs/troubleshooting</a></p>
<p>Want to roll your own? CSS variable reference: <a class="" href="https://boubli.github.io/AMUD-Dashboard/docs/themes">/docs/themes</a></p>]]></content>
        <author>
            <name>Youssef Boubli</name>
            <email>bbb.vloger@gmail.com</email>
            <uri>https://github.com/boubli</uri>
        </author>
        <category label="Themes" term="Themes"/>
        <category label="Homelab" term="Homelab"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Home Assistant Stats on Your Dashboard (Not Just a Link to :8123)]]></title>
        <id>https://boubli.github.io/AMUD-Dashboard/blog/home-assistant-dashboard-card</id>
        <link href="https://boubli.github.io/AMUD-Dashboard/blog/home-assistant-dashboard-card"/>
        <updated>2026-01-24T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Name your app card Home Assistant, drop in a long-lived token, get lights/switches/temp on the card.]]></summary>
        <content type="html"><![CDATA[<p>I had a Home Assistant card that was literally just a URL. Useful, but my wall tablet deserved better.</p>
<p>AMUD Dashboard can show on that card:</p>
<ul>
<li class="">How many <strong>lights</strong> are on</li>
<li class="">How many <strong>switches</strong> are on</li>
<li class="">Average home <strong>temperature</strong></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-one-naming-rule-that-trips-people-up">The one naming rule that trips people up<a href="https://boubli.github.io/AMUD-Dashboard/blog/home-assistant-dashboard-card#the-one-naming-rule-that-trips-people-up" class="hash-link" aria-label="Direct link to The one naming rule that trips people up" title="Direct link to The one naming rule that trips people up" translate="no">​</a></h2>
<p>Your app card has to be named exactly <strong><code>Home Assistant</code></strong>. Not "HA" or "homeassistant" or "the smart house thing." Exactly that string. Yes, I should make that more flexible someday. For now, that's the deal.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="setup">Setup<a href="https://boubli.github.io/AMUD-Dashboard/blog/home-assistant-dashboard-card#setup" class="hash-link" aria-label="Direct link to Setup" title="Direct link to Setup" translate="no">​</a></h2>
<ol>
<li class="">HA → Profile → Long-Lived Access Tokens → create one</li>
<li class="">AMUD → <strong>Settings → Smart Home</strong> → URL + token → save</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-it-polls-without-being-rude-to-ha">How it polls without being rude to HA<a href="https://boubli.github.io/AMUD-Dashboard/blog/home-assistant-dashboard-card#how-it-polls-without-being-rude-to-ha" class="hash-link" aria-label="Direct link to How it polls without being rude to HA" title="Direct link to How it polls without being rude to HA" translate="no">​</a></h2>
<p>Prefers the <strong>Template API</strong> (<code>POST /api/template</code>) so HA computes counts server-side. Falls back to <code>/api/states</code> if templates aren't available. Heavier, but works.</p>
<p>Runs on the same Tokio runtime as everything else — won't block your CPU graphs.</p>
<p>Pair with LXC status: see the HA container is up <em>and</em> you've got four lights on at 2am. Investigate that later.</p>
<p><a class="" href="https://boubli.github.io/AMUD-Dashboard/docs/configuration">/docs/configuration</a></p>]]></content>
        <author>
            <name>Youssef Boubli</name>
            <email>bbb.vloger@gmail.com</email>
            <uri>https://github.com/boubli</uri>
        </author>
        <category label="Integrations" term="Integrations"/>
        <category label="Homelab" term="Homelab"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[See What's Playing on Plex and Jellyfin Without Opening the App]]></title>
        <id>https://boubli.github.io/AMUD-Dashboard/blog/plex-jellyfin-live-badges</id>
        <link href="https://boubli.github.io/AMUD-Dashboard/blog/plex-jellyfin-live-badges"/>
        <updated>2026-01-22T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[AMUD Dashboard polls /Sessions and /status/sessions in the background. Your media cards show live stream titles.]]></summary>
        <content type="html"><![CDATA[<p>"Is anyone watching something right now or can I restart the container?"</p>
<p>That's the question I wanted answered from the dashboard, not from opening Plex on my phone.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="setup-boring-but-fast">Setup (boring but fast)<a href="https://boubli.github.io/AMUD-Dashboard/blog/plex-jellyfin-live-badges#setup-boring-but-fast" class="hash-link" aria-label="Direct link to Setup (boring but fast)" title="Direct link to Setup (boring but fast)" translate="no">​</a></h2>
<p><strong>Settings → Integrations</strong></p>
<p><strong>Jellyfin:</strong> base URL + API key from Dashboard → Advanced → API Keys.</p>
<p><strong>Plex:</strong> base URL + <code>X-Plex-Token</code>. If you've never extracted a Plex token before, welcome to the club — there's a few documented ways and they're all mildly annoying.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-the-badge-does">What the badge does<a href="https://boubli.github.io/AMUD-Dashboard/blog/plex-jellyfin-live-badges#what-the-badge-does" class="hash-link" aria-label="Direct link to What the badge does" title="Direct link to What the badge does" translate="no">​</a></h2>
<p>Starts as <strong>CHECKING...</strong>, then shows the active stream title. Multiple clients? You'll see something like <code>Dune (+2 more)</code>.</p>
<p>Missing creds → <strong>NOT CONFIGURED</strong>. Fixable in thirty seconds once you stop procrastinating.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-this-pairs-well-with-lxc-status">Why this pairs well with LXC status<a href="https://boubli.github.io/AMUD-Dashboard/blog/plex-jellyfin-live-badges#why-this-pairs-well-with-lxc-status" class="hash-link" aria-label="Direct link to Why this pairs well with LXC status" title="Direct link to Why this pairs well with LXC status" translate="no">​</a></h2>
<p>Card shows Jellyfin is <strong>RUNNING</strong> <em>and</em> someone's watching <em>Blade Runner</em>. Now you know restarting would make someone mad. That's operational awareness, not just bookmarks.</p>
<p>API keys get <strong>AES-GCM encrypted</strong> in SQLite at rest. Not sitting in plain text in a yaml file on disk.</p>
<p>Details: <a class="" href="https://boubli.github.io/AMUD-Dashboard/docs/configuration">/docs/configuration</a></p>]]></content>
        <author>
            <name>Youssef Boubli</name>
            <email>bbb.vloger@gmail.com</email>
            <uri>https://github.com/boubli</uri>
        </author>
        <category label="Integrations" term="Integrations"/>
        <category label="Homelab" term="Homelab"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Docker Homelab Monitoring in ~35MB RAM]]></title>
        <id>https://boubli.github.io/AMUD-Dashboard/blog/docker-homelab-35mb</id>
        <link href="https://boubli.github.io/AMUD-Dashboard/blog/docker-homelab-35mb"/>
        <updated>2026-01-20T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Two containers, one shared socket volume, AMUD_DOCKER=1 on the agent. Not Proxmox-native but still lean.]]></summary>
        <content type="html"><![CDATA[<p>Not everyone runs Proxmox. Some of you are Docker-all-the-way-down and that's fine.</p>
<p>AMUD Dashboard in Docker is two containers:</p>
<ul>
<li class=""><strong><code>amud_app</code></strong> — web server + SQLite</li>
<li class=""><strong><code>amud_agent</code></strong> — telemetry, mounts Docker socket read-only</li>
</ul>
<p>They talk over a shared volume at <code>/var/run/amud/amud.sock</code>. Same IPC model as bare metal, just containerized.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="minimal-compose">Minimal compose<a href="https://boubli.github.io/AMUD-Dashboard/blog/docker-homelab-35mb#minimal-compose" class="hash-link" aria-label="Direct link to Minimal compose" title="Direct link to Minimal compose" translate="no">​</a></h2>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token key atrule">services</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">image</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> tradmss/amud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">dashboard</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">latest</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"8000:8000"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">environment</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> AMUD_AGENT_SECRET=use</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">a</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">long</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">random</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">here</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> DB_PATH=/app/data/amud.db</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> AMUD_SOCKET_PATH=/var/run/amud/amud.sock</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">volumes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> ./data</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">/app/data</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> amud_run</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">/var/run/amud</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">image</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> tradmss/amud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">dashboard</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">latest</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">entrypoint</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"/app/amud-agent"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">environment</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> AMUD_AGENT_SECRET=use</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">a</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">long</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">random</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">here</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> AMUD_DOCKER=1</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> AMUD_SOCKET_PATH=/var/run/amud/amud.sock</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">volumes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> amud_run</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">/var/run/amud</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> /var/run/docker.sock</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">/var/run/docker.sock</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">ro</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">volumes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  amud_run</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><br></div></code></pre></div></div>
<p><strong>The secret must match in both containers.</strong> I cannot count how many issue reports were just mismatched <code>AMUD_AGENT_SECRET</code>.</p>
<p>Link app cards to <strong>container names</strong> for running/stopped badges.</p>
<p>Full guide: <a class="" href="https://boubli.github.io/AMUD-Dashboard/docs/installation/docker">/docs/installation/docker</a></p>
<p>RAM lands around 35–100MB depending on host. Still lighter than most PHP/Node dashboards I've run.</p>]]></content>
        <author>
            <name>Youssef Boubli</name>
            <email>bbb.vloger@gmail.com</email>
            <uri>https://github.com/boubli</uri>
        </author>
        <category label="Docker" term="Docker"/>
        <category label="Homelab" term="Homelab"/>
        <category label="Self-Hosted" term="Self-Hosted"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Green and Red LXC Badges (Plus Start/Stop From the Dashboard)]]></title>
        <id>https://boubli.github.io/AMUD-Dashboard/blog/lxc-status-badges</id>
        <link href="https://boubli.github.io/AMUD-Dashboard/blog/lxc-status-badges"/>
        <updated>2026-01-18T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Link an app card to a CTID, get live RUNNING/STOPPED status, and optionally power-cycle containers without opening Proxmox.]]></summary>
        <content type="html"><![CDATA[<p>A link list tells you where Jellyfin <em>should</em> be. It doesn't tell you Jellyfin is stopped because you updated the LXC last night and forgot to bring it back up.</p>
<p>AMUD Dashboard app cards can bind to a Proxmox <strong>CTID</strong>. Badge flips between <strong>RUNNING</strong>, <strong>STOPPED</strong>, and the eternal <strong>CHECKING...</strong> when something's misconfigured.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="setup-checklist">Setup checklist<a href="https://boubli.github.io/AMUD-Dashboard/blog/lxc-status-badges#setup-checklist" class="hash-link" aria-label="Direct link to Setup checklist" title="Direct link to Setup checklist" translate="no">​</a></h2>
<ol>
<li class=""><code>amud-agent</code> running on the Proxmox host</li>
<li class="">API token in <strong>Settings → Proxmox VE</strong></li>
<li class="">App card has the correct LXC/VM ID field filled in</li>
</ol>
<p>That's it. If you're stuck on CHECKING..., 90% of the time it's the token. I wrote a whole troubleshooting post for that misery.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="power-controls">Power controls<a href="https://boubli.github.io/AMUD-Dashboard/blog/lxc-status-badges#power-controls" class="hash-link" aria-label="Direct link to Power controls" title="Direct link to Power controls" translate="no">​</a></h2>
<p>If your API role includes <code>VM.PowerMgmt</code>, admins get start/stop/restart on linked containers. Handy when you're on your phone and don't want the Proxmox mobile experience.</p>
<p>Guest users see status only. No accidental <code>pct stop</code> from the kitchen tablet.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="dont-use-rootpam">Don't use root@pam<a href="https://boubli.github.io/AMUD-Dashboard/blog/lxc-status-badges#dont-use-rootpam" class="hash-link" aria-label="Direct link to Don't use root@pam" title="Direct link to Don't use root@pam" translate="no">​</a></h2>
<p>Create a restricted <code>amud@pve</code> user with <code>VM.Audit</code>, <code>Sys.Audit</code>, and optionally <code>VM.PowerMgmt</code>. Paste that token into AMUD. Your dashboard doesn't need god-mode PVE access.</p>
<p>Config details: <a class="" href="https://boubli.github.io/AMUD-Dashboard/docs/configuration">/docs/configuration</a></p>]]></content>
        <author>
            <name>Youssef Boubli</name>
            <email>bbb.vloger@gmail.com</email>
            <uri>https://github.com/boubli</uri>
        </author>
        <category label="Proxmox" term="Proxmox"/>
        <category label="Homelab" term="Homelab"/>
    </entry>
</feed>