--- apiVersion: v1 kind: ConfigMap metadata: name: pasarguard-scripts labels: app: pasarguard-node data: init-uuid.sh: | #!/bin/bash set -e echo "Started" # NODE_NAME is already set via environment variable NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace) # Get DNS name from node label xray-node-address DNS_NAME=$(kubectl get node "${NODE_NAME}" -o jsonpath='{.metadata.labels.xray-node-address}') if [ -z "${DNS_NAME}" ]; then echo "ERROR: Node ${NODE_NAME} does not have label 'xray-node-address'" exit 1 fi echo "Node: ${NODE_NAME}" echo "DNS Name from label: ${DNS_NAME}" # Use DNS name for ConfigMap name to ensure uniqueness CONFIGMAP_NAME="node-uuid-${DNS_NAME//./-}" echo "Checking ConfigMap: ${CONFIGMAP_NAME}" # Check if ConfigMap exists and get UUID if kubectl get configmap "${CONFIGMAP_NAME}" -n "${NAMESPACE}" &>/dev/null; then echo "ConfigMap exists, reading UUID..." API_KEY=$(kubectl get configmap "${CONFIGMAP_NAME}" -n "${NAMESPACE}" -o jsonpath='{.data.API_KEY}') if [ -z "${API_KEY}" ]; then echo "UUID not found in ConfigMap, generating new one..." API_KEY=$(cat /proc/sys/kernel/random/uuid) kubectl patch configmap "${CONFIGMAP_NAME}" -n "${NAMESPACE}" --type merge -p "{\"data\":{\"API_KEY\":\"${API_KEY}\"}}" else echo "Using existing UUID from ConfigMap" fi else echo "ConfigMap does not exist, creating new one..." API_KEY=$(cat /proc/sys/kernel/random/uuid) kubectl create configmap "${CONFIGMAP_NAME}" -n "${NAMESPACE}" \ --from-literal=API_KEY="${API_KEY}" \ --from-literal=NODE_NAME="${NODE_NAME}" fi # Save UUID and node info to shared volume for the main container echo -n "${API_KEY}" > /shared/api-key echo -n "${NODE_NAME}" > /shared/node-name echo -n "${CONFIGMAP_NAME}" > /shared/configmap-name echo "UUID initialized: ${API_KEY}" echo "Node name: ${NODE_NAME}" echo "ConfigMap: ${CONFIGMAP_NAME}" # Create Certificate for this node using DNS name from label CERT_NAME="pasarguard-node-${DNS_NAME//./-}" echo "Creating Certificate: ${CERT_NAME} for ${DNS_NAME}" # Check if Certificate already exists if ! kubectl get certificate "${CERT_NAME}" -n "${NAMESPACE}" &>/dev/null; then echo "Certificate does not exist, creating..." cat </dev/null; then echo "Certificate secret is ready!" break fi echo "Waiting for certificate... ($i/600)" sleep 1 done if ! kubectl get secret "${CERT_NAME}-tls" -n "${NAMESPACE}" &>/dev/null; then echo "WARNING: Certificate secret not ready after 600 seconds" else # Extract certificate and key from secret to shared volume echo "Extracting certificate and key..." kubectl get secret "${CERT_NAME}-tls" -n "${NAMESPACE}" -o jsonpath='{.data.tls\.crt}' | base64 -d > /shared/tls.crt kubectl get secret "${CERT_NAME}-tls" -n "${NAMESPACE}" -o jsonpath='{.data.tls\.key}' | base64 -d > /shared/tls.key echo "Certificate and key extracted successfully." cat /shared/tls.crt fi # Create individual Service and Endpoints for this node # Take only first part of node name before first dot NODE_SHORT_NAME="${NODE_NAME%%.*}" SERVICE_NAME="${NODE_SHORT_NAME}" # Get node internal IP (take only first IP if multiple) NODE_IP=$(kubectl get node "${NODE_NAME}" -o jsonpath='{.status.addresses[?(@.type=="InternalIP")].address}' | awk '{print $1}') echo "Creating Service: ${SERVICE_NAME} for node ${NODE_NAME} (short: ${NODE_SHORT_NAME}) with IP ${NODE_IP}" # Create Service without selector cat < ${NODE_IP}:62050" exporter-start.sh: | #!/bin/sh # Install required tools apk add --no-cache wget curl iproute2-ss bash # Download v2ray-exporter echo "Downloading v2ray-exporter..." ARCH=$(uname -m) case $ARCH in x86_64) BINARY_ARCH="amd64" ;; aarch64|arm64) BINARY_ARCH="arm64" ;; *) echo "Unsupported architecture: $ARCH" exit 1 ;; esac echo "Detected architecture: $ARCH, using binary: v2ray-exporter_linux_$BINARY_ARCH" wget -L -O /tmp/v2ray-exporter "https://github.com/wi1dcard/v2ray-exporter/releases/download/v0.6.0/v2ray-exporter_linux_$BINARY_ARCH" mv /tmp/v2ray-exporter /usr/local/bin/v2ray-exporter chmod +x /usr/local/bin/v2ray-exporter # Wait for initial API port file echo "Waiting for initial xray API port file..." while [ ! -f /shared/xray-api-port ]; do echo "Waiting for API port file..." sleep 2 done # Main loop - restart exporter if it crashes or port changes while true; do if [ -f /shared/xray-api-port ]; then API_PORT=$(cat /shared/xray-api-port) if [ -n "$API_PORT" ]; then echo "Starting v2ray-exporter with endpoint 127.0.0.1:$API_PORT" /usr/local/bin/v2ray-exporter --v2ray-endpoint "127.0.0.1:$API_PORT" --listen ":9550" & EXPORTER_PID=$! # Wait for exporter to exit or port file to change while kill -0 $EXPORTER_PID 2>/dev/null; do if [ -f /shared/xray-api-port ]; then NEW_PORT=$(cat /shared/xray-api-port) if [ "$NEW_PORT" != "$API_PORT" ]; then echo "API port changed from $API_PORT to $NEW_PORT, restarting exporter" kill $EXPORTER_PID 2>/dev/null wait $EXPORTER_PID 2>/dev/null break fi fi sleep 5 done echo "Exporter stopped, restarting..." wait $EXPORTER_PID 2>/dev/null fi fi sleep 2 done pasarguard-start.sh: | #!/bin/sh # Read API_KEY from shared volume created by init container if [ -f /shared/api-key ]; then export API_KEY=$(cat /shared/api-key) echo "Loaded API_KEY from shared volume" else echo "WARNING: API_KEY file not found, using default" fi cd /app # Start main process in background ./main & MAIN_PID=$! # Start continuous port monitoring in background { sleep 10 # Wait for xray to start initially LAST_PORT="" while true; do API_PORT=$(netstat -tlpn | grep xray | grep 127.0.0.1 | awk '{print $4}' | cut -d: -f2 | head -1) if [ -n "$API_PORT" ] && [ "$API_PORT" != "$LAST_PORT" ]; then echo "Found xray API port: $API_PORT" echo -n "$API_PORT" > /shared/xray-api-port LAST_PORT="$API_PORT" fi sleep 5 # Check every 5 seconds done } & PORT_MONITOR_PID=$! # Wait for main process to finish wait $MAIN_PID # Clean up port monitor kill $PORT_MONITOR_PID 2>/dev/null