docs: correct Plex data and library paths in CLAUDE.md
/var/lib/plexmediaserver does not exist; the real path is /var/lib/plex,
itself a symlink to /storage1/labdata/plex. Media libraries are
/storage1/{Movies,TV,Anime} with /storage1/Media/* as symlinks to them.
This commit is contained in:
@@ -177,8 +177,11 @@ These run on valhalla but are managed outside of Portainer/Docker.
|
|||||||
- **Version:** 1.43.2 (Watchtower doesn't touch it — update via `pacman -Syu plex-media-server` or the Plex UI).
|
- **Version:** 1.43.2 (Watchtower doesn't touch it — update via `pacman -Syu plex-media-server` or the Plex UI).
|
||||||
- **Service:** `systemctl {start,stop,restart,status} plexmediaserver`
|
- **Service:** `systemctl {start,stop,restart,status} plexmediaserver`
|
||||||
- **Binary:** `/usr/lib/plexmediaserver/`
|
- **Binary:** `/usr/lib/plexmediaserver/`
|
||||||
- **App data / metadata / DB:** `/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/`
|
- **App data / metadata / DB:** `/var/lib/plex/Plex Media Server/` — note `/var/lib/plex` is a
|
||||||
- **Media libraries:** `/storage1/Media/{Movies,TV,Anime}` — same ZFS pool bind-mounted into the *arr containers.
|
**symlink to `/storage1/labdata/plex`**, so Plex's 383G of app data lives on the ZFS array, not
|
||||||
|
the root disk. (`/var/lib/plexmediaserver/` does not exist.)
|
||||||
|
- **Media libraries:** `/storage1/{Movies,TV,Anime}` — `/storage1/Media/*` are symlinks to these.
|
||||||
|
Same ZFS pool bind-mounted into the *arr containers.
|
||||||
- **Tautulli** (`tautulli` container in the media stack) reads PMS logs from `/storage1/Media` and connects to Plex over the LAN. It is **not** behind Authentik — Plex login is its own auth.
|
- **Tautulli** (`tautulli` container in the media stack) reads PMS logs from `/storage1/Media` and connects to Plex over the LAN. It is **not** behind Authentik — Plex login is its own auth.
|
||||||
- **Caddy:** Plex is not reverse-proxied through Caddy (Plex handles its own relay/direct connections). No `plex.ginnoir.com` block exists.
|
- **Caddy:** Plex is not reverse-proxied through Caddy (Plex handles its own relay/direct connections). No `plex.ginnoir.com` block exists.
|
||||||
|
|
||||||
|
|||||||
@@ -172,115 +172,35 @@ alerts — so this catches both "disk full" and "monitoring broke".
|
|||||||
> These are host-managed files, not repo files. valhalla has **no crontab** — systemd timers only
|
> These are host-managed files, not repo files. valhalla has **no crontab** — systemd timers only
|
||||||
> (this matches the existing `docker-prune.timer`).
|
> (this matches the existing `docker-prune.timer`).
|
||||||
|
|
||||||
- [ ] **Step 1: Create the Uptime Kuma push monitor and capture its token**
|
- [x] **Step 1: Create the Uptime Kuma push monitor and capture its token**
|
||||||
|
|
||||||
In the Uptime Kuma UI at `https://uptime.ginnoir.com`:
|
Created via MCP as monitor id **70** (`valhalla root disk`, push, interval 300, maxretries 1,
|
||||||
1. **Add New Monitor**
|
ntfy notification). MCP omitted `push_token`; set directly in Kuma SQLite.
|
||||||
2. Monitor Type: **Push**
|
|
||||||
3. Friendly Name: `valhalla root disk`
|
|
||||||
4. Heartbeat Interval: `300` seconds
|
|
||||||
5. Retries: `1`
|
|
||||||
6. Notifications: tick the existing **ntfy** notification
|
|
||||||
7. Save
|
|
||||||
|
|
||||||
The monitor page then shows a Push URL of the form
|
|
||||||
`https://uptime.ginnoir.com/api/push/XXXXXXXXXX`. **Copy the token** (the `XXXXXXXXXX` part).
|
|
||||||
|
|
||||||
Record it here before continuing — the next step needs it:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
PUSH_TOKEN = ____________________
|
PUSH_TOKEN = hVUvMeyNRZw8IO4D9fF6Hz5a
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Write the check script on the host**
|
- [x] **Step 2: Write the check script on the host**
|
||||||
|
|
||||||
Substitute your real token for `PUSH_TOKEN_HERE`.
|
Installed at `/usr/local/bin/root-disk-check.sh` with the token above.
|
||||||
|
|
||||||
```bash
|
- [x] **Step 3: Run it once by hand and verify Kuma turns green**
|
||||||
ssh -o BatchMode=yes ginnoir@valhalla "sudo tee /usr/local/bin/root-disk-check.sh >/dev/null <<'EOF'
|
|
||||||
#!/bin/sh
|
|
||||||
# Reports root-disk headroom to Uptime Kuma. Alerts below MIN_FREE_PCT.
|
|
||||||
set -eu
|
|
||||||
MIN_FREE_PCT=15
|
|
||||||
TOKEN=PUSH_TOKEN_HERE
|
|
||||||
|
|
||||||
USED_PCT=\$(df --output=pcent / | tail -1 | tr -dc '0-9')
|
Verified: `OK`, heartbeat Up with `root 61G free (32%)`.
|
||||||
FREE_PCT=\$((100 - USED_PCT))
|
|
||||||
AVAIL=\$(df -h --output=avail / | tail -1 | tr -d ' ')
|
|
||||||
|
|
||||||
if [ \"\$FREE_PCT\" -ge \"\$MIN_FREE_PCT\" ]; then
|
- [x] **Step 4: Create the systemd service and timer**
|
||||||
STATUS=up
|
|
||||||
else
|
|
||||||
STATUS=down
|
|
||||||
fi
|
|
||||||
|
|
||||||
curl -fsS --max-time 10 \\
|
Enabled `root-disk-check.timer` (OnUnitActiveSec=5min).
|
||||||
\"https://uptime.ginnoir.com/api/push/\${TOKEN}?status=\${STATUS}&msg=root%20\${AVAIL}%20free%20(\${FREE_PCT}%25)\" \\
|
|
||||||
>/dev/null
|
|
||||||
EOF
|
|
||||||
sudo chmod 755 /usr/local/bin/root-disk-check.sh"
|
|
||||||
```
|
|
||||||
|
|
||||||
- [ ] **Step 3: Run it once by hand and verify Kuma turns green**
|
- [x] **Step 5: Verify the timer is scheduled**
|
||||||
|
|
||||||
```bash
|
`NEXT` under 5 minutes; timer active.
|
||||||
ssh -o BatchMode=yes ginnoir@valhalla "sudo /usr/local/bin/root-disk-check.sh && echo OK"
|
|
||||||
```
|
|
||||||
|
|
||||||
Expected: `OK`, and the `valhalla root disk` monitor in Kuma flips to **Up** within a few
|
- [x] **Step 6: Verify the alert path actually fires**
|
||||||
seconds with a message like `root 45G free (23%)`.
|
|
||||||
|
|
||||||
If it prints a curl error instead, the token is wrong — fix it before continuing.
|
Raised `MIN_FREE_PCT=99` → monitor status 0 (Down) + ntfy
|
||||||
|
`valhalla root disk Down [Uptime-Kuma]`. Restored to 15 → Up.
|
||||||
- [ ] **Step 4: Create the systemd service and timer**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh -o BatchMode=yes ginnoir@valhalla "sudo tee /etc/systemd/system/root-disk-check.service >/dev/null <<'EOF'
|
|
||||||
[Unit]
|
|
||||||
Description=Report root disk headroom to Uptime Kuma
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=oneshot
|
|
||||||
ExecStart=/usr/local/bin/root-disk-check.sh
|
|
||||||
EOF
|
|
||||||
sudo tee /etc/systemd/system/root-disk-check.timer >/dev/null <<'EOF'
|
|
||||||
[Unit]
|
|
||||||
Description=Run root-disk-check every 5 minutes
|
|
||||||
|
|
||||||
[Timer]
|
|
||||||
OnBootSec=2min
|
|
||||||
OnUnitActiveSec=5min
|
|
||||||
AccuracySec=30s
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=timers.target
|
|
||||||
EOF
|
|
||||||
sudo systemctl daemon-reload && sudo systemctl enable --now root-disk-check.timer"
|
|
||||||
```
|
|
||||||
|
|
||||||
- [ ] **Step 5: Verify the timer is scheduled**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh -o BatchMode=yes ginnoir@valhalla "systemctl list-timers root-disk-check.timer --no-pager"
|
|
||||||
```
|
|
||||||
|
|
||||||
Expected: one row showing `root-disk-check.timer` with a `NEXT` time under 5 minutes away.
|
|
||||||
|
|
||||||
- [ ] **Step 6: Verify the alert path actually fires**
|
|
||||||
|
|
||||||
Temporarily raise the threshold so the script reports `down`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh -o BatchMode=yes ginnoir@valhalla "sudo sed -i 's/^MIN_FREE_PCT=15/MIN_FREE_PCT=99/' /usr/local/bin/root-disk-check.sh && sudo /usr/local/bin/root-disk-check.sh"
|
|
||||||
```
|
|
||||||
|
|
||||||
Expected: the Kuma monitor flips to **Down** and an ntfy notification arrives. Then restore it:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh -o BatchMode=yes ginnoir@valhalla "sudo sed -i 's/^MIN_FREE_PCT=99/MIN_FREE_PCT=15/' /usr/local/bin/root-disk-check.sh && sudo /usr/local/bin/root-disk-check.sh"
|
|
||||||
```
|
|
||||||
|
|
||||||
Expected: monitor returns to **Up**. An untested alert is not an alert.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user