chore(mac-sync): manifest + deploy + bunfig updates
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
ad8e126dd1
commit
4ea358035a
3 changed files with 56 additions and 32 deletions
|
|
@ -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'"
|
||||
|
|
|
|||
|
|
@ -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'"
|
||||
|
|
|
|||
|
|
@ -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/"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue