# [Learn Microservices With Me] Setting Up A Config Server With Spring Cloud

Hey everyone! Today, we'll be learning about config servers in a microservice architecture using Spring Cloud. As a practical example, we'll be extending the student and course API from [our last guide](https://john-amiscaray.io/student-microservices-api) to use a config server.

## Prerequisites

To follow along with this tutorial, you should be able to follow along with [our last guide](https://john-amiscaray.io/student-microservices-api) on the basics of microservices and implementing them with Spring Cloud.

## What is a Config Server

A config server is a microservice that other services use to import their configurations (in the case of Spring Cloud, settings that would go in your `application.properties` file). This is useful for sharing common configurations for your microservices and creating externalized configurations that can be updated without redeployment! The config server can read configuration files from one location (often a git repository) and then other services can read the configuration files from the config server and import them.

## Implementation

Now that you understand the idea of a config server, let's implement it. To begin, we'll be starting from the code we left off from in the last guide which you can find [here](https://github.com/john-amiscaray/MicroservicesClassroomExample/tree/base-project). From that starting point, we'll need to create a new *ConfigServer* module:

```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>
    <parent>
        <groupId>io.john.amiscaray</groupId>
        <artifactId>MicroservicesClassroomExample</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>ConfigServer</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>
```

Notice the `spring-cloud-config-server` and `spring-cloud-starter-consul-discovery` dependencies. These will allow this microservice to act as a config server and register itself with Consul. Within this new Maven module, we need to add the following class to start up the Config Server:

```java
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {

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

}
```

From there, we need to create a Git repository with the configs we want to share and then have this config server retrieve it. To do this, first, create a new Git repository and host it on GitHub. Within the repository, we'll put a simple `application.properties` file in the root directory configuring a debug logging level for our testing purposes:

```java
logging.level.root=DEBUG
```

Once you committed the configuration and pushed it to GitHub, you'll need to create a GitHub personal access token with private repository access. With it, your config service can authenticate with GitHub to fetch configurations from the repository. To generate the token, go to *Settings &gt; Developer settings &gt; Personal access tokens &gt; Tokens (classic) &gt; Generate new token &gt; Generate new token (classic)*. Select the following permissions for the access token:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741902067702/d664461d-3fac-4105-a7a8-a4b12bda2944.png align="center")

Now that you have the token, you can configure your config service's `application.properties` to access the GitHub repo for the configs:

```plaintext
spring.application.name=config-server
server.port=8888
spring.cloud.config.server.git.uri=https://github.com/john-amiscaray/MicroservicesClassroomConfigs
# Set the GitHub username and access token using environment variables
spring.cloud.config.server.git.username=${GITHUB_USER}
spring.cloud.config.server.git.password=${GITHUB_REPO_TOKEN}
```

Now, we can configure our other microservices' `application.properties` to import configurations from our config server like so:

```plaintext
spring.config.import=configserver:
# Same as the spring.application.name property of our config service
spring.cloud.config.discovery.service-id=config-service
spring.cloud.config.discovery.enabled=true
```

Along with that, we also need to add a `spring-cloud-starter-config` dependency in our root pom.xml for all of our services:

```xml
 <dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-config</artifactId>
 </dependency>
```

Now, we can start up Consul and our microservices and see that our Student Service, API Gateway, and Course Service applications have debug-level logging in the console:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741902963209/e6963c8a-d4ee-419e-bd6d-71ba56fb7bfa.png align="center")

### Importing Microservice-Specific Configs

With our config server and our Git repository, we can also import configs for specific microservices. Within the GitHub repository containing our configs, let’s create new *course-service* and *student-service* directories with `course-service.properties` and `student-service.properties` files for our Course Service and Student Service respectively. We name these property files the exact same as the names of the services (listed in their respective `application.properties` files) so that the config server will know what to do with them. After adding these new files, the directory structure would look like so:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741909311568/f50cc477-231c-42b7-9dd6-38d066afed07.png align="left")

Within each properties file, let’s configure the data sources for its respective microservice:

```plaintext
# student-service configuration
spring.datasource.url=jdbc:mysql://localhost:3306/student
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=password
spring.jpa.hibernate.ddl-auto=create-drop
```

```plaintext
# course-service configuration
spring.datasource.url=jdbc:mysql://localhost:3306/course
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=password
spring.jpa.hibernate.ddl-auto=create-drop
```

After that, we need to update the `application.properties` file in our config server. These new properties specify subdirectories in our GitHub repository where configs can be:

```plaintext
spring.cloud.config.server.git.search-paths[0]=course-service
spring.cloud.config.server.git.search-paths[1]=student-service
```

With all that, we can commit to our GitHub repository, remove the configuration from the microservices' `resources/application.properties` files, re-run the microservices, and see that these data source configurations are being imported from the config server!

### Profile Specific Configuration

As you might expect, we can create Spring profile-specific configurations for all our microservices. As you'd normally do for a traditional Spring application, we can define property files with a _"-dev"_ suffix for configurations to use in a _dev_ profile:

```plaintext
# student-service-dev.properties

spring.datasource.url=jdbc:h2:mem:student
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
spring.jpa.hibernate.ddl-auto=create-drop
```

```plaintext
# course-service-dev.properties

spring.datasource.url=jdbc:h2:mem:course
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
spring.jpa.hibernate.ddl-auto=create-drop
```

```plaintext
# application-dev.properties

logging.level.root=DEBUG
```

```plaintext
# application.properties

logging.level.root=INFO
```

With these new files, our repository should look like so:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741918309533/529bc9de-e4d4-4cdc-a5c6-6824521e27dd.png align="left")

Once we run all our services with the *dev* profile, you'll see that our microservices have debug-level logging and connect to H2 databases.

## Conclusion

In this guide, we learned about what config servers are in a microservice architecture and how we can implement them with Spring Cloud. To review the work we did, you can have a look at the final code on [GitHub](https://github.com/john-amiscaray/MicroservicesClassroomExample/tree/config-server). Happy coding!
