Infrastructure worth keeping — and kept patched.

Gradle build cache behind a corporate proxy

Many companies make builds reach the network through a proxy. This page shows how Gradle's remote build cache behaves behind one: the settings, the ways it goes wrong, and how to tell a proxy problem from a cache problem. Everything was run for real with Gradle 9.8.0 and FosterStack Cache 0.2.1.

What was tested, and what was not

The settings

Gradle takes proxy settings from Java system properties. Put them in ~/.gradle/gradle.properties or the project's gradle.properties, with the systemProp. prefix:

systemProp.http.proxyHost=proxy.example.com
systemProp.http.proxyPort=3128
systemProp.https.proxyHost=proxy.example.com
systemProp.https.proxyPort=3128
systemProp.http.nonProxyHosts=cache.internal.example.com|localhost|127.*

Use the https pair for an https:// cache URL and the http pair for plain HTTP. The last line lists hosts that should skip the proxy.

What I saw

For the plain-HTTP rows I set isAllowInsecureProtocol = true, which Gradle requires for non-loopback http://. That is for the test rig only; use HTTPS for real.

SetupResultWhat the proxy logged
No proxy settings, cache at <cache-ip>second build FROM-CACHEnothing (not used)
Proxy settings, same plain-HTTP URLFROM-CACHEGET http://<cache-ip>:18130/<key>, one per build
Proxy settings, but the cache URL is 127.0.0.1FROM-CACHEnothing: Java skips the proxy for loopback addresses
Proxy settings, with the cache's address in nonProxyHostsFROM-CACHEnothing
Proxy settings, HTTPS cache, tunnel allowedFROM-CACHECONNECT <cache-ip>:18443, one per build
Proxy settings, proxy refuses the cache hostthe build succeeds but without the cache (log below)the request, answered 403

Three things that catch people

1. Testing against localhost skips the proxy. With the cache at 127.0.0.1, Gradle never used the proxy even though it was configured. A setup that works on your laptop against a local cache proves nothing about the proxy path. Test against the real address.

2. A refusing proxy looks like a cache error. When the proxy answered 403 to the tunnel, Gradle printed:

Could not load entry d4f2de693b561fd2c5d60b17a9232d6f from remote build cache: Loading entry from 'https://<cache-ip>:18443/d4f2de693b561fd2c5d60b17a9232d6f' response status 403: Forbidden

That is the same text you would get from the cache refusing a write with the read-only login (see the status codes). To tell them apart, take Gradle out of it and try the same route with curl:

$ curl -sS -x http://proxy.example.com:3128 https://cache.example.com/healthz
curl: (56) CONNECT tunnel failed, response 403      # the proxy said no
$ curl -sS --noproxy '*' https://cache.example.com/healthz
ok                                                   # the cache is fine

I substituted example hostnames in those commands; the two output lines are the real ones, from my test proxy refusing and from the cache answering directly. If the first one fails and the second works, ask whoever runs the proxy to allow the cache's host and port.

3. Over HTTPS the proxy only sees the address. A CONNECT tunnel shows the proxy the host and port and nothing inside, so the password and the cache keys are not visible to it. That also means any rule on the path cannot be applied. This is how the proxy log looked in my run: one CONNECT line per build.

Checklist

Related: Gradle remote build cache not working and authentication and 401 errors.

Gradle build cache tutorial FosterStack home