Add Audiobookshelf, Stirling PDF, Vaultwarden to sidebar; update PLAN.md
Deploy Dashboard / deploy (push) Successful in 1m32s
Deploy Dashboard / deploy (push) Successful in 1m32s
This commit is contained in:
@@ -21,8 +21,12 @@ Public Internet → nas.jimmygan.com / music.jimmygan.com
|
||||
├── :4533 Navidrome (music)
|
||||
├── :2283 Immich (photos, Tailscale-only)
|
||||
├── :3300 Gitea (Tailscale-only)
|
||||
├── :8096 Emby (video, Tailscale-only)
|
||||
└── :3100 OpenClaw (AI assistant, Tailscale-only)
|
||||
├── :8096 Jellyfin (video, Tailscale-only)
|
||||
├── :3100 OpenClaw (AI assistant, Tailscale-only)
|
||||
├── :8080 Speedtest (Tailscale-only)
|
||||
├── :13378 Audiobookshelf (audiobooks, Tailscale-only)
|
||||
├── :8030 Stirling PDF (PDF tools, Tailscale-only)
|
||||
└── :8222 Vaultwarden (passwords, Tailscale-only)
|
||||
|
||||
Existing VPS (158.101.140.85): xray VLESS+REALITY on :443 — untouched
|
||||
```
|
||||
@@ -86,7 +90,7 @@ cloud-monitor/
|
||||
|
||||
## Implementation Phases
|
||||
|
||||
### Phase 1 — Provision new AMD VPS
|
||||
### Phase 1 — Provision new AMD VPS ✅
|
||||
1. Add `oci-amd-monitor.py` to cloud-monitor repo:
|
||||
- Shape: `VM.Standard.E2.1.Micro` (1 OCPU, 1GB RAM, AMD free tier)
|
||||
- Display name: `free-amd-caddy`
|
||||
@@ -99,7 +103,7 @@ cloud-monitor/
|
||||
6. Update Cloudflare DNS: `nas.jimmygan.com` and `music.jimmygan.com` → new VPS IP (set to "DNS only", let Caddy handle TLS)
|
||||
7. Clean up stale DNS: `moldcost` → dead server1 (152.53.226.207) — remove or update
|
||||
|
||||
### Phase 2 — Dashboard MVP: Docker management
|
||||
### Phase 2 — Dashboard MVP: Docker management ✅
|
||||
8. Create directory structure, Dockerfile, docker-compose.yml
|
||||
9. Add docker-socket-proxy (Tecnativa) to limit Docker API access
|
||||
10. Backend: main.py + config.py + docker router (list, start/stop, logs)
|
||||
@@ -111,37 +115,37 @@ cloud-monitor/
|
||||
16. Deploy on NAS, port 4000
|
||||
17. Configure Caddy on new VPS: `nas.jimmygan.com` → NAS :4000 via Tailscale (behind basic auth from Phase 1)
|
||||
|
||||
### Phase 3 — Gitea + Files + Terminal
|
||||
### Phase 3 — Gitea + Files + Terminal ✅
|
||||
18. Add gitea router (repos, commits, trigger workflows) — needs Gitea API token
|
||||
19. Add files router (browse /volume1, download, upload, delete) with path traversal protection
|
||||
20. Add terminal router (WebSocket pty bridge + xterm.js) — blocked for non-Tailscale IPs
|
||||
21. Dashboard overview page with links to all services
|
||||
|
||||
### Phase 4 — Navidrome (Music)
|
||||
### Phase 4 — Navidrome (Music) ✅
|
||||
22. Deploy Navidrome Docker stack on port 4533 (with log rotation)
|
||||
23. Point at `/volume1/music`
|
||||
24. Link from dashboard sidebar
|
||||
25. Configure Caddy: `music.jimmygan.com` → NAS :4533 via Tailscale
|
||||
|
||||
### Phase 5 — Immich (Photos)
|
||||
### Phase 5 — Immich (Photos) ✅
|
||||
26. Deploy Immich Docker stack on port 2283 (disable ML/face recognition, with log rotation)
|
||||
27. Point at `/volume1/photo` + `/volume1/homes/zjgump/Photos`
|
||||
28. Link from dashboard sidebar (Tailscale-only)
|
||||
|
||||
### Phase 6 — OpenClaw (AI Assistant)
|
||||
### Phase 6 — OpenClaw (AI Assistant) ✅
|
||||
29. Deploy OpenClaw Docker stack on port 3100 (with log rotation)
|
||||
30. Configure Claude API as LLM provider
|
||||
31. Configure messaging channels (Telegram, etc.)
|
||||
32. Link from dashboard sidebar (Tailscale-only)
|
||||
|
||||
### Phase 7 — Authentication & Security
|
||||
33. Upgrade dashboard auth from Caddy basic auth → session-based login + TOTP 2FA
|
||||
34. Rate limiting for brute force protection on Caddy
|
||||
### Phase 7 — Authentication & Security ✅
|
||||
33. ~~Upgrade dashboard auth from Caddy basic auth → session-based login + TOTP 2FA~~ — Done (password + TOTP 2FA + passkey/WebAuthn login)
|
||||
34. ~~Rate limiting for brute force protection on Caddy~~ — Done (fail2ban + failed login Telegram alerts)
|
||||
|
||||
### Phase 8 — CI/CD for Dashboard
|
||||
35. Add Gitea workflow to nas-tools: on push to main, build Docker image, push to Gitea registry
|
||||
36. Tag images with git SHA + `latest`; keep previous image for rollback
|
||||
37. Auto-deploy on NAS: pull new image, restart container
|
||||
### Phase 8 — CI/CD for Dashboard ✅
|
||||
35. ~~Add Gitea workflow to nas-tools: on push to main, auto-deploy~~ — Done (Gitea Actions runs `docker compose up -d` on push)
|
||||
36. ~~Tag images with git SHA + `latest`~~ — Done
|
||||
37. ~~Auto-deploy on NAS~~ — Done
|
||||
38. Rollback: `docker compose pull <previous-tag> && docker compose up -d`
|
||||
|
||||
### Phase 9 — Backup & Recovery
|
||||
@@ -154,21 +158,28 @@ cloud-monitor/
|
||||
34. Backups stored to `/volume1/backups`
|
||||
35. Periodic restore test to verify backups work
|
||||
|
||||
### Phase 10 — Monitoring & Alerts
|
||||
36. Add system stats to dashboard overview: CPU, RAM, disk usage
|
||||
37. Container health checks in docker-compose files
|
||||
### Phase 10 — Monitoring & Alerts (partial)
|
||||
36. ~~Add system stats to dashboard overview: CPU, RAM, disk usage~~ — Done
|
||||
37. ~~Container health checks in docker-compose files~~ — Done
|
||||
38. Notification on failure (Telegram bot or email)
|
||||
|
||||
### Phase 11 — Polish
|
||||
39. Light/dark theme toggle, loading states, error handling
|
||||
40. Add Emby link to dashboard sidebar (port 8096)
|
||||
### Phase 11 — Polish (partial)
|
||||
39. ~~Light/dark theme toggle~~ — Done
|
||||
40. ~~Add Jellyfin link to dashboard sidebar (port 8096)~~ — Done (replaced Emby)
|
||||
|
||||
### Phase 12 — Additional Services
|
||||
41. Deploy Audiobookshelf on port 13378 — Done, add to dashboard sidebar
|
||||
42. Deploy Stirling PDF on port 8030 — Done, add to dashboard sidebar
|
||||
43. Deploy Vaultwarden on port 8222 — Done, add to dashboard sidebar
|
||||
44. Deploy Watchtower for auto-updates — Done (internal, no sidebar link needed)
|
||||
45. Deploy Speedtest on port 8080 — Done, already in dashboard sidebar
|
||||
|
||||
## Media Paths
|
||||
|
||||
- Music: `/volume1/music` (70GB, FLAC/WAV/DSD/ALAC)
|
||||
- Photos: `/volume1/photo` (186GB) + `/volume1/homes/zjgump/Photos`
|
||||
- Video: `/volume1/video` (759GB)
|
||||
- Emby: installed but unconfigured (port 8096, needs setup wizard)
|
||||
- Emby: replaced by Jellyfin (port 8096)
|
||||
|
||||
## VPS Strategy
|
||||
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
{ label: "Jellyfin", port: 8096, icon: "play" },
|
||||
{ label: "Gitea Web", port: 3300, icon: "git" },
|
||||
{ label: "Speedtest", port: 8080, icon: "speedtest" },
|
||||
{ label: "Audiobookshelf", port: 13378, icon: "headphones" },
|
||||
{ label: "Stirling PDF", port: 8030, icon: "pdf" },
|
||||
{ label: "Vaultwarden", port: 8222, icon: "lock" },
|
||||
];
|
||||
|
||||
function extHref(svc) {
|
||||
@@ -111,6 +114,12 @@
|
||||
<svg class="w-[16px] h-[16px]" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.8"><path stroke-linecap="round" stroke-linejoin="round" d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4" /></svg>
|
||||
{:else if svc.icon === "speedtest"}
|
||||
<svg class="w-[16px] h-[16px]" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.8"><path stroke-linecap="round" stroke-linejoin="round" d="M13 10V3L4 14h7v7l9-11h-7z" /></svg>
|
||||
{:else if svc.icon === "headphones"}
|
||||
<svg class="w-[16px] h-[16px]" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.8"><path stroke-linecap="round" stroke-linejoin="round" d="M3 18v-6a9 9 0 0118 0v6M3 18a3 3 0 003 3h0a3 3 0 003-3v-2a3 3 0 00-3-3h0a3 3 0 00-3 3v2zm18 0a3 3 0 01-3 3h0a3 3 0 01-3-3v-2a3 3 0 013-3h0a3 3 0 013 3v2z" /></svg>
|
||||
{:else if svc.icon === "pdf"}
|
||||
<svg class="w-[16px] h-[16px]" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.8"><path stroke-linecap="round" stroke-linejoin="round" d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" /></svg>
|
||||
{:else if svc.icon === "lock"}
|
||||
<svg class="w-[16px] h-[16px]" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.8"><path stroke-linecap="round" stroke-linejoin="round" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" /></svg>
|
||||
{/if}
|
||||
</span>
|
||||
{svc.label}
|
||||
|
||||
Reference in New Issue
Block a user