Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
697a7e614d | ||
|
|
d07342e97e |
@@ -41,13 +41,33 @@ On Linux and Windows a tray icon appears — closing the window hides to tray ra
|
||||
|
||||
---
|
||||
|
||||
## Option 3 — Run the daemon manually (headless / power users)
|
||||
## Option 3 — Run the daemon + TUI or web UI locally (power users / dev)
|
||||
|
||||
Example scripts are provided for the common local workflows. Copy them and fill in your anchor URL:
|
||||
|
||||
```bash
|
||||
# TUI (terminal UI):
|
||||
cp launch-tui.sh.example launch-tui.sh
|
||||
$EDITOR launch-tui.sh # set ANCHOR=wss://your-anchor/ws
|
||||
./launch-tui.sh
|
||||
|
||||
# Web UI in daemon mode (Vite dev server + daemon):
|
||||
cp launch-web.sh.example launch-web.sh
|
||||
$EDITOR launch-web.sh # set ANCHOR=wss://your-anchor/ws
|
||||
./launch-web.sh
|
||||
```
|
||||
|
||||
The real script files are gitignored so your local edits (anchor URL, alias, network) are never accidentally committed.
|
||||
|
||||
---
|
||||
|
||||
## Option 4 — Run the daemon manually (headless)
|
||||
|
||||
If you want the daemon running in the background without the desktop UI — on a server, over SSH, or with the web UI in a browser pointed at your local machine:
|
||||
|
||||
```bash
|
||||
# Download waste-daemon from the releases page, then:
|
||||
./waste-daemon -alias yourname -anchor wss://your-anchor-server/ws
|
||||
./waste-daemon -alias yourname -anchor wss://YOUR_ANCHOR_DOMAIN/ws
|
||||
```
|
||||
|
||||
Then open the web UI in a browser at the anchor URL, or point the web UI's daemon mode at `ws://127.0.0.1:17338`.
|
||||
@@ -83,7 +103,7 @@ The anchor is a tiny signaling server that helps peers find each other — it ne
|
||||
|
||||
```bash
|
||||
# On your VPS:
|
||||
./waste-anchor -bind 127.0.0.1:8080
|
||||
./waste-anchor -bind 127.0.0.1:8080 -turn-secret YOUR_COTURN_SECRET
|
||||
```
|
||||
|
||||
Put it behind nginx with a `/ws` WebSocket proxy and serve the web UI static files at `/`. See [README.md](README.md#hosting-on-a-vps) for the full nginx setup.
|
||||
Put it behind nginx with `/ws` and `/turn-credentials` proxied to the anchor, and the web UI static files at `/`. See [README.md](README.md#hosting-on-a-vps) for the full nginx setup.
|
||||
|
||||
@@ -155,8 +155,8 @@ func (a *anchor) handleWS(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithCancel(r.Context())
|
||||
defer cancel()
|
||||
|
||||
// Send a challenge nonce immediately.
|
||||
nonce := make([]byte, 16)
|
||||
// Send a challenge nonce immediately. §5.1 requires 32 bytes.
|
||||
nonce := make([]byte, 32)
|
||||
rand.Read(nonce)
|
||||
nonceHex := hex.EncodeToString(nonce)
|
||||
if err := wsjson.Write(ctx, conn, proto.AnchorMessage{
|
||||
|
||||
32
deploy-web.sh.example
Normal file
32
deploy-web.sh.example
Normal file
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env bash
|
||||
# deploy-web.sh — build and push the web UI to the VPS.
|
||||
# Assumes SSH agent forwarding is set up.
|
||||
#
|
||||
# SETUP: copy this file to deploy-web.sh (gitignored) and set HOST below.
|
||||
#
|
||||
# Usage:
|
||||
# ./deploy-web.sh
|
||||
#
|
||||
# Optional env vars:
|
||||
# HOST SSH target (user@host) (required — edit below)
|
||||
# REMOTE_DIR path on VPS (default: ~/waste-www)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
HOST="${HOST:-user@YOUR_VPS_IP}" # ← edit this
|
||||
REMOTE_DIR="${REMOTE_DIR:-~/waste-www}"
|
||||
|
||||
if [[ "$HOST" == *YOUR_VPS_IP* ]]; then
|
||||
echo "error: edit HOST in this script (or export HOST=user@your-vps before running)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "→ building web UI…"
|
||||
"$(dirname "$0")/build-web.sh"
|
||||
|
||||
echo "→ syncing to $HOST:$REMOTE_DIR"
|
||||
rsync -azv --delete \
|
||||
--exclude='config.js' \
|
||||
web/dist/ "$HOST:$REMOTE_DIR/"
|
||||
|
||||
echo "✓ done"
|
||||
96
launch-tui.sh.example
Normal file
96
launch-tui.sh.example
Normal file
@@ -0,0 +1,96 @@
|
||||
#!/usr/bin/env bash
|
||||
# launch-tui.sh — build and launch the TUI against a remote anchor.
|
||||
# Starts a local daemon then opens the Bubble Tea terminal UI.
|
||||
#
|
||||
# SETUP: copy this file to launch-tui.sh (gitignored) and set ANCHOR below.
|
||||
#
|
||||
# Usage:
|
||||
# ./launch-tui.sh
|
||||
# ALIAS=alice NETWORK=friends ./launch-tui.sh
|
||||
#
|
||||
# Optional env vars (all have defaults):
|
||||
# ANCHOR anchor WebSocket URL (required — edit below)
|
||||
# NETWORK network name to join (default: "friends")
|
||||
# ALIAS display name (default: $USER)
|
||||
# DATA_DIR identity + message store dir (default: ~/.waste-$ALIAS)
|
||||
# IPC_PORT local daemon IPC port (default: 17337)
|
||||
# SHARE_DIR directory to share with peers (optional)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ANCHOR="${ANCHOR:-wss://YOUR_ANCHOR_DOMAIN/ws}" # ← edit this
|
||||
|
||||
NETWORK="${NETWORK:-friends}"
|
||||
ALIAS="${ALIAS:-${USER:-anon}}"
|
||||
DATA_DIR="${DATA_DIR:-${HOME}/.waste-${ALIAS}}"
|
||||
|
||||
_DEFAULT_ALIAS="${USER:-anon}"
|
||||
if [ "${ALIAS}" = "${_DEFAULT_ALIAS}" ]; then
|
||||
IPC_PORT="${IPC_PORT:-17337}"
|
||||
else
|
||||
_HASH=$(printf '%d' "0x$(printf '%s' "$ALIAS" | md5sum | cut -c1-4)")
|
||||
IPC_PORT="${IPC_PORT:-$(( 17400 + _HASH % 1000 ))}"
|
||||
fi
|
||||
|
||||
SHARE_DIR="${SHARE_DIR:-}"
|
||||
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; DIM='\033[2m'; BOLD='\033[1m'; RESET='\033[0m'
|
||||
|
||||
if [[ "$ANCHOR" == *YOUR_ANCHOR_DOMAIN* ]]; then
|
||||
echo -e "${RED}error: edit ANCHOR in this script (or export ANCHOR=wss://... before running)${RESET}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$DATA_DIR"
|
||||
|
||||
echo ""
|
||||
echo -e "${BOLD}waste TUI${RESET}"
|
||||
echo -e "${DIM}anchor : ${BOLD}${ANCHOR}${RESET}"
|
||||
echo -e "${DIM}network : ${BOLD}${NETWORK}${RESET}"
|
||||
echo -e "${DIM}alias : ${BOLD}${ALIAS}${RESET}"
|
||||
echo -e "${DIM}data : ${DATA_DIR}${RESET}"
|
||||
[ -n "$SHARE_DIR" ] && echo -e "${DIM}share : ${SHARE_DIR}${RESET}"
|
||||
echo ""
|
||||
|
||||
echo -e "${DIM}building binaries…${RESET}"
|
||||
go build -o /tmp/waste-daemon-run ./cmd/daemon
|
||||
go build -o /tmp/waste-tui-run ./cmd/tui
|
||||
echo -e "${GREEN}✓ built${RESET}"
|
||||
echo ""
|
||||
|
||||
existing=$(lsof -ti tcp:"$IPC_PORT" 2>/dev/null || true)
|
||||
[ -n "$existing" ] && kill "$existing" 2>/dev/null && sleep 0.3 || true
|
||||
|
||||
echo -e "${DIM}starting daemon on :${IPC_PORT}…${RESET}"
|
||||
WS_PORT=$(( IPC_PORT + 1 ))
|
||||
/tmp/waste-daemon-run \
|
||||
-alias "$ALIAS" -data-dir "$DATA_DIR" \
|
||||
-ipc-port "$IPC_PORT" -ws-port "$WS_PORT" \
|
||||
-anchor "$ANCHOR" \
|
||||
2>/tmp/waste-daemon.log &
|
||||
DAEMON_PID=$!
|
||||
|
||||
n=0
|
||||
while ! nc -z 127.0.0.1 "$IPC_PORT" 2>/dev/null; do
|
||||
sleep 0.1; n=$(( n + 1 ))
|
||||
[ "$n" -gt 80 ] && echo -e "${RED}daemon failed — check /tmp/waste-daemon.log${RESET}" >&2 && exit 1
|
||||
done
|
||||
echo -e "${GREEN}✓ daemon started (pid ${DAEMON_PID})${RESET}"
|
||||
|
||||
sleep 0.3
|
||||
if [ -n "$SHARE_DIR" ]; then
|
||||
JOIN=$(jq -cn --arg net "$NETWORK" --arg dir "$SHARE_DIR" \
|
||||
'{"type":"join_network","network_name":$net,"share_dir":$dir}')
|
||||
else
|
||||
JOIN=$(jq -cn --arg net "$NETWORK" '{"type":"join_network","network_name":$net}')
|
||||
fi
|
||||
echo "$JOIN" | nc -q 0 127.0.0.1 "$IPC_PORT" >/dev/null 2>&1 || true
|
||||
echo -e "${DIM}joined network: ${BOLD}${NETWORK}${RESET}"
|
||||
|
||||
cleanup() { kill "$DAEMON_PID" 2>/dev/null || true; }
|
||||
trap cleanup EXIT INT TERM
|
||||
|
||||
echo ""
|
||||
echo -e "${BOLD}launching TUI${RESET} — ${DIM}ctrl+c to quit${RESET}"
|
||||
echo ""
|
||||
exec /tmp/waste-tui-run -ipc "$IPC_PORT" -network "$NETWORK"
|
||||
74
launch-web.sh.example
Normal file
74
launch-web.sh.example
Normal file
@@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env bash
|
||||
# launch-web.sh — start the daemon and open the web UI Vite dev server.
|
||||
# For local development / daemon-mode browsing.
|
||||
#
|
||||
# SETUP: copy this file to launch-web.sh (gitignored) and set ANCHOR below.
|
||||
#
|
||||
# Usage:
|
||||
# ./launch-web.sh
|
||||
# ALIAS=alice NETWORK=friends ./launch-web.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ANCHOR="${ANCHOR:-wss://YOUR_ANCHOR_DOMAIN/ws}" # ← edit this
|
||||
|
||||
NETWORK="${NETWORK:-friends}"
|
||||
ALIAS="${ALIAS:-${USER:-anon}}"
|
||||
DATA_DIR="${DATA_DIR:-${HOME}/.waste-${ALIAS}}"
|
||||
IPC_PORT="${IPC_PORT:-17337}"
|
||||
WS_PORT=$(( IPC_PORT + 1 ))
|
||||
|
||||
if [[ "$ANCHOR" == *YOUR_ANCHOR_DOMAIN* ]]; then
|
||||
echo "error: edit ANCHOR in this script (or export ANCHOR=wss://... before running)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PIDS=()
|
||||
cleanup() {
|
||||
for pid in "${PIDS[@]:-}"; do kill "$pid" 2>/dev/null || true; done
|
||||
wait 2>/dev/null || true
|
||||
}
|
||||
trap cleanup EXIT INT TERM
|
||||
|
||||
for port in "$IPC_PORT" "$WS_PORT"; do
|
||||
existing=$(lsof -ti tcp:"$port" 2>/dev/null || true)
|
||||
[ -n "$existing" ] && kill "$existing" 2>/dev/null || true
|
||||
done
|
||||
for port in "$IPC_PORT" "$WS_PORT"; do
|
||||
n=0
|
||||
while lsof -ti tcp:"$port" >/dev/null 2>&1; do
|
||||
sleep 0.1; n=$(( n + 1 )); [ "$n" -gt 30 ] && break
|
||||
done
|
||||
done
|
||||
|
||||
mkdir -p "$DATA_DIR"
|
||||
|
||||
echo "alias : $ALIAS"
|
||||
echo "network : $NETWORK"
|
||||
echo "anchor : $ANCHOR"
|
||||
echo "ws-port : $WS_PORT"
|
||||
echo ""
|
||||
|
||||
echo "building daemon…"
|
||||
go build -o /tmp/waste-daemon-web ./cmd/daemon
|
||||
|
||||
/tmp/waste-daemon-web \
|
||||
-alias "$ALIAS" -data-dir "$DATA_DIR" \
|
||||
-ipc-port "$IPC_PORT" -ws-port "$WS_PORT" \
|
||||
-anchor "$ANCHOR" \
|
||||
2>/tmp/waste-daemon-web.log &
|
||||
PIDS+=($!)
|
||||
|
||||
n=0
|
||||
while ! nc -z 127.0.0.1 "$IPC_PORT" 2>/dev/null; do
|
||||
sleep 0.1; n=$(( n + 1 ))
|
||||
[ "$n" -gt 80 ] && echo "daemon failed to start — check /tmp/waste-daemon-web.log" >&2 && exit 1
|
||||
done
|
||||
|
||||
sleep 0.2
|
||||
jq -cn --arg net "$NETWORK" '{"type":"join_network","network_name":$net}' \
|
||||
| nc -q0 127.0.0.1 "$IPC_PORT" >/dev/null 2>&1 || true
|
||||
echo "daemon ready — joined $NETWORK"
|
||||
echo ""
|
||||
|
||||
npm run dev --prefix "$(dirname "$0")/web"
|
||||
38
serve-web.sh.example
Normal file
38
serve-web.sh.example
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
# serve-web.sh — start (or restart) the static file server on the VPS.
|
||||
# Runs `npx serve` in the background, logs to ~/waste-www.log.
|
||||
#
|
||||
# SETUP: copy this file to serve-web.sh (gitignored) and set HOST below.
|
||||
#
|
||||
# Usage:
|
||||
# ./serve-web.sh
|
||||
#
|
||||
# Optional env vars:
|
||||
# HOST SSH target (user@host) (required — edit below)
|
||||
# REMOTE_DIR path on VPS (default: ~/waste-www)
|
||||
# PORT local port on VPS (default: 1337)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
HOST="${HOST:-user@YOUR_VPS_IP}" # ← edit this
|
||||
REMOTE_DIR="${REMOTE_DIR:-~/waste-www}"
|
||||
REMOTE_LOG="~/waste-www.log"
|
||||
REMOTE_PID="~/waste-www.pid"
|
||||
PORT="${PORT:-1337}"
|
||||
|
||||
if [[ "$HOST" == *YOUR_VPS_IP* ]]; then
|
||||
echo "error: edit HOST in this script (or export HOST=user@your-vps before running)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ssh "$HOST" bash <<EOF
|
||||
if [ -f $REMOTE_PID ]; then
|
||||
kill \$(cat $REMOTE_PID) 2>/dev/null || true
|
||||
rm -f $REMOTE_PID
|
||||
fi
|
||||
|
||||
echo "[\$(date)] starting npx serve on port $PORT" >> $REMOTE_LOG
|
||||
nohup npx serve -s $REMOTE_DIR -l $PORT >> $REMOTE_LOG 2>&1 &
|
||||
echo \$! > $REMOTE_PID
|
||||
echo "→ started (pid \$(cat $REMOTE_PID)), logging to $REMOTE_LOG"
|
||||
EOF
|
||||
Reference in New Issue
Block a user