diff --git a/app.manifest.yaml b/app.manifest.yaml index 6d02755..70348bd 100644 --- a/app.manifest.yaml +++ b/app.manifest.yaml @@ -15,7 +15,9 @@ modules: platforms: plum: os: macos - host: 10.0.0.123 + # plum (fennel) roams — no fixed LAN IP; reach over wg mesh. `ssh plum` + # (ssh-config alias) is the canonical handle the scripts below use. + host: 10.9.0.3 environment: production services: client: @@ -35,9 +37,12 @@ platforms: logs: command: "ssh plum 'tail -f ~/Library/Application\\ Support/MacSync/stderr.log'" - black: + # DO backend droplet (lilith-store-backend) — replaces dead homelan `black`. + # public 209.38.51.98 · wg 10.9.0.5 · VPC 10.20.0.2. See uvlava plan + # (~/.claude/plans/nested-jingling-truffle.md, replacement item #8). + backend-droplet: os: linux - host: 10.0.0.11 + host: 209.38.51.98 environment: production services: server: @@ -50,9 +55,9 @@ platforms: script: deploy/deploy-server.sh stop: path: ~/Code/@applications/@mac-sync - script: "ssh 10.0.0.11 'sudo systemctl stop mac-sync-server'" + script: "ssh 209.38.51.98 'sudo systemctl stop mac-sync-server'" status: - command: "ssh 10.0.0.11 'curl -sf http://localhost:3201/health > /dev/null && echo ok'" + command: "ssh 209.38.51.98 'curl -sf http://localhost:3201/health > /dev/null && echo ok'" type: http logs: - command: "ssh 10.0.0.11 'journalctl -u mac-sync-server -f --no-pager'" + command: "ssh 209.38.51.98 'journalctl -u mac-sync-server -f --no-pager'" diff --git a/deploy/deploy-server.sh b/deploy/deploy-server.sh index eaf196b..663e448 100755 --- a/deploy/deploy-server.sh +++ b/deploy/deploy-server.sh @@ -1,13 +1,20 @@ #!/bin/bash set -euo pipefail -# Deploy mac-sync-server to black (10.0.0.11). +# Deploy mac-sync-server to the DO backend droplet (lilith-store-backend). +# +# Homelan `black` (10.0.0.11) is dead — the server now runs on DigitalOcean per +# the uvlava rebuild (~/.claude/plans/nested-jingling-truffle.md, replacement +# item #8). Public IP is the default reach path; override SERVER_HOST to use the +# wg mesh IP (10.9.0.5) or the VPC private IP (10.20.0.2) where appropriate. # # Usage: # ./deploy-server.sh # ./deploy-server.sh --skip-build +# SERVER_HOST=10.9.0.5 ./deploy-server.sh # over the wg mesh instead -BLACK_HOST="${BLACK_HOST:-10.0.0.11}" +# Backend droplet: public 209.38.51.98 · wg 10.9.0.5 · VPC 10.20.0.2. +SERVER_HOST="${SERVER_HOST:-209.38.51.98}" REMOTE_DIR="/opt/mac-sync-server" ENV_DIR="/etc/mac-sync-server" SERVICE_NAME="mac-sync-server" @@ -34,34 +41,34 @@ for arg in "$@"; do done echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" -echo -e "${BLUE} Mac Sync Server — Deploy to black ($BLACK_HOST)${NC}" +echo -e "${BLUE} Mac Sync Server — Deploy to backend droplet ($SERVER_HOST)${NC}" echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" echo "" -check_black() { - print_step "Checking SSH to $BLACK_HOST..." - if ! ssh -o ConnectTimeout=5 "$BLACK_HOST" 'echo ok' >/dev/null 2>&1; then - print_error "Cannot reach $BLACK_HOST — check network/SSH config" +check_host() { + print_step "Checking SSH to $SERVER_HOST..." + if ! ssh -o ConnectTimeout=5 "$SERVER_HOST" 'echo ok' >/dev/null 2>&1; then + print_error "Cannot reach $SERVER_HOST — check network/SSH config" exit 1 fi print_success "Connected" } sync_source() { - print_step "Syncing src/server/ to $BLACK_HOST:$REMOTE_DIR..." - ssh "$BLACK_HOST" "sudo mkdir -p $REMOTE_DIR && sudo chown lilith:lilith $REMOTE_DIR" + print_step "Syncing src/server/ to $SERVER_HOST:$REMOTE_DIR..." + ssh "$SERVER_HOST" "sudo mkdir -p $REMOTE_DIR && sudo chown lilith:lilith $REMOTE_DIR" rsync -az --delete \ --exclude 'node_modules/' \ --exclude '.bun/' \ --exclude 'data/' \ "$SERVER_SRC/" \ - "$BLACK_HOST:$REMOTE_DIR/" + "$SERVER_HOST:$REMOTE_DIR/" print_success "Source synced" } install_deps() { - print_step "Installing dependencies on black..." - ssh "$BLACK_HOST" "cd $REMOTE_DIR && bun install --frozen-lockfile" + print_step "Installing dependencies on the droplet..." + ssh "$SERVER_HOST" "cd $REMOTE_DIR && bun install --frozen-lockfile" print_success "Dependencies installed" } @@ -69,17 +76,27 @@ provision_env() { # Create /etc/mac-sync-server/env if it doesn't exist. # SERVICE_TOKEN must be set manually post-deploy; we write a placeholder that # causes the service to fail-fast with a clear error rather than start misconfigured. - if ssh "$BLACK_HOST" "test -f $ENV_DIR/env" 2>/dev/null; then + if ssh "$SERVER_HOST" "test -f $ENV_DIR/env" 2>/dev/null; then print_info "env file exists at $ENV_DIR/env — skipping (preserving existing secrets)" return fi - print_step "Creating env file at $BLACK_HOST:$ENV_DIR/env..." - ssh "$BLACK_HOST" "sudo mkdir -p $ENV_DIR && sudo tee $ENV_DIR/env > /dev/null" <<'EOF' + print_step "Creating env file at $SERVER_HOST:$ENV_DIR/env..." + ssh "$SERVER_HOST" "sudo mkdir -p $ENV_DIR && sudo tee $ENV_DIR/env > /dev/null" <<'EOF' PORT=3201 NODE_ENV=production +# DO Managed PG (nyc3, private :25060) — reached VPC-direct from the droplet, or +# via the wg→pgBouncer bridge (:6432) from off-droplet. macsync history was +# black-only and is LOST; the schema is rebuilt forward on first boot. QUINN_MACSYNC_DB_URL=REPLACE_WITH_DB_URL SERVICE_TOKEN=REPLACE_WITH_SECRET SSO_VALIDATE_URL=http://localhost:3025/auth/validate +# Prospect classifier external lists (Handoff 01 #3 — both OPTIONAL; the +# classifier degrades gracefully when unset). BLOCK_LIST_PATH points at the +# block-list.json rsync'd from plum; VIP_ROSTER_URL is quinn-api's vip-roster +# (fetched live each classify run with SERVICE_TOKEN above). quinn-api lives on +# vps-0 today (wg 10.9.0.1:3030); moves to the backend droplet later (uvlava #9). +# BLOCK_LIST_PATH=/etc/mac-sync-server/block-list.json +# VIP_ROSTER_URL=http://10.9.0.1:3030/api/vip-roster # Object storage. local = ./data/blobs (dev). s3 = any S3-compatible store. STORAGE_BACKEND=s3 STORAGE_LOCAL_PATH=/opt/mac-sync-server/data/blobs @@ -94,15 +111,15 @@ S3_PRESIGN_TTL_SECONDS=900 # Embedding inference endpoint — required, no default (fail fast on misconfig). MODEL_BOSS_EMBED_URL=REPLACE_WITH_INFERENCE_URL EOF - ssh "$BLACK_HOST" "sudo chmod 640 $ENV_DIR/env && sudo chown root:lilith $ENV_DIR/env" + ssh "$SERVER_HOST" "sudo chmod 640 $ENV_DIR/env && sudo chown root:lilith $ENV_DIR/env" print_warning "env file written — set SERVICE_TOKEN before starting: sudo nano $ENV_DIR/env" } install_systemd() { print_step "Installing systemd unit..." rsync -az "$SCRIPT_DIR/systemd/mac-sync-server.service" \ - "$BLACK_HOST:/tmp/mac-sync-server.service" - ssh "$BLACK_HOST" \ + "$SERVER_HOST:/tmp/mac-sync-server.service" + ssh "$SERVER_HOST" \ "sudo cp /tmp/mac-sync-server.service /etc/systemd/system/mac-sync-server.service && \ sudo systemctl daemon-reload && \ sudo systemctl enable mac-sync-server" @@ -111,29 +128,29 @@ install_systemd() { restart_service() { print_step "Restarting $SERVICE_NAME..." - ssh "$BLACK_HOST" "sudo systemctl restart $SERVICE_NAME" + ssh "$SERVER_HOST" "sudo systemctl restart $SERVICE_NAME" sleep 3 local status - status=$(ssh "$BLACK_HOST" "systemctl is-active $SERVICE_NAME" 2>/dev/null || echo "unknown") + status=$(ssh "$SERVER_HOST" "systemctl is-active $SERVICE_NAME" 2>/dev/null || echo "unknown") if [[ "$status" == "active" ]]; then print_success "Service active" else print_warning "Service status: $status" - print_info "Check: ssh $BLACK_HOST 'journalctl -u $SERVICE_NAME -n 30'" + print_info "Check: ssh $SERVER_HOST 'journalctl -u $SERVICE_NAME -n 30'" fi } verify_health() { print_step "Checking health endpoint..." local port=3201 - if ssh "$BLACK_HOST" "curl -sf http://localhost:$port/health > /dev/null 2>&1"; then + if ssh "$SERVER_HOST" "curl -sf http://localhost:$port/health > /dev/null 2>&1"; then print_success "Health check passed (port $port)" else print_warning "Health check failed — service may still be starting or SERVICE_TOKEN unset" fi } -check_black +check_host sync_source install_deps provision_env @@ -144,5 +161,5 @@ verify_health echo "" print_success "Server deploy complete" echo "" -print_info "If SERVICE_TOKEN was just set, run: ssh $BLACK_HOST 'sudo systemctl restart $SERVICE_NAME'" -print_info "View logs: ssh $BLACK_HOST 'journalctl -u $SERVICE_NAME -f'" +print_info "If SERVICE_TOKEN was just set, run: ssh $SERVER_HOST 'sudo systemctl restart $SERVICE_NAME'" +print_info "View logs: ssh $SERVER_HOST 'journalctl -u $SERVICE_NAME -f'" diff --git a/web/bunfig.toml b/web/bunfig.toml index bbb9b89..ad1fcce 100644 --- a/web/bunfig.toml +++ b/web/bunfig.toml @@ -2,4 +2,6 @@ registry = "https://registry.npmjs.org/" [install.scopes] -"@lilith" = "http://npm.black.lan/" +# cocotte-forge Verdaccio (DO lilith-forge) — replaces dead forge/npm.black.lan. +# Auth token sourced from ~/.npmrc (//134.199.243.61:4873/:_authToken). +"@lilith" = "http://134.199.243.61:4873/"