Gradle build cache tutorial: see FROM-CACHE with a self-hosted cache
+Start a cache server, point a small Gradle project at it, build twice, and watch the second build take its work from the cache. Everything below was run for real: release 0.2.1 of the server and Gradle 9.8.0.
+ +1. Start the server
+Download and verify the release as shown in Verify a release yourself, unpack it, and run it with a password and a size cap:
+FSCACHE_ADDR=127.0.0.1:8080 FSCACHE_DATA_DIR=./data \
+ FSCACHE_USERNAME=gradle FSCACHE_PASSWORD=demo-pass \
+ FSCACHE_MAX_BYTES=1073741824 ./fscache
+ Prefer a container? Gradle build cache with Docker Compose has the same settings. (My test run used port 18090 instead of 8080; the outputs below do not show the port.)
+ +2. A small project
+Four files. settings.gradle.kts says where the cache is:
rootProject.name = "demo"
+
+// FosterStack Cache — remote Gradle build cache.
+// https://github.com/fosterstack/cache
+buildCache {
+ local { isEnabled = false } // so a hit can only come from the remote
+ remote<HttpBuildCache> {
+ url = uri("http://127.0.0.1:8080/")
+ isPush = true
+ credentials {
+ username = "gradle"
+ password = System.getenv("FSCACHE_PASSWORD")
+ }
+ }
+}
+ Turning the local cache off is only for this test. It means a hit can only have come from the remote. build.gradle.kts is one line, plugins { java }. gradle.properties switches caching on, which the buildCache block does not do by itself:
org.gradle.caching=true
+ And src/main/java/demo/App.java is any small class.
3. Build once
+export FSCACHE_PASSWORD=demo-pass
+gradle build --build-cache
+
+> Task :compileJava
+> Task :processResources NO-SOURCE
+> Task :classes
+> Task :jar
+> Task :assemble
+> Task :compileTestJava NO-SOURCE
+> Task :processTestResources NO-SOURCE
+> Task :testClasses UP-TO-DATE
+> Task :test NO-SOURCE
+> Task :check UP-TO-DATE
+> Task :build
+BUILD SUCCESSFUL in 5s
+2 actionable tasks: 2 executed
+ Nothing came from the cache, and every cacheable task ran. Gradle stored the compile result on the server. The status page agrees:
+$ curl -s -u gradle:demo-pass localhost:8080/statusz | grep -E '"store_entries"|"cache_hits"|"cache_misses"'
+ "store_entries": 1,
+ "cache_hits": 0,
+ "cache_misses": 1,
+
+ 4. Clean, and build again
+gradle clean
+gradle build --build-cache
+
+> Task :compileJava FROM-CACHE
+> Task :processResources NO-SOURCE
+> Task :classes UP-TO-DATE
+> Task :jar
+> Task :assemble
+> Task :compileTestJava NO-SOURCE
+> Task :processTestResources NO-SOURCE
+> Task :testClasses UP-TO-DATE
+> Task :test NO-SOURCE
+> Task :check UP-TO-DATE
+> Task :build
+BUILD SUCCESSFUL in 5s
+2 actionable tasks: 1 executed, 1 from cache
+ There it is: :compileJava FROM-CACHE and "1 from cache". The server counted the hit:
$ curl -s -u gradle:demo-pass localhost:8080/statusz | grep -E '"store_entries"|"cache_hits"|"cache_misses"'
+ "store_entries": 1,
+ "cache_hits": 1,
+ "cache_misses": 1,
+
+ The one thing that tripped me up
+My first attempt failed before any build ran, because I used http://localhost:...:
FAILURE: Build failed with an exception.
+
+* What went wrong:
+Using insecure protocols with remote build cache, without explicit opt-in, is unsupported.
+ Gradle refuses plain http:// unless you set isAllowInsecureProtocol = true. With Gradle 9.8.0, the address 127.0.0.1 was allowed without it, but the name localhost was refused, with or without a credentials block. That is why the file above uses 127.0.0.1. For a real server, use HTTPS and skip the opt-in. Gradle sends the password with every request.
If your second build shows no FROM-CACHE, work through Gradle remote build cache not working. The status codes are explained in Gradle build cache HTTP status codes.