npm-registry không khả dụng - và việc xây dựng dự án đã dừng lại. Đây là tình huống quen thuộc đối với các nhà phát triển trong các mạng doanh nghiệp, các khu vực có hạn chế truy cập hoặc khi làm việc qua tường lửa nghiêm ngặt. Trong hướng dẫn này, chúng ta sẽ xem xét tất cả các cách làm việc: từ việc chuyển sang gương đến cấu hình chi tiết proxy trong .npmrc - để npm install lại hoạt động mà không có lỗi.
Tại sao npm registry bị chặn và điều gì xảy ra khi đó
Registry npm chính thức nằm ở địa chỉ https://registry.npmjs.org. Đây là một CDN toàn cầu, nhưng nó vẫn có thể không khả dụng vì nhiều lý do, và mỗi lý do yêu cầu cách tiếp cận riêng.
Các lý do chính khiến registry không khả dụng
- Tường lửa doanh nghiệp - công ty chặn các yêu cầu trực tiếp đến các kho lưu trữ bên ngoài, chỉ cho phép lưu lượng truy cập qua máy chủ proxy nội bộ. Đây là thực tiễn tiêu chuẩn trong các ngân hàng, cơ quan nhà nước, và các công ty CNTT lớn.
- Chặn địa lý hoặc hạn chế khu vực - ở một số quốc gia và khu vực, quyền truy cập vào npmjs.org bị hạn chế ở cấp độ nhà cung cấp dịch vụ Internet hoặc tường lửa của nhà nước.
- Mạng văn phòng không có quyền truy cập trực tiếp vào Internet - các máy tính làm việc trong các phân đoạn mạng bị cô lập không có quyền truy cập trực tiếp vào các tài nguyên bên ngoài, tất cả lưu lượng đi qua cổng doanh nghiệp.
- Tunnel VPN với proxy bắt buộc - VPN doanh nghiệp chuyển hướng tất cả lưu lượng, và npm không thể truy cập registry trực tiếp.
- Vấn đề với kiểm tra SSL - proxy doanh nghiệp chặn lưu lượng HTTPS và thay thế chứng chỉ, gây ra các lỗi như
SELF_SIGNED_CERT_IN_CHAINhoặcUNABLE_TO_VERIFY_LEAF_SIGNATURE.
Các lỗi thường gặp khi registry bị chặn
npm ERR! code ECONNREFUSED npm ERR! errno ECONNREFUSED npm ERR! network request to https://registry.npmjs.org/react failed npm ERR! code ETIMEDOUT npm ERR! network This is a problem related to network connectivity. npm ERR! code CERT_HAS_EXPIRED npm ERR! code SELF_SIGNED_CERT_IN_CHAIN
Mỗi mã lỗi này chỉ ra một vấn đề khác nhau: ECONNREFUSED - kết nối bị từ chối bởi tường lửa, ETIMEDOUT - yêu cầu không đi đến đâu (bị chặn mà không có phản hồi), lỗi chứng chỉ - vấn đề kiểm tra SSL. Hiểu nguyên nhân ngay lập tức thu hẹp phạm vi giải pháp.
Gương npm registry: cách nhanh chóng vượt qua mà không cần proxy
Cách đơn giản nhất để vượt qua việc chặn là chuyển npm sang gương registry thay thế. Gương chứa các gói giống như registry chính thức, nhưng nằm trên các máy chủ và miền khác nhau. Điều này hoạt động khi miền registry.npmjs.org bị chặn, chứ không phải toàn bộ lưu lượng HTTPS.
Các gương npm phổ biến
| Gương | URL | Đặc điểm |
|---|---|---|
| Taobao / npmmirror | https://registry.npmmirror.com |
Đồng bộ mỗi 10 phút, tốc độ tốt từ Châu Á |
| Gương Yarn Berry | https://registry.yarnpkg.com |
Được hỗ trợ bởi đội ngũ Yarn, tương thích với npm-client |
| Verdaccio (tự host) | http://localhost:4873 |
Registry riêng với caching, hoạt động trong các mạng bị cô lập |
| Nexus Repository | http://nexus.company.local/npm |
Giải pháp doanh nghiệp, proxy và cache các gói |
| JFrog Artifactory | https://artifactory.company.com/npm |
Cấp độ doanh nghiệp, kiểm toán phụ thuộc, kiểm soát truy cập |
Cách chuyển đổi registry
Chuyển đổi cho một lệnh (không thay đổi cài đặt toàn cầu):
# Cài đặt một lần qua registry thay thế npm install react --registry https://registry.npmmirror.com # Cài đặt toàn cầu cho người dùng hiện tại npm config set registry https://registry.npmmirror.com # Kiểm tra registry hiện tại npm config get registry # Trở lại registry chính thức npm config set registry https://registry.npmjs.org
Một điểm quan trọng: nếu bạn chuyển sang gương trong dự án với lệnh, tốt hơn hết là ghi lại điều này trong tệp .npmrc ở gốc của kho lưu trữ - thì tất cả các thành viên trong nhóm sẽ tự động nhận được cấu hình đúng khi sao chép dự án.
# .npmrc ở gốc dự án registry=https://registry.npmmirror.com
Cấu hình proxy qua .npmrc: cú pháp đầy đủ
Khi gương không giúp ích (ví dụ, toàn bộ lưu lượng HTTPS bị chặn), bạn cần chỉ định rõ ràng địa chỉ máy chủ proxy cho npm. Tệp .npmrc là tệp cấu hình chính của npm, và chính trong đó chứa các cài đặt proxy.
Vị trí của các tệp .npmrc
npm tìm kiếm cấu hình ở một số nơi - theo thứ tự ưu tiên (từ cao đến thấp):
- Dự án -
/path/to/project/.npmrc- chỉ áp dụng cho dự án này - Người dùng -
~/.npmrc- áp dụng cho người dùng hiện tại của hệ thống - Toàn cầu -
$PREFIX/etc/npmrc- áp dụng cho toàn bộ cài đặt npm - Nhúng -
/path/to/npm/npmrc- cài đặt mặc định của chính npm
Cú pháp cấu hình proxy trong .npmrc
# Proxy cho lưu lượng HTTP proxy=http://proxy.example.com:8080 # Proxy cho lưu lượng HTTPS (được sử dụng cho hầu hết các yêu cầu đến registry) https-proxy=http://proxy.example.com:8080 # Proxy với xác thực (tên đăng nhập:mật khẩu trong URL) proxy=http://username:[email protected]:8080 https-proxy=http://username:[email protected]:8080 # Các ngoại lệ - các địa chỉ vượt qua proxy noproxy=localhost,127.0.0.1,internal.company.com
⚠️ Quan trọng về HTTPS-proxy
Lưu ý: tham số https-proxy chỉ định địa chỉ máy chủ proxy mà qua đó npm sẽ thực hiện các yêu cầu HTTPS. Địa chỉ proxy có thể bắt đầu bằng http:// - điều này là bình thường. Hầu hết các proxy doanh nghiệp chấp nhận kết nối qua HTTP, nhưng có khả năng tunnel HTTPS qua phương thức CONNECT.
Cài đặt proxy qua lệnh npm config
Một lựa chọn thay thế cho việc chỉnh sửa tệp thủ công là sử dụng lệnh npm config set. Nó sẽ tự động ghi các cài đặt vào ~/.npmrc:
# Cài đặt proxy npm config set proxy http://proxy.example.com:8080 npm config set https-proxy http://proxy.example.com:8080 # Kiểm tra cài đặt proxy hiện tại npm config get proxy npm config get https-proxy # Xóa cài đặt proxy (trở lại kết nối trực tiếp) npm config delete proxy npm config delete https-proxy # Xem toàn bộ cấu hình npm npm config list
Proxy qua biến môi trường cho npm
npm tự động đọc các biến môi trường hệ thống tiêu chuẩn cho proxy. Điều này rất tiện lợi trong các pipeline CI/CD, các container Docker và các hệ thống mà cấu hình được đặt ở cấp độ môi trường, không phải tệp.
Các biến môi trường tiêu chuẩn
# Linux / macOS - cài đặt trong phiên hiện tại export HTTP_PROXY=http://proxy.example.com:8080 export HTTPS_PROXY=http://proxy.example.com:8080 export NO_PROXY=localhost,127.0.0.1 # Các biến chữ thường (npm hiểu cả hai) export http_proxy=http://proxy.example.com:8080 export https_proxy=http://proxy.example.com:8080 # Windows (Command Prompt) set HTTP_PROXY=http://proxy.example.com:8080 set HTTPS_PROXY=http://proxy.example.com:8080 # Windows (PowerShell) $env:HTTP_PROXY = "http://proxy.example.com:8080" $env:HTTPS_PROXY = "http://proxy.example.com:8080"
Ưu tiên cấu hình npm
Quan trọng là hiểu rằng npm sử dụng ưu tiên sau để xác định proxy (từ cao đến thấp):
- Các cờ dòng lệnh:
--proxy http://... - Các biến môi trường với tiền tố
npm_config_: ví dụ,npm_config_proxy - Tệp dự án
.npmrc - Tệp người dùng
~/.npmrc - Tệp toàn cầu
$PREFIX/etc/npmrc - Các biến môi trường tiêu chuẩn
HTTP_PROXY/HTTPS_PROXY
Nếu proxy được cấu hình trong .npmrc, nhưng biến môi trường chỉ định một địa chỉ khác - .npmrc sẽ thắng. Đây là nguyên nhân thường gặp gây nhầm lẫn trong các hệ thống CI/CD.
Cấu hình trong CI/CD (GitHub Actions, GitLab CI)
# GitHub Actions - thêm vào phần env của job hoặc step
jobs:
build:
runs-on: ubuntu-latest
env:
HTTP_PROXY: http://proxy.example.com:8080
HTTPS_PROXY: http://proxy.example.com:8080
NO_PROXY: localhost,127.0.0.1
steps:
- uses: actions/checkout@v3
- run: npm install
# GitLab CI - trong các biến của dự án hoặc trong .gitlab-ci.yml
variables:
HTTP_PROXY: "http://proxy.example.com:8080"
HTTPS_PROXY: "http://proxy.example.com:8080"
Proxy doanh nghiệp với xác thực và kiểm tra SSL
Các máy chủ proxy doanh nghiệp là trường hợp phức tạp nhất. Chúng không chỉ chuyển hướng lưu lượng mà còn yêu cầu xác thực, và thường thực hiện kiểm tra SSL (chặn và giải mã lưu lượng HTTPS). Điều này gây ra các lỗi chứng chỉ đặc thù mà npm không thể xử lý ngay từ đầu.
Proxy với xác thực NTLM/Basic
Nếu proxy doanh nghiệp yêu cầu tên đăng nhập và mật khẩu (Basic Auth), bạn có thể truyền chúng trực tiếp trong URL. Tuy nhiên, với xác thực NTLM (miền Windows), mọi thứ phức tạp hơn - npm không hỗ trợ NTLM một cách tự nhiên. Trong trường hợp này, bạn cần sử dụng một công cụ trung gian.
# Basic Auth - tên đăng nhập và mật khẩu trong URL npm config set proxy http://user:[email protected]:8080 npm config set https-proxy http://user:[email protected]:8080 # Nếu mật khẩu chứa ký tự đặc biệt - cần mã hóa URL # @ → %40, # → %23, : → %3A # Ví dụ: mật khẩu "p@ss#word" → "p%40ss%23word" npm config set proxy http://user:p%40ss%[email protected]:8080
Đối với xác thực NTLM, bạn sử dụng tiện ích cntlm - nó chạy cục bộ, nhận các yêu cầu HTTP thông thường và tự thực hiện NTLM handshake với proxy doanh nghiệp. Đối với npm, điều này trông giống như một proxy thông thường không cần xác thực:
# Sau khi cấu hình cntlm, nó lắng nghe trên localhost:3128 npm config set proxy http://localhost:3128 npm config set https-proxy http://localhost:3128
Giải quyết vấn đề kiểm tra SSL
Các proxy doanh nghiệp với kiểm tra SSL thay thế chứng chỉ của các trang web bằng chứng chỉ doanh nghiệp của họ. npm kiểm tra chuỗi tin cậy và từ chối các chứng chỉ như vậy. Có ba cách tiếp cận:
Cách 1 (được khuyến nghị): thêm chứng chỉ CA doanh nghiệp vào danh sách tin cậy
# Nhận chứng chỉ doanh nghiệp từ bộ phận IT (tệp .crt hoặc .pem) # Chỉ định nó trong cấu hình npm npm config set cafile /path/to/corporate-ca.crt # Hoặc thêm nhiều chứng chỉ qua cafile # Có thể kết hợp nhiều CA vào một tệp PEM
Cách 2 (tạm thời, không an toàn): tắt kiểm tra SSL
# Chỉ sử dụng như một giải pháp tạm thời để chẩn đoán! npm config set strict-ssl false # Hoặc cho một lệnh npm install --legacy-peer-deps --no-strict-ssl
⚠️ Cảnh báo bảo mật
Tham số strict-ssl false tắt hoàn toàn kiểm tra chứng chỉ SSL. Điều này làm cho kết nối dễ bị tấn công kiểu MITM. Chỉ sử dụng cách này cho việc chẩn đoán, không trong môi trường production và không trên cơ sở lâu dài. Giải pháp đúng là thêm chứng chỉ CA doanh nghiệp qua cafile.
Proxy SOCKS5 cho npm: cấu hình qua các tiện ích trợ giúp
npm chỉ hỗ trợ natively các proxy HTTP/HTTPS. Nếu bạn có proxy SOCKS5 (ví dụ, từ nhà cung cấp proxy dân cư), bạn không thể chỉ định trực tiếp trong cấu hình npm. Cần một lớp trung gian - một tiện ích nhận các yêu cầu HTTP từ npm và chuyển hướng chúng qua SOCKS5.
Cách 1: proxychains (Linux/macOS)
# Cài đặt proxychains # Ubuntu/Debian: sudo apt-get install proxychains4 # macOS: brew install proxychains-ng # Cấu hình /etc/proxychains4.conf [ProxyList] socks5 proxy.example.com 1080 username password # Chạy npm qua proxychains proxychains4 npm install
Cách 2: chuyển đổi HTTP sang SOCKS5 cục bộ
Tiện ích privoxy hoặc polipo tạo ra một proxy HTTP cục bộ, tunnel lưu lượng qua SOCKS5. Sau khi khởi động, npm sẽ thấy một proxy HTTP thông thường trên localhost:
# Cài đặt privoxy sudo apt-get install privoxy # Ubuntu/Debian brew install privoxy # macOS # Thêm vào cấu hình /etc/privoxy/config: forward-socks5 / proxy.example.com:1080 . # Privoxy lắng nghe trên localhost:8118 theo mặc định # Chỉ định npm sử dụng địa chỉ này: npm config set proxy http://localhost:8118 npm config set https-proxy http://localhost:8118
Cách 3: Tunneling SSH như một proxy SOCKS5
Nếu bạn có quyền truy cập vào một máy chủ từ xa với Internet mở, bạn có thể tạo một tunnel SOCKS5 SSH và chuyển hướng lưu lượng npm qua đó. Điều này đặc biệt tiện lợi khi làm việc từ mạng doanh nghiệp với quyền truy cập hạn chế:
# Tạo tunnel SOCKS5 SSH trên cổng cục bộ 1080 ssh -D 1080 -f -C -q -N [email protected] # Sau đó sử dụng privoxy hoặc proxychains để chuyển đổi sang HTTP # Hoặc trực tiếp qua biến môi trường (Node.js hiểu SOCKS qua một số thư viện) # Lựa chọn thay thế - sử dụng curl như một bài kiểm tra: curl --socks5 localhost:1080 https://registry.npmjs.org/react/latest
Registry riêng tư của riêng bạn như một sự thay thế cho proxy
Trong các môi trường doanh nghiệp và bị cô lập, thường giải pháp tốt nhất không phải là cấu hình proxy cho từng nhà phát triển, mà là triển khai một npm-registry riêng bên trong mạng. Registry như vậy sẽ cache các gói từ npmjs.org công khai và cung cấp chúng từ mạng nội bộ. Các nhà phát triển không cần quyền truy cập vào Internet - mọi thứ hoạt động qua registry cục bộ.
Verdaccio: khởi động nhanh trong 10 phút
Verdaccio là một npm-registry mã nguồn mở với hỗ trợ proxy và caching. Nó được cài đặt như một gói npm, hoạt động như một dịch vụ riêng biệt:
# Cài đặt Verdaccio toàn cầu npm install -g verdaccio # Khởi động (theo mặc định lắng nghe trên http://localhost:4873) verdaccio # Cấu hình npm để sử dụng registry cục bộ npm config set registry http://localhost:4873 # Xuất bản các gói vào registry cục bộ npm adduser --registry http://localhost:4873 npm publish --registry http://localhost:4873
Cấu hình Verdaccio (~/.config/verdaccio/config.yaml) cho phép cấu hình proxy qua proxy bên ngoài để tải các gói từ npmjs.org:
# config.yaml - cấu hình uplink với proxy
uplinks:
npmjs:
url: https://registry.npmjs.org/
# Nếu Verdaccio cũng nằm sau proxy:
agent_options:
http_proxy: http://proxy.company.com:8080
https_proxy: http://proxy.company.com:8080
no_proxy: localhost,127.0.0.1
packages:
'@*/*':
access: $all
publish: $authenticated
proxy: npmjs
'**':
access: $all
publish: $authenticated
proxy: npmjs
So sánh các giải pháp cho các môi trường bị cô lập
| Giải pháp | Độ phức tạp | Caching | Phù hợp cho |
|---|---|---|---|
| Gương (npmmirror) | Thấp | Không | Chặn địa lý, truy cập chậm đến npmjs.org |
| HTTP-proxy trong .npmrc | Thấp | Không | Mạng doanh nghiệp với HTTP-proxy |
| SOCKS5 + proxychains | Trung bình | Không | Proxy dân cư/di động, VPN |
| Verdaccio | Trung bình | Có | Các nhóm, mạng bị cô lập, CI/CD |
| Nexus / Artifactory | Cao | Có | Doanh nghiệp, kiểm toán phụ thuộc |
Chẩn đoán và khắc phục các lỗi thường gặp
Ngay cả khi đã cấu hình đúng, proxy vẫn có thể gặp vấn đề. Đây là cách tiếp cận hệ thống để chẩn đoán và danh sách các lỗi thường gặp nhất cùng với giải pháp của chúng.
Bước 1: Kiểm tra cấu hình npm hiện tại
# Hiển thị tất cả cài đặt npm (bao gồm cả proxy) npm config list # Hiển thị chỉ cài đặt proxy npm config get proxy npm config get https-proxy npm config get registry npm config get strict-ssl # Bật chế độ chi tiết để chẩn đoán npm install react --verbose npm install react --loglevel verbose
Bước 2: Kiểm tra khả năng truy cập registry trực tiếp
# Kiểm tra khả năng truy cập registry qua curl curl -v https://registry.npmjs.org/react/latest # Kiểm tra qua proxy curl -v --proxy http://proxy.example.com:8080 https://registry.npmjs.org/react/latest # Kiểm tra ping (không phải lúc nào cũng hữu ích cho HTTPS) ping registry.npmjs.org # Kiểm tra phân giải DNS nslookup registry.npmjs.org
Các lỗi thường gặp và giải pháp của chúng
| Lỗi | Nguyên nhân | Giải pháp |
|---|---|---|
| ECONNREFUSED | Proxy không chấp nhận kết nối hoặc cổng không đúng | Kiểm tra địa chỉ và cổng của proxy, khả năng truy cập của máy chủ proxy |
| ETIMEDOUT | Yêu cầu bị chặn bởi tường lửa mà không có phản hồi | Cấu hình lại proxy hoặc chuyển sang gương |
| SELF_SIGNED_CERT | Kiểm tra SSL của proxy doanh nghiệp | Thêm CA doanh nghiệp qua cafile |
| 407 Proxy Auth | Proxy yêu cầu xác thực | Thêm tên đăng nhập:mật khẩu vào URL của proxy |
| ENOTFOUND | DNS không phân giải tên registry hoặc proxy | Kiểm tra cài đặt DNS, sử dụng IP thay vì tên |
| E403 Forbidden | Proxy chặn các yêu cầu đến npmjs.org | Sử dụng gương hoặc liên hệ với quản trị mạng |
Đặt lại tất cả cài đặt proxy
# Xóa tất cả cài đặt proxy từ cấu hình người dùng npm config delete proxy npm config delete https-proxy npm config delete noproxy # Đặt lại registry về chính thức npm config set registry https://registry.npmjs.org # Trở lại strict-ssl (nếu đã tắt) npm config set strict-ssl true # Kiểm tra cấu hình cuối cùng npm config list
Làm việc với pnpm và Yarn khi registry bị chặn
Nếu bạn sử dụng các trình quản lý gói thay thế, cấu hình proxy trông tương tự, nhưng cú pháp có chút khác biệt:
# pnpm - sử dụng cùng một .npmrc như npm # Có thể cấu hình thêm qua pnpm config: pnpm config set proxy http://proxy.example.com:8080 pnpm config set https-proxy http://proxy.example.com:8080 pnpm config set registry https://registry.npmmirror.com # Yarn Classic (v1) - tệp .yarnrc riêng yarn config set proxy http://proxy.example.com:8080 yarn config set https-proxy http://proxy.example.com:8080 yarn config set registry https://registry.npmmirror.com # Yarn Berry (v2+) - tệp .yarnrc.yml # httpProxy: "http://proxy.example.com:8080" # httpsProxy: "http://proxy.example.com:8080" # npmRegistryServer: "https://registry.npmmirror.com"
Cấu hình proxy cho các gói scoped cụ thể
Đôi khi cần sử dụng các registry khác nhau cho các gói khác nhau: ví dụ, các gói công khai lấy từ npmjs.org chính thức, trong khi các gói doanh nghiệp @company/* - từ Nexus nội bộ. Điều này được cấu hình qua registry riêng cho scope trong .npmrc:
# .npmrc - các registry khác nhau cho các scope khác nhau registry=https://registry.npmjs.org # Các gói doanh nghiệp @company qua Nexus nội bộ @company:registry=http://nexus.company.local/repository/npm-hosted/ # Các gói @myorg qua Verdaccio @myorg:registry=http://localhost:4873/ # Xác thực cho registry cụ thể //nexus.company.local/repository/npm-hosted/:_authToken=YOUR_TOKEN_HERE
Kết luận và khuyến nghị cuối cùng
Trong môi trường phát triển hiện đại, việc cấu hình proxy cho npm là một kỹ năng quan trọng. Hy vọng rằng hướng dẫn này đã cung cấp cho bạn những thông tin cần thiết để vượt qua các vấn đề về registry và tối ưu hóa quy trình phát triển của bạn.
```