Slow Git clones, failed Docker pulls, npm timeouts, and unreliable CI builds often look like separate problems. In practice, they usually share the same underlying causes: the application does not inherit the operating system proxy, a registry is reached through an unsuitable route, DNS is resolved in the wrong network context, or a long-lived connection is interrupted before the transfer finishes. The right solution is therefore not to turn on a proxy and hope that every developer tool follows it. Each tool needs an explicit routing decision.
This guide presents a practical setup for GitHub, Docker, npm, and common CI workflows. It explains when a system-level VPN client is enough, when a command-line proxy must be configured separately, and when a daemon such as Docker needs its own environment settings. The same method works with official Windows, macOS, Android, iOS, and Linux clients, as well as compatible clients such as Clash Verge, sing-box, or Shadowrocket when they support the required subscription format and routing mode.
Map the development traffic before changing settings
Begin by listing the destinations that the workflow actually uses. A Git operation may contact a repository host, an authentication endpoint, a package subdomain, and a release asset host during one command. A Docker build may contact a container registry, an image metadata endpoint, a credential service, and several base-image layers. An npm installation may use the configured registry, redirect to a tarball host, and contact a source-control host for a dependency declared with a Git URL.
This distinction matters because a proxy setting is usually applied to a protocol or process, not to the abstract idea of “development traffic.” A browser proxy can affect HTTPS requests from the browser while leaving a background daemon untouched. Likewise, setting a proxy for the interactive shell does not necessarily change the environment of a Docker service that started earlier.
Next, determine whether the problem is routing, DNS, authentication, or a local configuration error. A connection that reaches a host but returns an authorization error is not a speed problem. A package that resolves to an unreachable address may need DNS correction rather than a different registry. A Docker image that starts downloading and then fails repeatedly may indicate a daemon timeout, an interrupted route, or an expired credential.
Record the original state before editing anything. Save the output of git config --show-origin --get-regexp 'http\..*|https\..*|url\..*', npm config get registry, and the relevant Docker service configuration. This gives you a clean rollback path and prevents an old proxy entry from remaining hidden in a user-level or system-level configuration file.
Choose a routing model that matches the tool
There are three practical routing models. A full-device VPN route sends most or all traffic through the selected tunnel. This is simple for a personal workstation because browsers, terminals, and applications usually share the same network path. It can be useful when several tools are involved and you do not want to maintain separate proxy variables.
A system proxy route uses an HTTP or SOCKS endpoint exposed by the local VPN client. Applications that honor operating-system proxy settings can use it automatically, but command-line programs and daemons may still need explicit variables. SOCKS is a forwarding protocol, while an HTTP CONNECT proxy is designed to establish tunnels for HTTPS requests. Do not place a SOCKS address in a field that only accepts an HTTP proxy URL.
Per-process routing is the most controlled option. You can configure Git and npm explicitly, start a shell with proxy variables, and leave unrelated local services outside the tunnel. This reduces unexpected effects on private intranet services, local registries, and development databases. It also requires more discipline: every new tool must be checked for proxy support and for the way it inherits environment variables.
- ✅ Use a full-device route when you need the simplest setup across many developer tools.
- ✅ Use explicit application settings when Docker, Git, or npm does not follow the system proxy.
- ✅ Use split routing for local development services that must remain reachable directly.
- ❌ Do not run two full-tunnel VPN clients at the same time; competing route tables can create intermittent failures.
- ❌ Do not assume that a browser extension changes the route used by a background service.
For a team, consistency is more important than a particular client brand. Windows and macOS users may use the official desktop client, while Linux users may use the official client or a compatible client that supports the same subscription. Clash Verge and sing-box can be useful when rule-based routing is required, but the team should document the selected mode, DNS behavior, and proxy endpoint so that every developer is troubleshooting the same architecture.
VPNRZ lists support for Windows, macOS, iOS, Android, and Linux, with 100+ countries and 220+ lines. Those figures describe service coverage, not a guarantee that every route is optimal for every repository or registry. A practical choice still requires testing the destination, protocol, DNS behavior, and transfer continuity from the actual development network.
Configure Git and GitHub without hiding errors
Git can use HTTPS or SSH, and the proxy design is different for each. HTTPS remotes generally work with HTTP proxy variables or Git’s own HTTP configuration. SSH remotes use an SSH connection and do not automatically obey an HTTP proxy setting. If a network only exposes an HTTP CONNECT proxy, SSH requires an appropriate tunnel method or a switch to an HTTPS remote. A SOCKS-capable SSH configuration may also be possible, but it must be configured through SSH rather than pasted into Git’s HTTP proxy field.
Check the remote before changing it:
git remote -v
git config --show-origin --get-regexp 'http\..*|https\..*|core\.sshCommand'
For an HTTPS workflow, a temporary shell variable is a good first test because it does not permanently modify the repository or user configuration:
export HTTP_PROXY=http://127.0.0.1:LOCAL_PORT
export HTTPS_PROXY=http://127.0.0.1:LOCAL_PORT
git ls-remote https://github.com/OWNER/REPOSITORY.git
Replace the local address and port with the endpoint shown by the VPN client. On Windows PowerShell, use $env:HTTP_PROXY and $env:HTTPS_PROXY instead. If the test succeeds, decide whether the setting belongs at the shell, user, repository, or CI level. A repository-level setting is usually inappropriate when the repository is shared, because it can expose a workstation-specific proxy assumption to other developers.
Git also has its own configuration:
git config --global http.proxy http://127.0.0.1:LOCAL_PORT
git config --global https.proxy http://127.0.0.1:LOCAL_PORT
git config --global --unset http.proxy
git config --global --unset https.proxy
Use the last two commands when removing a stale proxy. A common failure pattern is that the VPN client is no longer running, but Git still points to a local port from an old configuration. Another is a proxy URL containing credentials saved in plain text. Avoid putting long-lived secrets directly into Git configuration. Prefer the client’s authenticated session, a credential manager, or a short-lived CI secret with restricted scope.
Submodules deserve a separate check. The main repository may use HTTPS while a submodule uses SSH, or a nested configuration may override the parent’s URL. Run git submodule sync --recursive only after reviewing the declared URLs, then test the submodule endpoints individually. Large clones can also fail because of interrupted transfers rather than insufficient bandwidth. Switching to a stable route and retrying is safer than repeatedly increasing arbitrary buffer values.
GitHub Actions and other hosted CI services should not be treated as if they were running on your laptop. A local VPN does not automatically route a hosted runner. If the build must access a private repository or an external dependency through a controlled route, use the CI provider’s supported network architecture, a self-hosted runner, or an approved organization proxy. Never place a personal subscription link or a private proxy credential in a public repository, build log, or unprotected environment variable.
Configure Docker Engine and image builds
Docker has at least two network contexts: the Docker CLI process and the Docker Engine daemon. Running docker pull from a terminal may appear to use the shell’s proxy variables, while the daemon performs the actual registry request independently. On Docker Desktop, the application has its own proxy and network settings. On Linux, a system-managed Docker service commonly needs a service-level environment configuration followed by a daemon restart.
Start by separating three questions: can the host reach the registry, can the Docker daemon authenticate to it, and can a build container reach package mirrors during a RUN instruction? These are not identical tests. A successful host request does not prove that the daemon has the same DNS path, and a successful image pull does not prove that build steps can reach npm or another package service.
docker info
docker pull IMAGE_NAME
docker build --progress=plain -t test-image .
Configure the daemon only with the proxy format it supports. An HTTP proxy endpoint is commonly expressed through HTTP_PROXY and HTTPS_PROXY; a SOCKS endpoint requires Docker and the surrounding environment to support that scheme correctly. Do not blindly copy a desktop application’s auto-configuration URL into a daemon configuration file. Consult the client and Docker documentation for the accepted syntax, then restart the daemon and confirm the effective configuration with docker info.
Build-time networking introduces another boundary. If the Dockerfile runs npm install, downloads a release archive, or retrieves a private module, the build process needs access to the required endpoint. Passing a proxy as a build argument can expose it in image history or logs, so it should not be used for durable credentials. Where possible, use BuildKit secrets, an internal package mirror, or a CI-managed secret mechanism. Also define a sensible NO_PROXY list for local registries, service names, private address ranges, and internal domains that should not traverse the external proxy.
Be careful with the special address 127.0.0.1. From the host, it means the host itself. From inside a container, it normally refers to that container, not the host and not the Docker daemon. A proxy bound only to the host loopback interface may therefore be unreachable from a build container. If a container must access a host-side proxy, use a supported host gateway or a properly bound interface, while ensuring that the proxy is not exposed broadly to untrusted networks.
Registry authentication failures should be handled separately from transfer failures. Reauthenticate with the registry, check the image name and tag, and inspect whether the registry requires a credential helper. Do not solve a 401 or 403 response by changing routes repeatedly. Conversely, do not publish access tokens in a Dockerfile, a copied shell transcript, or a publicly readable CI artifact.
Configure npm, package mirrors, and lifecycle scripts
npm can be affected by its registry setting, proxy configuration, environment variables, certificate settings, and the behavior of package lifecycle scripts. First inspect the effective values and their origin:
npm config get registry
npm config get proxy
npm config get https-proxy
npm config list
A normal public registry URL uses HTTPS. If npm times out, test whether the issue is name resolution, TLS negotiation, authentication, or the transfer itself. Do not disable certificate verification as a quick fix. Settings such as strict-ssl=false weaken protection against interception and can conceal an incorrectly installed local certificate. If an organization uses a private certificate authority, install it through the organization’s approved trust mechanism rather than turning TLS checks off.
For a temporary test, environment variables are less invasive than writing a permanent user configuration:
export HTTP_PROXY=http://127.0.0.1:LOCAL_PORT
export HTTPS_PROXY=http://127.0.0.1:LOCAL_PORT
npm view PACKAGE_NAME version
npm pack PACKAGE_NAME
npm may also have explicit proxy entries left over from an earlier network. If the current client exposes a local proxy on a different endpoint, remove or update those entries. Review project files such as .npmrc carefully: a project-level registry may be intentional, and deleting it can redirect private packages to the wrong service. For authentication, use a token with the narrowest available scope and keep it outside source control. A committed .npmrc containing a token should be treated as a credential leak and rotated immediately.
Not every dependency is downloaded from the npm registry. A package can refer to a Git repository, a tarball URL, or a private package service. If the registry request works but installation still fails, inspect the lockfile and dependency declarations. A Git dependency may invoke Git’s HTTPS or SSH behavior, while a tarball may follow npm’s proxy behavior. This is why a single successful npm ping does not validate the entire dependency graph.
Lifecycle scripts can introduce additional network requests during installation. They may download binaries, contact an API, or compile native code using a toolchain that has its own proxy rules. In a controlled diagnostic run, compare installation with scripts enabled and disabled, but do not permanently disable scripts without understanding the package’s requirements. A package that installs successfully with scripts disabled may still be unusable at runtime.
Make CI builds repeatable and safe
CI failures are harder to diagnose because the runner can differ from a developer workstation in operating system, DNS, container runtime, clock, certificate store, and egress policy. Write down the network assumptions in the pipeline instead of relying on undocumented runner defaults. The build should identify its registry endpoints, proxy variables, certificate requirements, and the expected authentication mechanism.
Use secret storage provided by the CI platform. Proxy credentials, registry tokens, subscription links, and private package tokens should be injected only into the jobs that need them. Mask them in logs, avoid printing the full environment, and prevent them from becoming Docker image layers or cached artifacts. If a command may echo its arguments, do not include credentials in the command line. Prefer environment variables or the platform’s secure authentication helper.
For containerized CI jobs, configure the job container and any service containers separately. A job that has HTTPS_PROXY may still start a database, Docker-in-Docker service, or sidecar without the same variables. Conversely, routing internal service names through an external proxy can break name resolution. Use NO_PROXY deliberately for local service names and internal addresses, and verify that the variable is recognized with the spelling and case expected by the relevant tool.
Cache dependencies only after the direct network path is understood. A warm npm cache or Docker layer cache can hide a broken registry route until the cache expires. A robust pipeline should be able to perform a clean dependency fetch under controlled conditions, while still using caches to reduce repeated downloads. Record useful error categories, not sensitive request headers or tokens: DNS failure, proxy refusal, TLS error, authentication rejection, registry rate limit, and interrupted transfer lead to different fixes.
- ✅ Test Git HTTPS, Git SSH if used, Docker pull, Docker build, and npm package retrieval as separate checks.
- ✅ Confirm whether the client, daemon, container, and CI runner each inherit the intended proxy.
- ✅ Keep registry credentials and proxy secrets in a protected secret store.
- ✅ Add internal domains and local service names to
NO_PROXYonly after verifying the required syntax. - ❌ Do not commit
.npmrc, Docker configuration, or CI files containing reusable private tokens.
Budget planning should follow usage rather than headline speed. A developer who mainly clones repositories and installs packages may prefer a monthly subscription with a defined allowance. The available VPNRZ monthly options are ¥9.9 per month with 60GB, ¥18 per month with 250GB, and ¥28 per month with 500GB; monthly traffic resets on the activation date. For transfers that are occasional but large, the permanent traffic packages are ¥158 for 300GB, ¥358 for 1000GB, and ¥658 for 3000GB. Upgrading a monthly plan calculates the difference according to the remaining days, so teams should still monitor usage instead of selecting solely by the largest number.
VPNRZ allows unlimited simultaneous devices, supports Alipay, WeChat, and USDT, and does not require an email address for registration. It also offers a 60-day no-questions-asked refund policy. These are service terms, not substitutes for technical validation: confirm that the chosen client is available on the developers’ platforms, that the required protocol works in the target network, and that the route is appropriate for repositories, registries, and CI infrastructure.
For a first implementation, connect one client, identify its local proxy endpoint, and test Git, Docker, and npm one at a time. Then document the working settings for the team and add a clean-build check to CI. If the issue remains unclear, compare the host route with the daemon or runner route, inspect DNS and authentication separately, and return to the smallest reproducible command. This approach is slower than copying a random proxy snippet, but it produces a setup that developers can understand, roll back, and maintain.