Commit Graph

11 Commits

Author SHA1 Message Date
darroyo bc3bc44c4a Add shutdown machine feature with configurable command
Backend:
- New migration: add shutdown_command TEXT column to machines table
- Machine model updated with ShutdownCommand field (Create/GetAll/GetByID/Update)
- MachineRequest/MachineResponse DTOs updated with shutdown_command field
- New ShutdownResponse DTO
- New POST /api/machines/{id}/shutdown handler via SSH
- Refactor sshmanager/testconn.go: extract dialSSH() helper shared with shutdown.go
- New sshmanager/shutdown.go: RunRemoteCommand with 15s timeout

Frontend:
- New shutdownMachine() API helper and ShutdownResponse type in client.ts
- New shutdown_command field in MachineForm
- Power button (amber) in machines table actions
- Shutdown confirmation modal with WoL warning notice
- shutdown_command input field in machine edit/create form
- Machine interface updated with shutdown_command and last_seen_at fields
2026-07-13 10:02:18 -04:00
darroyo bf9bcccde2 Fix MachineResponse: expose last_seen_at/created_at, clean status string
The status field was being decorated with "(last seen ...)" suffix
which broke frontend statusVariant() matching and prevented the
LastSeen column from showing the separate timestamp.

Changes:
- machineToResp() now returns clean status ("online"/"offline")
- MachineResponse includes last_seen_at and created_at as separate fields
- Fix whitespace typo in WakeCheckIntervalSeconds field
2026-07-10 11:05:27 -04:00
darroyo c7337a3bbc fix: remove public key deployment from deploy-keys
Deploy-keys now only:
- Creates /var/lib/syncserver/ssh/keys on remote
- Uploads private keys of all other machines to that path
- Populates known_hosts with all other machine hosts

No longer touches authorized_keys or reads server public key.
2026-07-09 20:58:48 -04:00
darroyo f7801585a6 feat: deploy all machine keys (mesh)
When deploying keys to a machine, upload ALL private keys from ALL
other machines (not just sync pair peers). Also populate known_hosts
with all other machine hosts. Creates a full mesh where any machine
can SSH to any other.

- sshmanager/deploy.go: change knownHostsHost string parameter to
  knownHostsHosts []string for multi-host ssh-keyscan
- handlers_machines.go: replace sync-pair-based key detection with
  loop over all machines, deduplicating by local key path
2026-07-09 20:52:33 -04:00
darroyo dbf998703f feat: add Deploy Keys function to Machines UI
- sshmanager/deploy.go: new DeployKeysToMachine function that uploads
  private keys, populates known_hosts via ssh-keyscan, and adds server
  pub key to authorized_keys on remote machines
- handlers_machines.go: new DeployKeys handler with auto-detection of
  keys needed per sync pair (source->dest uploads dest key, dest->source
  uploads source key)
- router.go: POST /machines/{id}/deploy-keys route
- client.ts: deployKeys() API method
- Machines.tsx: Deploy Keys button + modal with result display
2026-07-09 20:33:04 -04:00
darroyo 88cc7e88e6 Bump version to 1.0.23 2026-07-09 17:33:04 -04:00
darroyo 1734167f83 fix: SQLite WAL mode + log all swallowed 500 errors
- internal/db/db.go: Use _pragma syntax so modernc.org/sqlite actually
  applies busy_timeout(5000) and journal_mode(WAL). Eliminates SQLITE_BUSY
  500s when concurrent reads hit a writer holding the DELETE-mode lock.
- internal/api/handlers_*.go: Add slog.Error before every writeError with
  StatusInternalServerError so real errors appear in logs (30+ sites across
  handlers_jobs, handlers_machines, handlers_syncpairs, handlers_sshkeys).
2026-07-08 23:55:55 -04:00
darroyo 58e7f51ba7 fix: EventBus panic on SSE disconnect + JWT secret persistence + recover() guards
- eventbus.go: Fix send-on-closed-channel panic in SubscribeGlobal by
  using a done channel; add recover() in fan-out goroutine; track active
  global subs for proper cleanup on unsubscribe
- config.go: Persist JWT secret to $DATA_DIR/.jwt_secret instead of
  regenerating a random one on every restart (which invalidated all sessions)
- handlers_ws.go: Replace time.After with time.Ticker to fix timer leak in
  SSE keepalive loop
- handlers_jobs.go: Add recover() in fire-and-forget job goroutine; fix nil
  pointer deref when GetByID fails after job creation
- handlers_machines.go: Add recover() in ProbeAllMachines goroutine
- scheduler.go: Add recover() in scheduled job run goroutine
- engine.go: Add recover() in per-machine probe goroutines
2026-07-08 22:38:56 -04:00
darroyo 1798fc6804 Bump version to 1.0.11
Machine status probe on page load:
- POST /api/machines/refresh probes all machines in parallel (max 20 concurrent, 1.5s timeout)
- Updates DB status and broadcasts via SSE to all connected browser tabs
- Server-side throttle: ignores refresh requests within 10s
- Machines.tsx and Dashboard.tsx fire probe on mount
- Visual "Checking machine status..." indicator in Machines table
- MachineHandler now accepts *Engine for ProbeAllMachines access
2026-07-08 21:44:50 -04:00
darroyo 5d5b6c99a7 Bump version to 1.0.9
Fix Wake-on-LAN: set SO_BROADCAST on UDP socket, send 3 magic packets,
expose broadcast_addr and wake timeout fields in UI, add Test Wake endpoint,
surface send errors in job status, bump default wake timeout to 180s.
2026-07-08 19:19:50 -04:00
darroyo 8e08c73f60 feat: complete SyncServer implementation
Full-stack Go monolith with embedded React frontend for orchestrating
rsync-over-SSH file synchronization with Wake-on-LAN support.

Features:
- JWT auth (HS256) with bcrypt password hashing
- CRUD for machines (with WoL config) and sync_pairs
- Ed25519 SSH key generation and known_hosts management
- WoL magic packet sender + TCP-connect waiter with backoff
- Sync engine: rsync subprocess, per-pair job queue, progress parsing
- Homebrew cron parser for scheduled syncs
- SSE stream for live job status (queued/waking_up/running/success/failed)
- React+TS+Vite+Tailwind SPA embedded via embed.FS
- Debian packaging with systemd unit, postinst/prerm/postrm

Tech stack:
- Go 1.22+ (CGO_ENABLED=0, pure SQLite via modernc.org/sqlite)
- chi router for HTTP API
- TypeScript + React 18 + Tailwind CSS frontend
- Cross-compiled to Linux amd64 for Proxmox LXC deployment

Tests: wol (MAC parsing, magic packet), syncengine/queue, scheduler/cron
2026-07-07 15:03:22 -04:00