updated readme
This commit is contained in:
+82
-6
@@ -4,7 +4,7 @@
|
||||
|
||||
A single, lightweight Go container that replaces Portainer + scattered systemd scripts with a unified, Hungarian-language web dashboard for managing Docker Compose stacks, backups, storage, monitoring, and notifications on customer hardware.
|
||||
|
||||
**Current version: v0.22.0**
|
||||
**Current version: v0.22.3**
|
||||
|
||||
---
|
||||
|
||||
@@ -22,6 +22,7 @@ A single, lightweight Go container that replaces Portainer + scattered systemd s
|
||||
- [Central Hub](#8-central-hub-reporting)
|
||||
- [Setup Wizard](#9-first-run-setup-wizard)
|
||||
- [Disaster Recovery](#10-disaster-recovery)
|
||||
- [Asset Sync](#11-asset-sync)
|
||||
- [Repository Layout](#repository-layout)
|
||||
- [Configuration](#configuration)
|
||||
- [REST API](#rest-api)
|
||||
@@ -58,12 +59,17 @@ A single, lightweight Go container that replaces Portainer + scattered systemd s
|
||||
│ │ │ Notify │ │ REST API + Hub Reporter ││ │
|
||||
│ │ │ (events) │ │ (JSON push + events) ││ │
|
||||
│ │ └──────────┘ └─────────────────────────┘│ │
|
||||
│ │ ┌──────────┐ │ │
|
||||
│ │ │ Assets │ │ │
|
||||
│ │ │ (Hub │ │ │
|
||||
│ │ │ sync) │ │ │
|
||||
│ │ └──────────┘ │ │
|
||||
│ └────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│ events + reports │ git pull
|
||||
▼ ▼
|
||||
hub.felhom.eu gitea.dooplex.hu
|
||||
(central dashboard) (stack definitions)
|
||||
│ events + reports │ git pull │ asset sync
|
||||
▼ ▼ ▼
|
||||
hub.felhom.eu gitea.dooplex.hu hub.felhom.eu
|
||||
(central dashboard) (stack definitions) (logos, screenshots)
|
||||
```
|
||||
|
||||
### Key Architecture Decisions
|
||||
@@ -907,6 +913,60 @@ When a system drive fails and is replaced, the recovery flow uses the setup wiza
|
||||
|
||||
---
|
||||
|
||||
### 11. Asset Sync
|
||||
|
||||
App assets (logos, screenshots) are managed centrally by the Hub and downloaded to each controller via a daily sync process. This decouples asset updates from controller image rebuilds — new app icons only require a Hub redeploy.
|
||||
|
||||
#### How It Works (`internal/assets/syncer.go`)
|
||||
|
||||
```
|
||||
1. Fetch manifest from Hub: GET /api/v1/assets/manifest (Bearer auth)
|
||||
2. Compare SHA-256 checksums with local cache (<dataDir>/assets/)
|
||||
3. Download changed/new files: GET /api/v1/assets/file/{filename}
|
||||
4. Remove local files not in Hub manifest (stale cleanup)
|
||||
5. Save local manifest copy for next comparison
|
||||
```
|
||||
|
||||
#### Asset Resolution (two-tier)
|
||||
|
||||
| Priority | Path | Source |
|
||||
|----------|------|--------|
|
||||
| 1 | `<dataDir>/assets/` | Downloaded from Hub (synced cache) |
|
||||
| 2 | `/usr/share/felhom/assets/` | Baked into Docker image (fallback) |
|
||||
|
||||
The `Resolve(filename)` method checks the synced cache first, then falls back to the baked-in directory. This ensures assets are always available even before the first sync.
|
||||
|
||||
#### Configuration
|
||||
|
||||
```yaml
|
||||
assets:
|
||||
sync_enabled: true # Opt-in: download assets from Hub API
|
||||
sync_schedule: "05:00" # Daily sync time (HH:MM, Budapest timezone)
|
||||
```
|
||||
|
||||
Asset sync requires `hub.enabled: true` with valid `hub.url` and `hub.api_key`. The initial sync runs 10 seconds after startup (to let subsystems initialize), then daily at the configured time.
|
||||
|
||||
#### Sync Status
|
||||
|
||||
The syncer tracks status (last sync time, result, file count, total bytes) accessible via `GET /api/assets/status`. On-demand sync can be triggered via `POST /api/assets/sync`.
|
||||
|
||||
#### File Types
|
||||
|
||||
The Hub serves three asset types per app:
|
||||
- `{slug}-logo.svg` — primary SVG logo
|
||||
- `{slug}-logo.png` — PNG fallback
|
||||
- `{slug}-screenshot-{N}.webp` — app screenshots
|
||||
|
||||
#### Key Design Decisions
|
||||
|
||||
- **Opt-in via `sync_enabled`** — backward compatible, baked-in assets still work without Hub
|
||||
- **SHA-256 change detection** — only downloads files that actually changed (bandwidth efficient)
|
||||
- **Atomic file writes** — downloads to `.tmp` then `os.Rename` for crash safety
|
||||
- **Stale file cleanup** — removes local files not in the Hub manifest (e.g., deleted apps)
|
||||
- **Non-blocking initial sync** — runs in a goroutine with 10s delay, doesn't block startup
|
||||
|
||||
---
|
||||
|
||||
## Repository Layout
|
||||
|
||||
```
|
||||
@@ -940,6 +1000,7 @@ controller/
|
||||
│ │ ├── restore_scan.go # DR: scan drives for backup data, build restore plan
|
||||
│ │ ├── restore_app_linux.go # DR: per-app restore (rsync config/data + docker compose up)
|
||||
│ │ └── restore_drives_linux.go # DR: auto-mount drives by UUID from Hub infra backup
|
||||
│ ├── assets/syncer.go # Hub asset sync (download, SHA-256 compare, resolve)
|
||||
│ ├── api/router.go # REST API endpoints (~30 routes)
|
||||
│ ├── scheduler/scheduler.go # Central job scheduler (Every, Daily)
|
||||
│ ├── system/
|
||||
@@ -1041,6 +1102,10 @@ hub:
|
||||
url: "https://hub.felhom.eu"
|
||||
api_key: "bearer-token-here"
|
||||
|
||||
assets:
|
||||
sync_enabled: true # Download app assets (logos, screenshots) from Hub API
|
||||
sync_schedule: "05:00" # Daily sync time (HH:MM, Budapest timezone)
|
||||
|
||||
system:
|
||||
reserved_memory_mb: 384 # RAM reserved for OS + controller
|
||||
```
|
||||
@@ -1073,6 +1138,7 @@ Auto-generated during deployment. Contains env vars, locked fields list, deploy
|
||||
| metrics-prune | daily | 04:00 | Delete metrics older than 30 days |
|
||||
| selfupdate-check | periodic | 6h | Check registry for new version (cache for UI) |
|
||||
| selfupdate-auto | daily | 04:30 | Auto-update if enabled + backup not running |
|
||||
| asset-sync | daily | 05:00 | Download changed app assets from Hub |
|
||||
|
||||
All daily jobs use Europe/Budapest timezone. Skip-if-running prevents concurrent execution. Panic recovery in all jobs.
|
||||
|
||||
@@ -1167,6 +1233,13 @@ Config endpoints accept session auth OR `Authorization: Bearer <hub_api_key>` (s
|
||||
| GET | `/api/metrics/containers/{name}` | Per-container time-series |
|
||||
| GET | `/api/metrics/sysinfo` | Static system info |
|
||||
|
||||
### Assets
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
|--------|----------|-------------|
|
||||
| POST | `/api/assets/sync` | Trigger on-demand asset sync from Hub (async) |
|
||||
| GET | `/api/assets/status` | Asset sync status (last sync, file count, total bytes) |
|
||||
|
||||
Response format: `{"ok": true/false, "data": ..., "error": "...", "message": "..."}`
|
||||
|
||||
---
|
||||
@@ -1247,6 +1320,9 @@ See `docker-compose.yml` for the full volume configuration.
|
||||
- [x] Controller self-update (v0.16.0) — Watchtower-style pull + restart, Settings page UI, API key auth, auto-update scheduling
|
||||
- [x] Hub-managed config (v0.20.0) — Config apply endpoint (`POST /api/config/apply`), config hash in reports for sync comparison
|
||||
- [x] Config content endpoint (v0.21.1) — `GET /api/config` returns raw YAML for Hub live diff and pull operations
|
||||
- [x] First-run setup wizard (v0.22.0) — Web-based wizard replaces shell scripts, drive scan for local backups, Hub recovery, fresh install flow
|
||||
- [x] Setup wizard logo fix (v0.22.2) — Use embedded SVG instead of filesystem path
|
||||
- [x] Hub-managed asset sync (v0.22.3) — Download app logos/screenshots from Hub API with SHA-256 change detection, daily sync schedule
|
||||
|
||||
### In Progress / Planned
|
||||
|
||||
@@ -1262,7 +1338,7 @@ See `docker-compose.yml` for the full volume configuration.
|
||||
|
||||
| Node | Hardware | Domain | Status |
|
||||
|------|----------|--------|--------|
|
||||
| demo-felhom | Acemagic GK3PLUS N100, 16G RAM, 512G SSD + 1TB HDD | demo-felhom.eu | Controller v0.20.0 |
|
||||
| demo-felhom | Acemagic GK3PLUS N100, 16G RAM, 512G SSD + 1TB HDD | demo-felhom.eu | Controller v0.22.3 |
|
||||
| pi-customer-1 | Raspberry Pi 3B+, 1G RAM, 32G SD | pi-customer-1.local | Not yet tested |
|
||||
|
||||
## Related Repositories
|
||||
|
||||
Reference in New Issue
Block a user