A Guide to Spring Cloud Config

Spring Cloud Config provides server-side and client-side support for externalized configuration in a distributed system. With the Config Server, you have a central place to manage external properties for applications across all environments.

In this post, I will cover the common uses of the Spring Cloud Config. This post is based on Java 21, Spring Boot 3.5.3, and Spring Cloud 2025.0.0.

Spring Cloud Config Server

1. Create Project and Add Dependencies

Using Gradle

$ mkdir spring-cloud-config-server && cd spring-cloud-config-server
$ gradle init --use-defaults \
--type java-application \
--package com.taogen.springcloud

app/build.gradle.kts

plugins {
java
id("org.springframework.boot") version "3.5.3"
// Use the Spring Dependency Management plugin to manage Spring Cloud dependencies.
id("io.spring.dependency-management") version "1.1.7"
}

extra["springCloudVersion"] = "2025.0.0"

java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}

repositories {
mavenCentral()
}

dependencies {
implementation("org.springframework.cloud:spring-cloud-config-server")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

dependencyManagement {
imports {
mavenBom("org.springframework.cloud:spring-cloud-dependencies:${property("springCloudVersion")}")
}
}

tasks.withType<Test> {
useJUnitPlatform()
}

Using Maven

$ mvn -B archetype:generate \
-DgroupId=com.taogen.springcloud \
-DartifactId=spring-cloud-config-server \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DarchetypeVersion=1.5

pom.xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.taogen.springcloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
<version>1.0-SNAPSHOT</version>

<name>spring-cloud-config-server</name>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>21</maven.compiler.release>
<java.version>21</java.version>
<spring-boot.version>3.5.3</spring-boot.version>
<spring-cloud.version>2025.0.0</spring-cloud.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

Using Spring Initializr

Go to https://start.spring.io/

Project Metadata

  • Group: com.taogen.springcloud
  • Artifact: spring-cloud-config-server

Add dependencies

  • Config Server

2. Spring Configuration

There are many implementations of the server storage backend. The commonly used implementations are: Git, File System, and Vault. The default implementation of the server storage backend uses git.

File System Backend (Simple, Fast)

A filesystem backend is great for getting started quickly and for testing. To use it in production, you need to be sure that the file system is reliable and shared across all instances of the Config Server.

The “native” profile in the Config Server that does not use Git but loads the config files from the local classpath or file system (any static URL you want to point to with spring.cloud.config.server.native.searchLocations). To use the native profile, launch the Config Server with spring.profiles.active=native.

src/main/resources/application.yml

spring: 
profiles:
active: native
cloud:
config:
server:
native:
searchLocations: "classpath:/config"
server:
port: 8888
  • searchLocations:
    • Classpath: classpath:/config
    • File system: file:///Users/taogen/config/spring-cloud-config (require an extra /)

Configuration file for Spring Cloud Config client application

myapp.properties in src/main/resources/config (classpath:/config)

greeting=Hello World!

myapp-dev.properties

greeting=Hello Dev!

myapp-prod.properties

greeting=Hello Prod!

You can also use yaml configuration files.

Git Local

1. application.yml

spring:
cloud:
config:
server:
git:
uri: file:///Users/taogen/config/spring-cloud-config
defaultLabel: main

server:
port: 8888

2. Initializing the local git repository

$ mkdir -p /Users/taogen/config/spring-cloud-config
$ cd /Users/taogen/config/spring-cloud-config
$ git init .

3. Add properties files

myapp.properties in /Users/taogen/config/spring-cloud-config

greeting=Hello World!

myapp-dev.properties

greeting=Hello Dev!

myapp-prod.properties

greeting=Hello Prod!

4. Commit properties files to the local git repository

git add .
git commit -m "Add properties"
Git SSH

application.yaml

spring:
cloud:
config:
server:
git:
cloneOnStart: true
timeout: 10
uri: git@github.com:tg-playground/spring-cloud-config.git
defaultLabel: main
ignoreLocalSshSettings: true
hostKey: YOUR_PUBLIC_KEY
hostKeyAlgorithm: ssh-rsa
private-key: YOUR_PRIVATE_KEY

server:
port: 8888
  • hostKey: Git publicKey for server verification. Used to validate the Git server’s host key during SSH handshake. Protects against man-in-the-middle attacks.
  • private-key: Git privateKey for client authentication. Spring Cloud Config Server acts as an SSH client. It uses the privateKey to prove its identity to the Git server.
Git HTTPS

1. application.yml

spring:
config:
import: optional:file:.env[.properties],optional:file:../.env[.properties]
cloud:
config:
server:
git:
cloneOnStart: true
timeout: 10
# Suggest using Gitee in China. Using GitHub URL often throws connect timeout exception.
uri: "https://github.com/tg-playground/spring-cloud-config.git"
defaultLabel: main
username: ${username}
password: ${personalAccessToken}

server:
port: 8888
  • username: GitHub username or email.
  • password: personal access token (PAT)

2. Generating a personal access token (PAT) on GitHub

New fine-grained personal access token (Recommended)

  • Only select repositories: spring-cloud-config
  • Permissions:
    • Contents: Read-only

Token (classic)

  • Permissions:
    • repo: Full control of private repositories

3. Adding the .env file to the root directory of the project

.env

# Git HTTPS
username=YOUR_USERNAME
personalAccessToken=YOUR_TOKEN

Spring Cloud Config Server also supports Vault as a backend.

Vault is a tool for securely accessing secrets. A secret is anything that to which you want to tightly control access, such as API keys, passwords, certificates, and other sensitive information. Vault provides a unified interface to any secret while providing tight access control and recording a detailed audit log.

To enable the config server to use a Vault backend, you can run your config server with the vault profile. For example, in your config server’s application.properties, you can add spring.profiles.active=vault.

1. application.yml

spring:
config:
import: optional:file:.env[.properties],optional:file:../.env[.properties]
profiles:
active: vault
cloud:
config:
server:
vault:
host: localhost
port: ${VAULT_PORT}
kv-version: 2
authentication: token
token: ${VAULT_DEV_ROOT_TOKEN_ID}
profile-separator: /
scheme: http
backend: spring-cloud-config

server:
port: 8888
  • backend: Secrets engine name

2. Adding the .env file to the root directory of the project

.env

# HashiCorp Vault  
VAULT_PORT=8200
VAULT_DEV_ROOT_TOKEN_ID=myroot

3. Running HashiCorp Vault

Add the compose.yaml to your project root path.

compose.yaml

services:
vault:
image: 'hashicorp/vault:1.20'
ports:
- ${VAULT_PORT}:8200
cap_add:
- IPC_LOCK
environment:
- 'VAULT_DEV_ROOT_TOKEN_ID=${VAULT_DEV_ROOT_TOKEN_ID}'
  • VAULT_DEV_ROOT_TOKEN_ID: It’s used to login Vault UI web page and spring cloud config server token authentication.

Starting HashiCorp Vault with docker compose

docker compose up -d

Visiting http://localhost:8200/ to open the Vault UI web page.

4. Set up HashiCorp Vault

Login HashiCorp Vault UI.

Add the Secret Engine spring-cloud-config

  1. Click “Secrets Engines” on the left navigation bar.
  2. Click the “Enable new engine” button.
  3. Select “Generic” > “KV”.
  4. File the form. Path: spring-cloud-config, Maximum number of versions: 2
  5. Click the “Enable engine” button.

Add Secret

  • Path for this secret: {application_name}/{profile}.
  • Secret data:
    • key: value

Secret 1

  • Path for this secret: myapp
  • Secret data:
    • greeting: Hello World!

Secret 2

  • Path for this secret: myapp/dev
  • Secret data:
    • greeting: Hello Dev!

3. Config Server Application

Spring Cloud Config Server provides an HTTP resource-based API for external configuration (name-value pairs or equivalent YAML content). The server is embeddable in a Spring Boot application, by using the @EnableConfigServer annotation.

SpringCloudConfigServerApplication.java

package com.taogen.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;

@SpringBootApplication
@EnableConfigServer
public class SpringCloudConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloudConfigServerApplication.class, args);
}
}

4. Start and Verification

Starting Spring Cloud Config Server

Running the main() method in the SpringCloudConfigServerApplication to start Spring Cloud Config Server.

Verification

Visiting http://localhost:8888/{application_name}/{profile} to see the configurations for the client application.

For example, http://localhost:8888/myapp/default or http://localhost:8888/myapp/dev.

5. Securing Configurations

1. Add the following configuration to your application.yml

encrypt:
key: my-secret-key

After adding the above spring configuration, you need to restart the application.

2. Get encrypted text

Generating encrypted text of “MyPssowrd”

curl -X POST http://localhost:8888/encrypt -d "MyPssowrd" 

Output

f24b9ee2de9cf7c02a58a026ff235189f86c9d00e47ae4ef4bdd6fe014326a33

3. Using encrypted text in properties files

myapp.properties

greeting=Hello World!
myPassword={cipher}f24b9ee2de9cf7c02a58a026ff235189f86c9d00e47ae4ef4bdd6fe014326a33

Visiting http://localhost:8888/myapp/default to see the decrypted configurations.

Spring Cloud Config Client

1. Create Project and Add Dependencies

Using Gradle

$ mkdir spring-cloud-config-client && cd spring-cloud-config-client
$ gradle init --use-defaults \
--type java-application \
--package com.taogen.springcloud

app/build.gradle.kts

plugins {
java
id("org.springframework.boot") version "3.5.3"
// Use the Spring Dependency Management plugin to manage Spring Cloud dependencies.
id("io.spring.dependency-management") version "1.1.7"
}

extra["springCloudVersion"] = "2025.0.0"

java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}

repositories {
mavenCentral()
}

dependencies {
implementation("org.springframework.cloud:spring-cloud-config")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-actuator")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

dependencyManagement {
imports {
mavenBom("org.springframework.cloud:spring-cloud-dependencies:${property("springCloudVersion")}")
}
}

tasks.withType<Test> {
useJUnitPlatform()
}

Using Maven

$ mvn -B archetype:generate \
-DgroupId=com.taogen.springcloud \
-DartifactId=spring-cloud-config-client \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DarchetypeVersion=1.5

pom.xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.taogen.springcloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
<version>1.0-SNAPSHOT</version>

<name>spring-cloud-config-client</name>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>21</maven.compiler.release>
<java.version>21</java.version>
<spring-boot.version>3.5.3</spring-boot.version>
<spring-cloud.version>2025.0.0</spring-cloud.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

Using Spring Initializr

Go to https://start.spring.io/

Project Metadata

  • Group: com.taogen.springcloud
  • Artifact: spring-cloud-config-client

Add dependencies

  • Config Client
  • Spring Web
  • Spring Boot Actuator

2. Spring Configuration

application.yml

spring:
application:
name: myapp
profiles:
active: dev
config:
import: "optional:configserver:http://localhost:8888"
  • spring.application.name: It must be the same with the filename of properties or yaml files in Spring Cloud Config Server. If the application name is myapp (spring.application.name: myapp), the properties file in Spring Cloud Config Server is myapp.properties, or myapp-dev.properties, or myapp.yml and so on.

3. Config Client Application

SpringCloudConfigClientApplication.java

package com.taogen.springcloud;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class SpringCloudConfigClientApplication {
@Value("${greeting}")
private String greeting;

public static void main(String[] args) {
SpringApplication.run(SpringCloudConfigClientApplication.class, args);
}

@GetMapping("/greeting")
public String greeting() {
return greeting;
}
}

4. Start and Verification

Starting Spring Cloud Config Client

Running the main() method in the SpringCloudConfigClientApplication to start Spring Cloud Config Client.

Verification

Visiting http://localhost:8080/greeting to see the properties value from Spring Cloud Config Server. You can update spring.profiles.active to see the different properties values.

5. Refresh Configurations

Using @RefreshScope

1. Add @RefreshScope annotation

Add @RefreshScope annotation in your beans that import properties from Spring Cloud Config. For example:

@Component
@RefreshScope
public class MyComponent {
@Value("${greeting}")
private String greeting;

//...
}

2. Expose the /refresh endpoint

To expose the /refresh endpoint, you need to add the following configuration to your application.yml:

management:
endpoints:
web:
exposure:
include: refresh

3. Call the /actuator/refresh endpoint to refresh configurations

curl -X POST http://localhost:8080/actuator/refresh

4. Visiting http://localhost:8080/greeting to see the updated properties value from Spring Cloud Config Server.

Best Practices

  • Use Git for regular configuration versioning, environments, and ease of updates.
  • Combine Git + Vault: Git for general configs, Vault for secrets.
  • Enable spring-cloud-bus or /actuator/refresh for dynamic config refresh.

References

[1] Spring Microservices in Action, Second Edition

[2] Spring Cloud Config Documentation

[3] Spring Cloud Context: Application Context Services