Jenkins and CI build cache for Gradle and Maven
Point your Jenkins agents, GitHub Actions runners or GitLab runners at one shared build cache, so a fresh agent stops rebuilding what another agent already built.
How a CI runner uses a remote build cache
The cache is a plain web server. Your build tool (Gradle, or Maven with Apache's Build Cache Extension) asks it for finished task results and uploads new ones. Any runner that can reach the server over HTTP can use it. There is no plugin to install on the CI system.
We have not tested it with any particular CI product. Our own tests run in GitHub Actions. The protocol is the same everywhere, so what matters is that the runner can reach the server and holds a login.
Let CI write, let developers read
The simplest safe setup is that only CI uploads to the cache and laptops only download. The server can enforce this: give laptops the optional read-only login (FSCACHE_RO_USERNAME and FSCACHE_RO_PASSWORD), and any write they attempt is refused. On the Gradle side you can also stop uploads from non-CI machines in settings.gradle.kts:
isPush = System.getenv("CI") != null
That line alone is the client choosing not to upload, not a rule on the server. Anyone holding the read-write password can write, so share it only with people and systems you already trust to change your code.
Runners inside your Kubernetes cluster
If your runners already run in the cluster that hosts the cache (including Jenkins agents), you need no load balancer and no ingress. Point the build at the cluster-internal name:
// FosterStack Cache — remote Gradle build cache.
// https://github.com/fosterstack/cache
buildCache {
remote<HttpBuildCache> {
url = uri("http://fscache.fscache-ns.svc.cluster.local/")
isAllowInsecureProtocol = true
isPush = true
credentials {
username = System.getenv("FSCACHE_USERNAME")
password = System.getenv("FSCACHE_PASSWORD")
}
}
}
Replace fscache-ns with your namespace. Plain HTTP is acceptable here only because the traffic never leaves the cluster network. The manifests are in the Kubernetes guide.
Runners outside the cluster, or on plain servers
Run the server on a host the runners can reach and put HTTPS in front of it. Gradle sends the password with every request, so over plain HTTP it travels in the clear. Gradle refuses plain HTTP unless you opt in with isAllowInsecureProtocol, which is a useful warning, not a nuisance. (In our test with Gradle 9.8.0, the address 127.0.0.1 was allowed without it, but the name localhost was refused.) Setup is in the install guide.
Give the runner the password
Store it in your CI system's secret store and expose it as the FSCACHE_PASSWORD environment variable. If builds stop using the cache after you change the secret, check the build log for a line like Could not load entry ... response status 401: Unauthorized, which means the password Gradle sent was wrong. In our test with Gradle 9.8.0 on macOS, a changed environment variable reached an already-running daemon on the next build, so a restart was not needed; ./gradlew --stop is still a quick way to rule the daemon out.
Check that CI is really using the cache
Run the same build twice on two different agents. The second should show FROM-CACHE next to tasks. A runner's local cache can hide a broken remote, so run once with -i, which prints remote errors. Gradle treats a broken remote as non-fatal, so the build carries on without it. On the server, the hit and miss counters at /metrics should move.
Maven on CI follows the same pattern with the extension and a <server> entry for the password. See the Gradle and Maven setup page.