- Restructure Dockerfile.alpine-musl for better layer caching * Build dependencies (secp256k1, libwebsockets) in separate cached layers * Copy submodules before source files to maximize cache hits * Reduce rebuild time from ~2-3 minutes to ~10-15 seconds for source changes - Remove 'musl' from binary names (c_relay_static_x86_64 instead of c_relay_static_musl_x86_64) - Enforce static binary usage in make_and_restart_relay.sh * Remove all fallbacks to regular make builds * Exit with clear error if static binary not found * Ensures JSON1 extension is always available - Fix build_static.sh hanging on ldd check with timeout - Remove sudo usage from build_static.sh (assumes docker group membership) These changes ensure consistent builds with JSON1 support and dramatically improve development iteration speed through intelligent Docker layer caching.
390 lines
13 KiB
Bash
Executable File
390 lines
13 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# C-Relay Build and Restart Script
|
|
# Builds the project first, then stops any running relay and starts a new one in the background
|
|
|
|
echo "=== C Nostr Relay Build and Restart Script ==="
|
|
|
|
# Parse command line arguments
|
|
PRESERVE_DATABASE=false
|
|
HELP=false
|
|
USE_TEST_KEYS=false
|
|
ADMIN_KEY=""
|
|
RELAY_KEY=""
|
|
PORT_OVERRIDE=""
|
|
|
|
# Key validation function
|
|
validate_hex_key() {
|
|
local key="$1"
|
|
local key_type="$2"
|
|
|
|
if [ ${#key} -ne 64 ]; then
|
|
echo "ERROR: $key_type key must be exactly 64 characters"
|
|
return 1
|
|
fi
|
|
|
|
if ! [[ "$key" =~ ^[0-9a-fA-F]{64}$ ]]; then
|
|
echo "ERROR: $key_type key must contain only hex characters (0-9, a-f, A-F)"
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
-a|--admin-key)
|
|
if [ -z "$2" ]; then
|
|
echo "ERROR: Admin key option requires a value"
|
|
HELP=true
|
|
shift
|
|
else
|
|
ADMIN_KEY="$2"
|
|
shift 2
|
|
fi
|
|
;;
|
|
-r|--relay-key)
|
|
if [ -z "$2" ]; then
|
|
echo "ERROR: Relay key option requires a value"
|
|
HELP=true
|
|
shift
|
|
else
|
|
RELAY_KEY="$2"
|
|
shift 2
|
|
fi
|
|
;;
|
|
-p|--port)
|
|
if [ -z "$2" ]; then
|
|
echo "ERROR: Port option requires a value"
|
|
HELP=true
|
|
shift
|
|
else
|
|
PORT_OVERRIDE="$2"
|
|
shift 2
|
|
fi
|
|
;;
|
|
-d|--preserve-database)
|
|
PRESERVE_DATABASE=true
|
|
shift
|
|
;;
|
|
--test-keys|-t)
|
|
USE_TEST_KEYS=true
|
|
shift
|
|
;;
|
|
--help|-h)
|
|
HELP=true
|
|
shift
|
|
;;
|
|
*)
|
|
echo "Unknown option: $1"
|
|
HELP=true
|
|
shift
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Validate custom keys if provided
|
|
if [ -n "$ADMIN_KEY" ]; then
|
|
if ! validate_hex_key "$ADMIN_KEY" "Admin"; then
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
if [ -n "$RELAY_KEY" ]; then
|
|
if ! validate_hex_key "$RELAY_KEY" "Relay"; then
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Validate port if provided
|
|
if [ -n "$PORT_OVERRIDE" ]; then
|
|
if ! [[ "$PORT_OVERRIDE" =~ ^[0-9]+$ ]] || [ "$PORT_OVERRIDE" -lt 1 ] || [ "$PORT_OVERRIDE" -gt 65535 ]; then
|
|
echo "ERROR: Port must be a number between 1 and 65535"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Show help
|
|
if [ "$HELP" = true ]; then
|
|
echo "Usage: $0 [OPTIONS]"
|
|
echo ""
|
|
echo "Options:"
|
|
echo " -a, --admin-key <hex> 64-character hex admin private key"
|
|
echo " -r, --relay-key <hex> 64-character hex relay private key"
|
|
echo " -p, --port <port> Custom port override (default: 8888)"
|
|
echo " --preserve-database Keep existing database files (don't delete for fresh start)"
|
|
echo " --test-keys, -t Use deterministic test keys for development (admin: all 'a's, relay: all '1's)"
|
|
echo " --help, -h Show this help message"
|
|
echo ""
|
|
echo "Event-Based Configuration:"
|
|
echo " This relay now uses event-based configuration stored directly in the database."
|
|
echo " On first startup, keys are automatically generated and printed once."
|
|
echo " Database file: <relay_pubkey>.db (created automatically)"
|
|
echo ""
|
|
echo "Examples:"
|
|
echo " $0 # Fresh start with random keys"
|
|
echo " $0 -a <admin-hex> -r <relay-hex> # Use custom keys"
|
|
echo " $0 -a <admin-hex> -p 9000 # Custom admin key on port 9000"
|
|
echo " $0 --preserve-database # Preserve existing database and keys"
|
|
echo " $0 --test-keys # Use test keys for consistent development"
|
|
echo " $0 -t --preserve-database # Use test keys and preserve database"
|
|
echo ""
|
|
echo "Key Format: Keys must be exactly 64 hexadecimal characters (0-9, a-f, A-F)"
|
|
echo "Default behavior: Deletes existing database files to start fresh with new keys"
|
|
echo " for development purposes"
|
|
exit 0
|
|
fi
|
|
|
|
# Handle database file cleanup for fresh start
|
|
if [ "$PRESERVE_DATABASE" = false ]; then
|
|
if ls *.db >/dev/null 2>&1 || ls build/*.db >/dev/null 2>&1; then
|
|
echo "Removing existing database files to trigger fresh key generation..."
|
|
rm -f *.db build/*.db
|
|
echo "✓ Database files removed - will generate new keys and database"
|
|
else
|
|
echo "No existing database found - will generate fresh setup"
|
|
fi
|
|
else
|
|
echo "Preserving existing database files as requested"
|
|
# Back up database files before clean build
|
|
if ls build/*.db >/dev/null 2>&1; then
|
|
echo "Backing up existing database files..."
|
|
mkdir -p /tmp/relay_backup_$$
|
|
cp build/*.db* /tmp/relay_backup_$$/ 2>/dev/null || true
|
|
echo "Database files backed up to temporary location"
|
|
fi
|
|
fi
|
|
|
|
# Clean up legacy files that are no longer used
|
|
rm -rf dev-config/ 2>/dev/null
|
|
rm -f db/c_nostr_relay.db* 2>/dev/null
|
|
|
|
# Embed web files into C headers before building
|
|
echo "Embedding web files..."
|
|
./embed_web_files.sh
|
|
|
|
# Build the project - ONLY static build
|
|
echo "Building project (static binary with SQLite JSON1 extension)..."
|
|
./build_static.sh
|
|
|
|
# Exit if static build fails - no fallback
|
|
if [ $? -ne 0 ]; then
|
|
echo "ERROR: Static build failed. Cannot proceed without static binary."
|
|
echo "Please fix the build errors and try again."
|
|
exit 1
|
|
fi
|
|
|
|
# Restore database files if preserving
|
|
if [ "$PRESERVE_DATABASE" = true ] && [ -d "/tmp/relay_backup_$$" ]; then
|
|
echo "Restoring preserved database files..."
|
|
cp /tmp/relay_backup_$$/*.db* build/ 2>/dev/null || true
|
|
rm -rf /tmp/relay_backup_$$
|
|
echo "Database files restored to build directory"
|
|
fi
|
|
|
|
# Check if build was successful
|
|
if [ $? -ne 0 ]; then
|
|
echo "ERROR: Build failed. Cannot restart relay."
|
|
exit 1
|
|
fi
|
|
|
|
# Check if static relay binary exists after build - ONLY use static binary
|
|
ARCH=$(uname -m)
|
|
case "$ARCH" in
|
|
x86_64)
|
|
BINARY_PATH="./build/c_relay_static_x86_64"
|
|
;;
|
|
aarch64|arm64)
|
|
BINARY_PATH="./build/c_relay_static_arm64"
|
|
;;
|
|
*)
|
|
BINARY_PATH="./build/c_relay_static_$ARCH"
|
|
;;
|
|
esac
|
|
|
|
# Verify static binary exists - no fallbacks
|
|
if [ ! -f "$BINARY_PATH" ]; then
|
|
echo "ERROR: Static relay binary not found: $BINARY_PATH"
|
|
echo ""
|
|
echo "The relay requires the static binary with JSON1 support."
|
|
echo "Please run: ./build_static.sh"
|
|
echo ""
|
|
exit 1
|
|
fi
|
|
|
|
echo "Using static binary: $BINARY_PATH"
|
|
|
|
echo "Build successful. Proceeding with relay restart..."
|
|
|
|
# Kill existing relay if running - start aggressive immediately
|
|
echo "Stopping any existing relay servers..."
|
|
|
|
# Get all relay processes and kill them immediately with -9
|
|
RELAY_PIDS=$(pgrep -f "c_relay_" || echo "")
|
|
if [ -n "$RELAY_PIDS" ]; then
|
|
echo "Force killing relay processes immediately: $RELAY_PIDS"
|
|
kill -9 $RELAY_PIDS 2>/dev/null
|
|
else
|
|
echo "No existing relay processes found"
|
|
fi
|
|
|
|
# Ensure port 8888 is completely free with retry loop
|
|
echo "Ensuring port 8888 is available..."
|
|
for attempt in {1..15}; do
|
|
if ! lsof -i :8888 >/dev/null 2>&1; then
|
|
echo "Port 8888 is now free"
|
|
break
|
|
fi
|
|
|
|
echo "Attempt $attempt: Port 8888 still in use, force killing..."
|
|
# Kill anything using port 8888
|
|
fuser -k 8888/tcp 2>/dev/null || true
|
|
|
|
# Double-check for any remaining relay processes
|
|
REMAINING_PIDS=$(pgrep -f "c_relay_" || echo "")
|
|
if [ -n "$REMAINING_PIDS" ]; then
|
|
echo "Killing remaining relay processes: $REMAINING_PIDS"
|
|
kill -9 $REMAINING_PIDS 2>/dev/null || true
|
|
fi
|
|
|
|
sleep 2
|
|
|
|
if [ $attempt -eq 15 ]; then
|
|
echo "ERROR: Could not free port 8888 after 15 attempts"
|
|
echo "Current processes using port:"
|
|
lsof -i :8888 2>/dev/null || echo "No process details available"
|
|
echo "You may need to manually kill processes or reboot"
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
# Final safety check - ensure no relay processes remain
|
|
FINAL_PIDS=$(pgrep -f "c_relay_" || echo "")
|
|
if [ -n "$FINAL_PIDS" ]; then
|
|
echo "Final cleanup: killing processes $FINAL_PIDS"
|
|
kill -9 $FINAL_PIDS 2>/dev/null || true
|
|
sleep 1
|
|
fi
|
|
|
|
# Clean up PID file
|
|
rm -f relay.pid
|
|
|
|
# Database initialization is now handled automatically by the relay
|
|
# with event-based configuration system
|
|
echo "Database will be initialized automatically on startup if needed"
|
|
|
|
# Start relay in background with output redirection
|
|
echo "Starting relay server..."
|
|
echo "Debug: Current processes: $(ps aux | grep 'c_relay_' | grep -v grep || echo 'None')"
|
|
|
|
# Build command line arguments for relay binary
|
|
RELAY_ARGS=""
|
|
|
|
if [ -n "$ADMIN_KEY" ]; then
|
|
RELAY_ARGS="$RELAY_ARGS -a $ADMIN_KEY"
|
|
echo "Using custom admin key: ${ADMIN_KEY:0:16}..."
|
|
fi
|
|
|
|
if [ -n "$RELAY_KEY" ]; then
|
|
RELAY_ARGS="$RELAY_ARGS -r $RELAY_KEY"
|
|
echo "Using custom relay key: ${RELAY_KEY:0:16}..."
|
|
fi
|
|
|
|
if [ -n "$PORT_OVERRIDE" ]; then
|
|
RELAY_ARGS="$RELAY_ARGS -p $PORT_OVERRIDE"
|
|
echo "Using custom port: $PORT_OVERRIDE"
|
|
fi
|
|
|
|
# Change to build directory before starting relay so database files are created there
|
|
cd build
|
|
# Start relay in background and capture its PID
|
|
if [ "$USE_TEST_KEYS" = true ]; then
|
|
echo "Using deterministic test keys for development..."
|
|
./$(basename $BINARY_PATH) -a 6a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3 -r 1111111111111111111111111111111111111111111111111111111111111111 --strict-port > ../relay.log 2>&1 &
|
|
elif [ -n "$RELAY_ARGS" ]; then
|
|
echo "Starting relay with custom configuration..."
|
|
./$(basename $BINARY_PATH) $RELAY_ARGS --strict-port > ../relay.log 2>&1 &
|
|
else
|
|
# No command line arguments needed for random key generation
|
|
echo "Starting relay with random key generation..."
|
|
./$(basename $BINARY_PATH) --strict-port > ../relay.log 2>&1 &
|
|
fi
|
|
RELAY_PID=$!
|
|
# Change back to original directory
|
|
cd ..
|
|
|
|
echo "Started with PID: $RELAY_PID"
|
|
|
|
# Check if server is still running after short delay
|
|
sleep 3
|
|
|
|
# Check if process is still alive
|
|
if ps -p "$RELAY_PID" >/dev/null 2>&1; then
|
|
echo "Relay started successfully!"
|
|
echo "PID: $RELAY_PID"
|
|
|
|
# Wait for relay to fully initialize and detect the actual port it's using
|
|
sleep 2
|
|
|
|
# Extract actual port from relay logs
|
|
ACTUAL_PORT=""
|
|
if [ -f relay.log ]; then
|
|
# Look for the success message with actual port
|
|
ACTUAL_PORT=$(grep "WebSocket relay started on ws://127.0.0.1:" relay.log 2>/dev/null | tail -1 | sed -n 's/.*ws:\/\/127\.0\.0\.1:\([0-9]*\).*/\1/p')
|
|
|
|
# If we couldn't find the port in logs, try to detect from netstat
|
|
if [ -z "$ACTUAL_PORT" ]; then
|
|
ACTUAL_PORT=$(netstat -tln 2>/dev/null | grep -E ":888[0-9]" | head -1 | sed -n 's/.*:\([0-9]*\).*/\1/p')
|
|
fi
|
|
fi
|
|
|
|
# Display the actual endpoint
|
|
if [ -n "$ACTUAL_PORT" ]; then
|
|
if [ "$ACTUAL_PORT" = "8888" ]; then
|
|
echo "WebSocket endpoint: ws://127.0.0.1:$ACTUAL_PORT"
|
|
else
|
|
echo "WebSocket endpoint: ws://127.0.0.1:$ACTUAL_PORT (fell back from port 8888)"
|
|
fi
|
|
else
|
|
echo "WebSocket endpoint: ws://127.0.0.1:8888 (port detection failed - check logs)"
|
|
fi
|
|
|
|
echo "HTTP endpoint: http://127.0.0.1:${ACTUAL_PORT:-8888}"
|
|
echo "Log file: relay.log"
|
|
echo ""
|
|
|
|
# Save PID for debugging
|
|
echo $RELAY_PID > relay.pid
|
|
|
|
# Check if new keys were generated and display them
|
|
sleep 1 # Give relay time to write initial logs
|
|
if grep -q "IMPORTANT: SAVE THIS ADMIN PRIVATE KEY SECURELY!" relay.log 2>/dev/null; then
|
|
echo "=== IMPORTANT: NEW ADMIN PRIVATE KEY GENERATED ==="
|
|
echo ""
|
|
# Extract and display the admin private key section from the log
|
|
grep -A 15 -B 2 "IMPORTANT: SAVE THIS ADMIN PRIVATE KEY SECURELY!" relay.log | head -n 20
|
|
echo ""
|
|
echo "⚠️ SAVE THIS ADMIN PRIVATE KEY SECURELY - IT CONTROLS YOUR RELAY CONFIGURATION!"
|
|
echo "⚠️ This key is needed to update configuration and is only displayed once"
|
|
echo "⚠️ The relay and database information is also logged in relay.log for reference"
|
|
echo ""
|
|
fi
|
|
|
|
echo "=== Event-Based Relay Server Running ==="
|
|
echo "Configuration: Event-based (kind 33334 Nostr events)"
|
|
echo "Database: Automatically created with relay pubkey naming"
|
|
echo "To kill relay: pkill -f 'c_relay_'"
|
|
echo "To check status: ps aux | grep c_relay_"
|
|
echo "To view logs: tail -f relay.log"
|
|
echo "Binary: $BINARY_PATH (zero configuration needed)"
|
|
echo "Ready for Nostr client connections!"
|
|
else
|
|
echo "ERROR: Relay failed to start"
|
|
echo "Debug: Check relay.log for error details:"
|
|
echo "--- Last 10 lines of relay.log ---"
|
|
tail -n 10 relay.log 2>/dev/null || echo "No log file found"
|
|
echo "--- End log ---"
|
|
exit 1
|
|
fi
|
|
|
|
echo "" |