diff --git a/Makefile b/Makefile index 2d5f415..9846674 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,12 @@ else REMOTEDEV_SSH := $(REMOTEDEV_HOST) endif +# pkill -x cannot match names longer than 15 chars (Linux /proc/*/comm). Use -f on argv. +# Stop before scp so running binaries are not busy when overwritten. +REMOTEDEV_KILL = pkill -f './clustercanvas-server( |$$)' >/dev/null 2>&1 || true; \ + pkill -f './clustercanvas-webui( |$$)' >/dev/null 2>&1 || true; \ + sleep 0.2 + service: cd service && go run ./cmd/server @@ -46,13 +52,14 @@ remotedev: # scp only needs OpenSSH on the remote (rsync is often missing on minimal VMs). # Leave ~ unquoted so the remote shell expands REMOTEDEV_DIR=~/... correctly. ssh "$(REMOTEDEV_SSH)" "mkdir -p $(REMOTEDEV_DIR)/web $(REMOTEDEV_DIR)/config" + ssh "$(REMOTEDEV_SSH)" "cd $(REMOTEDEV_DIR) 2>/dev/null || true; $(REMOTEDEV_KILL)" scp bin/clustercanvas-server bin/clustercanvas-webui "$(REMOTEDEV_SSH):$(REMOTEDEV_DIR)/" ssh "$(REMOTEDEV_SSH)" "rm -rf $(REMOTEDEV_DIR)/web && mkdir -p $(REMOTEDEV_DIR)/web" scp -r webui/dist/. "$(REMOTEDEV_SSH):$(REMOTEDEV_DIR)/web/" @echo "Starting on $(REMOTEDEV_SSH) — open http://:$(WEBUI_PORT) (Ctrl+C stops both)" + # Kill in a separate ssh so pkill -f cannot match this start script's own argv. + ssh "$(REMOTEDEV_SSH)" "cd $(REMOTEDEV_DIR) 2>/dev/null || true; $(REMOTEDEV_KILL)" ssh -t "$(REMOTEDEV_SSH)" "cd $(REMOTEDEV_DIR) && \ - pkill -x clustercanvas-server >/dev/null 2>&1 || true; \ - pkill -x clustercanvas-webui >/dev/null 2>&1 || true; \ trap 'kill 0' EXIT INT TERM; \ export CLUSTERCANVAS_CONFIG_KEY='$(REMOTEDEV_CONFIG_KEY)'; \ export CLUSTERCANVAS_CONFIG_DIR=\"\$$PWD/config\"; \ diff --git a/README.md b/README.md index a65428c..59a203c 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,7 @@ REMOTEDEV_USER=youruser REMOTEDEV_HOST=192.168.1.50 make remotedev | `PORT` | `8080` | API listen port on the VM (all interfaces) | | `WEBUI_PORT` | `5173` | Web UI listen port on the VM (all interfaces) | -What lands on the VM: `clustercanvas-server`, `clustercanvas-webui`, and `web/` (built SPA). Config is stored under `$(REMOTEDEV_DIR)/config` with the remotedev encryption key so the setup wizard works without extra env setup. Transfer uses `scp` (OpenSSH only on the remote—no `rsync` required). The webui binary serves the SPA and proxies `/api` and `/health` to the API. Open `http://:5173`. Ctrl+C stops both remote processes. A reverse proxy in front of these ports is optional and separate. +What lands on the VM: `clustercanvas-server`, `clustercanvas-webui`, and `web/` (built SPA). Config is stored under `$(REMOTEDEV_DIR)/config` with the remotedev encryption key so the setup wizard works without extra env setup. Transfer uses `scp` (OpenSSH only on the remote—no `rsync` required). Re-running `make remotedev` stops any previous instance on the VM before uploading so binaries are not busy. The webui binary serves the SPA and proxies `/api` and `/health` to the API. Open `http://:5173`. Ctrl+C stops both remote processes. A reverse proxy in front of these ports is optional and separate. **Do not use `REMOTEDEV_CONFIG_KEY` (or its default) in production** — generate a unique key with `openssl rand -base64 32` instead. ## Test