Gradle remote build cache authentication and 401 errors
How to put a password on a self-hosted build cache and give Gradle the right one, three ways to supply it, and what you see when it is wrong. Every output below is from a real run: a 0.2.1 server and Gradle 9.8.0 on macOS.
Turn on a password on the server
FSCACHE_USERNAME=gradle FSCACHE_PASSWORD=<a long secret> ./fscache
This is HTTP Basic Auth. The health and metrics paths stay open without a password, so monitoring still works. The status page does not. For a second, read-only login see let CI write, developers only read.
Tell Gradle the password
In settings.gradle.kts:
// FosterStack Cache — remote Gradle build cache.
// https://github.com/fosterstack/cache
buildCache {
remote<HttpBuildCache> {
url = uri("https://cache.example.com/")
isPush = true
credentials {
username = "gradle"
password = System.getenv("FSCACHE_PASSWORD")
}
}
}
Keep the credentials block even where the server has no password. I tested a client with this block against a server with authentication switched off: the build stored an entry and the next build got a hit, so one config works against both a test server and a real one.
Three ways to supply the password
All three were tested and gave :compileJava FROM-CACHE:
- An environment variable, as above:
export FSCACHE_PASSWORD=.... Good for CI, where the secret store sets it. - Your user
~/.gradle/gradle.properties, withpassword = providers.gradleProperty("fscachePassword").orNullin the settings file andfscachePassword=...in that file. Never put it in the project's owngradle.properties, which gets committed. - The command line:
gradle build -PfscachePassword=.... Handy for one-off tests; it also shows up in the process list.
What a wrong or missing password looks like
Gradle treats a broken remote cache as non-fatal, so the build still succeeds, just without the cache. In my runs it printed this at the default log level, with a wrong password and with none:
Could not load entry d4f2de693b561fd2c5d60b17a9232d6f from remote build cache: Loading entry from 'http://127.0.0.1:18099/d4f2de693b561fd2c5d60b17a9232d6f' response status 401: Unauthorized
If you see that line, the password Gradle sent was wrong or missing. To test the server directly, a 401 means wrong credentials and a 404 means the credentials are right and the key is not stored yet. See the status codes.
Do I need to restart the Gradle daemon?
Not in my test. I started a daemon with no password, exported the right one in the same shell, and the next build used it (same daemon process, no restart) and got FROM-CACHE. Then I exported a wrong one and the next build printed the 401 line straight away. If a password still seems ignored on your setup, ./gradlew --stop is a quick way to rule the daemon out. I only tested macOS with Gradle 9.8.0.
Use HTTPS
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; in my test the address 127.0.0.1 was let through without it, but the name localhost was refused. Put real servers behind HTTPS.
Related: Gradle remote build cache not working and who can write to a remote build cache.