localnet: wire otel

This commit is contained in:
Tommy Verrall
2026-02-16 13:46:23 +01:00
parent 40a3cd28b7
commit 597aae1a20
3 changed files with 99 additions and 69 deletions
+3 -4
View File
@@ -10,10 +10,9 @@ COPY ./ ./
ENV CARGO_BUILD_JOBS=8
# Build all required binaries in release mode
RUN cargo build --release --locked \
-p nym-node \
-p nym-network-requester \
-p nym-socks5-client
# nym-node is built with the otel feature for OpenTelemetry tracing support
RUN cargo build --release --locked -p nym-node --features otel && \
cargo build --release --locked -p nym-network-requester -p nym-socks5-client
# Install runtime dependencies including Go for wireguard-go
RUN apt update && apt install -y \
+14 -7
View File
@@ -5,6 +5,13 @@
SESSION_NAME="nym-localnet-logs"
# Detect runtime
if command -v container &> /dev/null; then
RUNTIME="container"
else
RUNTIME="docker"
fi
# Container names
CONTAINERS=(
"nym-mixnode1"
@@ -17,9 +24,9 @@ CONTAINERS=(
# Check if containers are running
running_containers=()
for container in "${CONTAINERS[@]}"; do
if container inspect "$container" &>/dev/null; then
running_containers+=("$container")
for ctr in "${CONTAINERS[@]}"; do
if $RUNTIME inspect "$ctr" &>/dev/null; then
running_containers+=("$ctr")
fi
done
@@ -32,11 +39,11 @@ fi
# Check if we're already in tmux
if [ -n "$TMUX" ]; then
# Inside tmux - create new window
tmux new-window -n "logs" "container logs -f ${running_containers[0]}"
tmux new-window -n "logs" "$RUNTIME logs -f ${running_containers[0]}"
# Split for remaining containers
for ((i=1; i<${#running_containers[@]}; i++)); do
tmux split-window -t logs "container logs -f ${running_containers[$i]}"
tmux split-window -t logs "$RUNTIME logs -f ${running_containers[$i]}"
tmux select-layout -t logs tiled
done
@@ -48,11 +55,11 @@ else
exec tmux attach-session -t "$SESSION_NAME"
else
# Create new session
tmux new-session -d -s "$SESSION_NAME" -n "logs" "container logs -f ${running_containers[0]}"
tmux new-session -d -s "$SESSION_NAME" -n "logs" "$RUNTIME logs -f ${running_containers[0]}"
# Split for remaining containers
for ((i=1; i<${#running_containers[@]}; i++)); do
tmux split-window -t "$SESSION_NAME:logs" "container logs -f ${running_containers[$i]}"
tmux split-window -t "$SESSION_NAME:logs" "$RUNTIME logs -f ${running_containers[$i]}"
tmux select-layout -t "$SESSION_NAME:logs" tiled
done
+82 -58
View File
@@ -2,8 +2,8 @@
set -ex
# Nym Localnet Orchestration Script for Apple Container Runtime
# Emulates docker-compose functionality
# Nym Localnet Orchestration Script
# Supports both Docker and Apple Container Runtime
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
@@ -14,6 +14,28 @@ NYM_VOLUME_PATH="/tmp/nym-localnet-home-$$"
SUFFIX=${NYM_NODE_SUFFIX:-localnet}
# Detect container runtime: prefer Apple 'container' if available, fall back to docker
if command -v container &> /dev/null; then
RUNTIME="container"
HOST_INTERNAL="host.containers.internal"
else
RUNTIME="docker"
HOST_INTERNAL="host.docker.internal"
fi
# OpenTelemetry configuration
# Set OTEL_ENABLE=1 to enable OTel tracing on all nym-node instances.
# OTEL_ENDPOINT should point to the OTLP gRPC collector reachable from containers.
OTEL_ENABLE=${OTEL_ENABLE:-1}
OTEL_ENDPOINT=${OTEL_ENDPOINT:-"http://${HOST_INTERNAL}:4317"}
# Build OTel flags for nym-node run commands
otel_flags() {
if [ "$OTEL_ENABLE" = "1" ]; then
echo "--otel --otel-endpoint $OTEL_ENDPOINT"
fi
}
# Container names
INIT_CONTAINER="nym-localnet-init"
MIXNODE1_CONTAINER="nym-mixnode1"
@@ -64,13 +86,13 @@ cleanup_host_state() {
done
}
# Check if container command exists
# Check prerequisites
check_prerequisites() {
if ! command -v container &> /dev/null; then
log_error "Apple 'container' command not found"
log_error "Install from: https://github.com/apple/container"
if ! command -v docker &> /dev/null; then
log_error "Docker not found"
exit 1
fi
log_info "Using runtime: $RUNTIME"
}
# Build the Docker image
@@ -80,7 +102,6 @@ build_image() {
cd "$PROJECT_ROOT"
# Build with Docker
log_info "Building with Docker..."
if ! docker build \
-f "$SCRIPT_DIR/Dockerfile.localnet" \
@@ -90,30 +111,24 @@ build_image() {
exit 1
fi
# Transfer image to container runtime
log_info "Transferring image to container runtime..."
# Save to temporary file (container image load doesn't support stdin)
TEMP_IMAGE="/tmp/nym-localnet-image-$$.tar"
if ! docker save -o "$TEMP_IMAGE" "$IMAGE_NAME"; then
log_error "Failed to save Docker image"
exit 1
fi
# Load into container runtime from file
if ! container image load --input "$TEMP_IMAGE"; then
# If using Apple container runtime, transfer image from Docker
if [ "$RUNTIME" = "container" ]; then
log_info "Transferring image to Apple container runtime..."
TEMP_IMAGE="/tmp/nym-localnet-image-$$.tar"
if ! docker save -o "$TEMP_IMAGE" "$IMAGE_NAME"; then
log_error "Failed to save Docker image"
exit 1
fi
if ! container image load --input "$TEMP_IMAGE"; then
rm -f "$TEMP_IMAGE"
log_error "Failed to load image into container runtime"
exit 1
fi
rm -f "$TEMP_IMAGE"
log_error "Failed to load image into container runtime"
exit 1
fi
# Clean up temporary file
rm -f "$TEMP_IMAGE"
# Verify image is available
if ! container image inspect "$IMAGE_NAME" &>/dev/null; then
log_error "Image not found in container runtime after load"
exit 1
if ! container image inspect "$IMAGE_NAME" &>/dev/null; then
log_error "Image not found in container runtime after load"
exit 1
fi
fi
log_success "Image built and loaded: $IMAGE_NAME"
@@ -155,7 +170,7 @@ NETWORK_NAME="nym-localnet-network"
# Create container network
create_network() {
log_info "Creating container network: $NETWORK_NAME"
if container network create "$NETWORK_NAME" 2>/dev/null; then
if $RUNTIME network create "$NETWORK_NAME" 2>/dev/null; then
log_success "Network created: $NETWORK_NAME"
else
log_info "Network $NETWORK_NAME already exists or creation failed"
@@ -164,9 +179,9 @@ create_network() {
# Remove container network
remove_network() {
if container network list | grep -q "$NETWORK_NAME"; then
if $RUNTIME network list | grep -q "$NETWORK_NAME"; then
log_info "Removing network: $NETWORK_NAME"
container network rm "$NETWORK_NAME" 2>/dev/null || true
$RUNTIME network rm "$NETWORK_NAME" 2>/dev/null || true
log_success "Network removed"
fi
}
@@ -183,7 +198,10 @@ start_mixnode() {
local verloc_port="2000${node_id}"
local http_port="3000${node_id}"
container run \
local otel_args
otel_args=$(otel_flags)
$RUNTIME run \
--name "$container_name" \
-m 2G \
--network "$NETWORK_NAME" \
@@ -215,7 +233,7 @@ start_mixnode() {
sleep 2;
done;
echo "Starting mix'"${node_id}"'...";
exec nym-node run --id mix'"${node_id}"'-localnet --unsafe-disable-replay-protection --local
exec nym-node '"${otel_args}"' run --id mix'"${node_id}"'-localnet --unsafe-disable-replay-protection --local
'
log_success "$container_name started"
@@ -224,7 +242,10 @@ start_mixnode() {
start_gateway() {
log_info "Starting $GATEWAY_CONTAINER..."
container run \
local otel_args
otel_args=$(otel_flags)
$RUNTIME run \
--name "$GATEWAY_CONTAINER" \
-m 2G \
--network "$NETWORK_NAME" \
@@ -267,7 +288,7 @@ start_gateway() {
sleep 2;
done;
echo "Starting gateway with LP listener (mock ecash)...";
exec nym-node run --id gateway-localnet --unsafe-disable-replay-protection --local --wireguard-enabled true --wireguard-userspace true --lp-use-mock-ecash true
exec nym-node '"${otel_args}"' run --id gateway-localnet --unsafe-disable-replay-protection --local --wireguard-enabled true --wireguard-userspace true --lp-use-mock-ecash true
'
log_success "$GATEWAY_CONTAINER started"
@@ -291,7 +312,10 @@ start_gateway() {
start_gateway2() {
log_info "Starting $GATEWAY2_CONTAINER..."
container run \
local otel_args
otel_args=$(otel_flags)
$RUNTIME run \
--name "$GATEWAY2_CONTAINER" \
-m 2G \
--network "$NETWORK_NAME" \
@@ -334,7 +358,7 @@ start_gateway2() {
sleep 2;
done;
echo "Starting gateway2 with LP listener (mock ecash)...";
exec nym-node run --id gateway2-localnet --unsafe-disable-replay-protection --local --wireguard-enabled true --wireguard-userspace true --lp-use-mock-ecash true
exec nym-node '"${otel_args}"' run --id gateway2-localnet --unsafe-disable-replay-protection --local --wireguard-enabled true --wireguard-userspace true --lp-use-mock-ecash true
'
log_success "$GATEWAY2_CONTAINER started"
@@ -360,10 +384,10 @@ start_network_requester() {
# Get gateway IP address
log_info "Getting gateway IP address..."
GATEWAY_IP=$(container exec "$GATEWAY_CONTAINER" hostname -i)
GATEWAY_IP=$($RUNTIME exec "$GATEWAY_CONTAINER" hostname -i)
log_info "Gateway IP: $GATEWAY_IP"
container run \
$RUNTIME run \
--name "$REQUESTER_CONTAINER" \
--network "$NETWORK_NAME" \
-v "$VOLUME_PATH:/localnet" \
@@ -398,7 +422,7 @@ start_network_requester() {
start_socks5_client() {
log_info "Starting $SOCKS5_CONTAINER..."
container run \
$RUNTIME run \
--name "$SOCKS5_CONTAINER" \
--network "$NETWORK_NAME" \
-p 1080:1080 \
@@ -451,15 +475,15 @@ stop_containers() {
log_info "Stopping all containers..."
for container_name in "${ALL_CONTAINERS[@]}"; do
if container inspect "$container_name" &>/dev/null; then
if $RUNTIME inspect "$container_name" &>/dev/null; then
log_info "Stopping $container_name"
container stop "$container_name" 2>/dev/null || true
container rm "$container_name" 2>/dev/null || true
$RUNTIME stop "$container_name" 2>/dev/null || true
$RUNTIME rm "$container_name" 2>/dev/null || true
fi
done
# Also clean up init container if it exists
container rm "$INIT_CONTAINER" 2>/dev/null || true
$RUNTIME rm "$INIT_CONTAINER" 2>/dev/null || true
log_success "All containers stopped"
@@ -467,7 +491,7 @@ stop_containers() {
remove_network
}
# Show container logs
# Show $RUNTIME logs
show_logs() {
local container_name=${1:-}
@@ -478,8 +502,8 @@ show_logs() {
fi
# Show logs for specific container
if container inspect "$container_name" &>/dev/null; then
container logs -f "$container_name"
if $RUNTIME inspect "$container_name" &>/dev/null; then
$RUNTIME logs -f "$container_name"
else
log_error "Container not found: $container_name"
log_info "Available containers:"
@@ -496,8 +520,8 @@ show_status() {
echo ""
for container_name in "${ALL_CONTAINERS[@]}"; do
if container inspect "$container_name" &>/dev/null; then
local status=$(container inspect "$container_name" 2>/dev/null | grep -o '"Status":"[^"]*"' | cut -d'"' -f4 || echo "unknown")
if $RUNTIME inspect "$container_name" &>/dev/null; then
local status=$($RUNTIME inspect "$container_name" 2>/dev/null | grep -o '"Status":"[^"]*"' | cut -d'"' -f4 || echo "unknown")
echo -e " ${GREEN}${NC} $container_name - $status"
else
echo -e " ${RED}${NC} $container_name - not running"
@@ -554,11 +578,11 @@ build_topology() {
# Get container IPs
log_info "Getting container IP addresses..."
MIX1_IP=$(container exec "$MIXNODE1_CONTAINER" hostname -i)
MIX2_IP=$(container exec "$MIXNODE2_CONTAINER" hostname -i)
MIX3_IP=$(container exec "$MIXNODE3_CONTAINER" hostname -i)
GATEWAY_IP=$(container exec "$GATEWAY_CONTAINER" hostname -i)
GATEWAY2_IP=$(container exec "$GATEWAY2_CONTAINER" hostname -i)
MIX1_IP=$($RUNTIME exec "$MIXNODE1_CONTAINER" hostname -i)
MIX2_IP=$($RUNTIME exec "$MIXNODE2_CONTAINER" hostname -i)
MIX3_IP=$($RUNTIME exec "$MIXNODE3_CONTAINER" hostname -i)
GATEWAY_IP=$($RUNTIME exec "$GATEWAY_CONTAINER" hostname -i)
GATEWAY2_IP=$($RUNTIME exec "$GATEWAY2_CONTAINER" hostname -i)
log_info "Container IPs:"
echo " mix1: $MIX1_IP"
@@ -568,7 +592,7 @@ build_topology() {
echo " gateway2: $GATEWAY2_IP"
# Run build_topology.py in a container with access to the volumes
container run \
$RUNTIME run \
--name "nym-localnet-topology-builder" \
--network "$NETWORK_NAME" \
-v "$VOLUME_PATH:/localnet" \
@@ -613,7 +637,7 @@ start_all() {
# Note: Runs after build_topology to ensure gateways have finished WireGuard setup
log_info "Configuring gateway networking (IP forwarding, NAT)..."
for gw in "$GATEWAY_CONTAINER" "$GATEWAY2_CONTAINER"; do
container exec "$gw" sh -c "
$RUNTIME exec "$gw" sh -c "
# Enable IP forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward
# Add NAT masquerade for outbound traffic