Add implementation plan for NAS dashboard and services
This commit is contained in:
@@ -0,0 +1,205 @@
|
||||
# NAS Dashboard — Implementation Plan
|
||||
|
||||
## Context
|
||||
|
||||
A modern, self-hosted web dashboard on your Synology DS224+ NAS (Tailscale-only) that serves as a single entry point to manage repos, Docker containers, files, terminal sessions, and media — plus an AI assistant. Replaces the need to SSH into the NAS for routine tasks. Public access via a dedicated Caddy reverse proxy VPS.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
Public Internet → nas.jimmygan.com / music.jimmygan.com
|
||||
│
|
||||
└── New AMD VPS (Caddy, HTTPS, Tailscale)
|
||||
│
|
||||
└── Tailscale → NAS (100.78.131.124)
|
||||
├── :4000 NAS Dashboard (FastAPI + Svelte)
|
||||
│ ├── /api/docker/* → Docker socket proxy (limited API)
|
||||
│ ├── /api/gitea/* → Gitea REST API
|
||||
│ ├── /api/files/* → /volume1 filesystem
|
||||
│ ├── /ws/terminal → WebSocket pty (Tailscale-only)
|
||||
│ └── /* → Svelte SPA
|
||||
├── :4533 Navidrome (music)
|
||||
├── :2283 Immich (photos, Tailscale-only)
|
||||
├── :3300 Gitea (Tailscale-only)
|
||||
├── :8096 Emby (video, Tailscale-only)
|
||||
└── :3100 OpenClaw (AI assistant, Tailscale-only)
|
||||
|
||||
Existing VPS (158.101.140.85): xray VLESS+REALITY on :443 — untouched
|
||||
```
|
||||
|
||||
## Tech Stack (Dashboard)
|
||||
|
||||
- Backend: Python FastAPI + uvicorn
|
||||
- Frontend: Svelte + Tailwind CSS (light theme default, with dark/light toggle)
|
||||
- Terminal: xterm.js + WebSocket pty bridge
|
||||
- Docker mgmt: via docker-socket-proxy (Tecnativa) for safety
|
||||
- Gitea: `httpx` async client
|
||||
- Build: Multi-stage Dockerfile (node → python-slim), built on Mac, pushed to Gitea container registry
|
||||
- LLM: Claude API (key from ~/.zshrc)
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
nas-tools/
|
||||
dashboard/
|
||||
docker-compose.yml # Dashboard + docker-socket-proxy
|
||||
Dockerfile
|
||||
.env.example
|
||||
backend/
|
||||
main.py
|
||||
config.py
|
||||
requirements.txt
|
||||
routers/
|
||||
docker.py
|
||||
gitea.py
|
||||
files.py
|
||||
terminal.py
|
||||
frontend/
|
||||
package.json
|
||||
vite.config.js
|
||||
svelte.config.js
|
||||
src/
|
||||
App.svelte
|
||||
lib/
|
||||
api.js
|
||||
terminal.js
|
||||
routes/
|
||||
Dashboard.svelte
|
||||
Docker.svelte
|
||||
Gitea.svelte
|
||||
Files.svelte
|
||||
Terminal.svelte
|
||||
components/
|
||||
Sidebar.svelte
|
||||
ContainerCard.svelte
|
||||
LogViewer.svelte
|
||||
navidrome/
|
||||
docker-compose.yml
|
||||
immich/
|
||||
docker-compose.yml
|
||||
openclaw/
|
||||
docker-compose.yml
|
||||
|
||||
cloud-monitor/
|
||||
oci-amd-monitor.py # New: grab AMD free-tier instance
|
||||
```
|
||||
|
||||
## Implementation Phases
|
||||
|
||||
### 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`
|
||||
- AMD-compatible image (Ubuntu x86_64)
|
||||
- Same compartment, availability domain, subnet as existing VPS
|
||||
2. Run script to grab AMD instance
|
||||
3. Harden new VPS: SSH key-only, firewall (only 22/80/443), fail2ban, unattended-upgrades
|
||||
4. Install Tailscale + Caddy on new VPS
|
||||
5. Configure Caddy with HTTP basic auth immediately (placeholder until Phase 7 upgrades to 2FA)
|
||||
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
|
||||
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)
|
||||
11. Frontend: Svelte app with sidebar + Docker container view
|
||||
12. Terminal access control: backend middleware blocks `/ws/terminal` for non-Tailscale IPs (100.x.x.x)
|
||||
13. File browser: read-write (mount `/volume1` as rw), with path traversal protection
|
||||
14. Add Docker log rotation to all compose files (`max-size: 10m`, `max-file: 3`)
|
||||
15. Build image on Mac, push to Gitea container registry
|
||||
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
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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 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
|
||||
38. Rollback: `docker compose pull <previous-tag> && docker compose up -d`
|
||||
|
||||
### Phase 9 — Backup & Recovery
|
||||
33. Automated daily backup script for:
|
||||
- Gitea DB (pg_dump) + gitea-data
|
||||
- Immich DB + upload data
|
||||
- Navidrome config/DB
|
||||
- OpenClaw data
|
||||
- Dashboard .env and config
|
||||
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
|
||||
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)
|
||||
|
||||
## 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)
|
||||
|
||||
## VPS Strategy
|
||||
|
||||
- Existing VPS (158.101.140.85): xray VLESS+REALITY on :443 — untouched
|
||||
- New AMD VPS: Caddy on :80/:443, Tailscale, reverse proxy to NAS
|
||||
- Both in Tokyo region, Oracle free tier
|
||||
|
||||
## DNS (Cloudflare)
|
||||
|
||||
- `nas.jimmygan.com` → new AMD VPS IP (DNS only, Caddy handles TLS)
|
||||
- `music.jimmygan.com` → new AMD VPS IP (DNS only)
|
||||
- `moldcost.jimmygan.com` → remove (dead server1)
|
||||
- Existing `jimmygan.com` A record → keep as-is
|
||||
|
||||
## Build Strategy
|
||||
|
||||
- Docker images built on Mac (faster than NAS Celeron)
|
||||
- Push to Gitea container registry (`100.78.131.124:3300`)
|
||||
- NAS pulls and runs images
|
||||
- CI/CD automates this via Gitea Actions
|
||||
|
||||
## Verification
|
||||
|
||||
1. Dashboard at `http://100.78.131.124:4000` — Docker page shows containers, start/stop works
|
||||
2. Gitea page lists repos and commits
|
||||
3. Files page browses /volume1
|
||||
4. Terminal opens a working shell session
|
||||
5. Navidrome at `:4533` — plays music from `/volume1/music`
|
||||
6. Immich at `:2283` — browses photos
|
||||
7. OpenClaw at `:3100` — responds via Claude API
|
||||
8. `https://nas.jimmygan.com` — dashboard accessible from internet with login + 2FA
|
||||
9. `https://music.jimmygan.com` — Navidrome accessible from internet
|
||||
10. Backups run daily, restore tested
|
||||
11. Dashboard shows system stats, alerts on disk/container issues
|
||||
Reference in New Issue
Block a user