From 5b9e3887575fc9c82c3564c8b1a6271600cf2f76 Mon Sep 17 00:00:00 2001 From: 2019jack Date: Fri, 29 Aug 2025 02:56:46 +0800 Subject: [PATCH] fix:docker authentication error --- Dockerfile | 34 +++++++++- README.md | 98 ++++++++++++++++++++++++--- docker-compose.yml | 6 +- src/services/execution-api/service.ts | 6 ++ src/services/jwt/service.ts | 27 ++++++-- 5 files changed, 151 insertions(+), 20 deletions(-) diff --git a/Dockerfile b/Dockerfile index ca974f02..56710afa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,25 +1,53 @@ -FROM node:16-alpine as building +FROM --platform=linux/amd64 node:18 AS building WORKDIR /app +# Install build dependencies for native modules +RUN apt-get update && apt-get install -y \ + python3 \ + python3-dev \ + make \ + g++ \ + gcc \ + build-essential \ + && rm -rf /var/lib/apt/lists/* + +# Create python symlink for node-gyp +RUN ln -sf /usr/bin/python3 /usr/bin/python + +# Copy package files COPY package.json yarn.lock ./ COPY ts*.json ./ +COPY .nvmrc ./ +# Install dependencies RUN yarn install --frozen-lockfile --non-interactive && yarn cache clean +# Copy source code and build COPY ./src ./src COPY ./encryptor ./encryptor RUN yarn build -FROM node:16-alpine +FROM --platform=linux/amd64 node:18-slim + +# Install wget for healthcheck +RUN apt-get update && apt-get install -y wget && rm -rf /var/lib/apt/lists/* WORKDIR /app +# Copy built application COPY --from=building /app/dist ./dist COPY --from=building /app/node_modules ./node_modules COPY package.json ts*.json ./ -USER node +# Create non-root user +RUN groupadd -r appuser && useradd -r -g appuser appuser +RUN chown -R appuser:appuser /app +USER appuser + +EXPOSE 8989 + +CMD ["node", "dist/main.js"] HEALTHCHECK --interval=60s --timeout=10s --retries=3 \ CMD sh -c "wget -nv -t1 --spider http://localhost:$HTTP_PORT/health" || exit 1 diff --git a/README.md b/README.md index fd6899b2..af4a1f91 100644 --- a/README.md +++ b/README.md @@ -158,19 +158,97 @@ Available metrics: ## Troubleshooting -When you try to use Lido Validator Ejector on ARM, you may encounter an unexpected -problem related to the inability to install @chainsafe/blst dependencies under darwin arm64. +### Installation Issues -### Why does it happen?! +#### Node.js Version Compatibility -It happens because https://www.npmjs.com/package/@chainsafe/blst doesn't provide native C binding to https://github.com/supranational/blst under darwin arm64. -Such as there no native binding, a user has to compile C binding to blst lab manually for darwin arm64. -@chainsafe/blst has compile option but inside itself for downloading dependencies this lib uses Python language. -Historically MacOs uses alias python3 for python. So then @chainsafe/blst fails with an error that it could not install all dependencies. -To fix it on MacOs just create alias python for python3. +The project requires Node.js v18. If you encounter build errors with @chainsafe/blst or other native modules: ```bash -ln -s /opt/homebrew/bin/python3 /usr/local/bin/python +# Check your Node.js version +node --version + +# If using Node.js v24 or higher, switch to v18 +nvm install 18 +nvm use 18 + +# Clear caches and reinstall +yarn cache clean +rm -rf node_modules yarn.lock +yarn install +``` + +#### macOS Setup + +When you try to use Lido Validator Ejector on ARM Mac, you may encounter problems with @chainsafe/blst dependencies. + +**Python Command Not Found:** +```bash +# Create python symlink (required for node-gyp) +sudo ln -s /opt/homebrew/bin/python3 /usr/local/bin/python +# Or alternatively: +sudo ln -s $(which python3) /usr/local/bin/python +``` + +**Build Dependencies:** +```bash +# Install Xcode command line tools +xcode-select --install + +# Install Python development headers (if using pyenv) +env PYTHON_CONFIGURE_OPTS="--enable-framework" pyenv install 3.x.x +``` + +#### Linux Setup + +**Ubuntu/Debian:** +```bash +# Install build dependencies +sudo apt-get update +sudo apt-get install -y python3 python3-dev make g++ gcc build-essential + +# Create python symlink +sudo ln -sf /usr/bin/python3 /usr/bin/python ``` -More info here - https://github.com/ChainSafe/lodestar/issues/4767#issuecomment-1640631566 +**CentOS/RHEL:** +```bash +# Install build dependencies +sudo yum install -y python3 python3-devel make gcc gcc-c++ + +# Create python symlink +sudo ln -sf /usr/bin/python3 /usr/bin/python +``` + +### Docker Issues + +#### Platform Architecture Mismatch + +If you see "exec format error" on Linux servers: + +```bash +# Build for correct platform +docker build --platform linux/amd64 -t validator-ejector . + +``` + +#### Network Connection Issues + +If the container cannot connect to `127.0.0.1:8545`: + +1. **Use host networking** (recommended for localhost services): + ```yaml + # In docker-compose.yml + services: + app: + network_mode: host + ``` + +2. **Use server IP instead** of localhost: + ```bash + # In .env file + EXECUTION_NODE=http://YOUR_SERVER_IP:8545 + CONSENSUS_NODE=http://YOUR_SERVER_IP:5052 + ``` + +More info: https://github.com/ChainSafe/lodestar/issues/4767#issuecomment-1640631566 diff --git a/docker-compose.yml b/docker-compose.yml index 7a389996..6d63a1ca 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,12 +2,14 @@ version: '3.7' services: app: # get last hash from https://docs.lido.fi/guides/tooling#validator-ejector - image: lidofinance/validator-ejector@ + image: 2020jack/validator-ejector:v1.9.1 container_name: validator-ejector restart: unless-stopped + network_mode: host environment: - EXECUTION_NODE=${EXECUTION_NODE} - CONSENSUS_NODE=${CONSENSUS_NODE} + - JWT_SECRET_PATH=${JWT_SECRET_PATH} - LOCATOR_ADDRESS=${LOCATOR_ADDRESS} - STAKING_MODULE_ID=${STAKING_MODULE_ID} - OPERATOR_ID=${OPERATOR_ID} @@ -32,3 +34,5 @@ services: - '${HTTP_PORT}:${HTTP_PORT}' volumes: - ./messages:/app/messages + - ${JWT_SECRET_PATH}:${JWT_SECRET_PATH}:ro + diff --git a/src/services/execution-api/service.ts b/src/services/execution-api/service.ts index 4e75cefb..9486f320 100644 --- a/src/services/execution-api/service.ts +++ b/src/services/execution-api/service.ts @@ -39,6 +39,12 @@ export const makeExecutionApi = ( const token = jwtService.generateToken() if (token) { headers['Authorization'] = `Bearer ${token}` + logger.debug('JWT token added to request headers') + } else { + logger.warn('JWT service failed to generate token, proceeding without authentication') + } + } else if (JWT_SECRET_PATH) { + logger.warn('JWT_SECRET_PATH configured but jwtService not initialized') } } diff --git a/src/services/jwt/service.ts b/src/services/jwt/service.ts index a0a198b9..eb8bb6ce 100644 --- a/src/services/jwt/service.ts +++ b/src/services/jwt/service.ts @@ -23,8 +23,16 @@ export const makeJwtService = ( // Read hex format secret const hexSecret = await fs.readFile(JWT_SECRET_PATH, 'utf8') + const cleanHexSecret = hexSecret.trim().replace(/^0x/, '') + + // Validate hex format + if (!/^[0-9a-fA-F]+$/.test(cleanHexSecret)) { + throw new Error(`Invalid hex format in JWT secret file: ${JWT_SECRET_PATH}`) + } + // Convert hex to buffer - secretBuffer = Buffer.from(hexSecret.trim(), 'hex') + secretBuffer = Buffer.from(cleanHexSecret, 'hex') + logger.debug(`JWT secret loaded: ${cleanHexSecret.length} hex characters, ${secretBuffer.length} bytes`) logger.info('JWT secret loaded successfully') return true @@ -42,11 +50,18 @@ export const makeJwtService = ( logger.warn('JWT secret not initialized, unable to generate token') return null } - - // Create payload with current timestamp - const payload = { iat: Math.floor(Date.now() / 1000) } - // Sign using buffer - return jwt.sign(payload, secretBuffer, { algorithm: 'HS256' }) + + try { + // Create payload with current timestamp + const payload = { iat: Math.floor(Date.now() / 1000) } + // Sign using buffer + const token = jwt.sign(payload, secretBuffer, { algorithm: 'HS256' }) + logger.debug('JWT token generated successfully') + return token + } catch (error) { + logger.error('Failed to generate JWT token', error) + return null + } } return {