Backend Development 23 min read

How to Build and Secure a Spring Boot Admin Dashboard with Eureka Integration

This tutorial walks through setting up Spring Boot Admin as a monitoring server and client, integrating it with Eureka for service discovery, adding Spring Security for authentication, and configuring email and custom notifications, complete with Maven and YAML configurations and Java code examples.

macrozheng
macrozheng
macrozheng
How to Build and Secure a Spring Boot Admin Dashboard with Eureka Integration

What is Spring Boot Admin?

Spring Boot Admin is an open‑source community project for managing and monitoring Spring Boot applications. Clients register with the Admin Server via HTTP or a Spring Cloud registry (e.g., Eureka, Consul). The UI, built with Vue.js, displays health status, JVM and memory metrics, Micrometer metrics, datasource and cache metrics, build information, log files, environment properties, Spring Boot configuration properties, JMX beans, thread dumps, HTTP traces, audit events, scheduled tasks, active sessions, Flyway/Liquibase migrations, heap dumps, and supports status change notifications via email, Slack, HipChat, etc.

Display health status

Show detailed metrics (JVM, memory, micrometer.io, datasource, cache)

Show build information

Download log files

View JVM system and environment properties

View Spring Boot configuration properties

Support Spring Cloud's /postable, /env, and /refresh endpoints

Easy log level management

Interact with JMX beans

View thread dumps

View HTTP traces

View audit events

View HTTP endpoints

View scheduled tasks

View and delete active sessions (spring‑session)

View Flyway/Liquibase migrations

Download heap dumps

Status change notifications (email, Slack, HipChat, …)

Non‑persistent event log for status changes

Getting Started

1. Create Spring Boot Admin Server

pom.xml

<code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;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"&gt;
    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
    &lt;parent&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;
        &lt;version&gt;2.1.0.RELEASE&lt;/version&gt;
        &lt;relativePath/&gt;
    &lt;/parent&gt;
    &lt;groupId&gt;com.gf&lt;/groupId&gt;
    &lt;artifactId&gt;admin-server&lt;/artifactId&gt;
    &lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;
    &lt;properties&gt;
        &lt;java.version&gt;1.8&lt;/java.version&gt;
        &lt;spring-boot-admin.version&gt;2.1.0&lt;/spring-boot-admin.version&gt;
    &lt;/properties&gt;
    &lt;dependencies&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;de.codecentric&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-admin-starter-server&lt;/artifactId&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
            &lt;scope&gt;test&lt;/scope&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;
    &lt;dependencyManagement&gt;
        &lt;dependencies&gt;
            &lt;dependency&gt;
                &lt;groupId&gt;de.codecentric&lt;/groupId&gt;
                &lt;artifactId&gt;spring-boot-admin-dependencies&lt;/artifactId&gt;
                &lt;version&gt;${spring-boot-admin.version}&lt;/version&gt;
                &lt;type&gt;pom&lt;/type&gt;
                &lt;scope&gt;import&lt;/scope&gt;
            &lt;/dependency&gt;
        &lt;/dependencies&gt;
    &lt;/dependencyManagement&gt;
    &lt;build&gt;
        &lt;plugins&gt;
            &lt;plugin&gt;
                &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
                &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
            &lt;/plugin&gt;
        &lt;/plugins&gt;
    &lt;/build&gt;
&lt;/project&gt;</code>

application.yml

<code>spring:
  application:
    name: admin-server
server:
  port: 8769</code>

AdminServerApplication

<code>@SpringBootApplication
@EnableAdminServer
public class AdminServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(AdminServerApplication.class, args);
    }
}</code>

2. Create Spring Boot Admin Client

pom.xml

<code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;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"&gt;
    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
    &lt;parent&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;
        &lt;version&gt;2.1.0.RELEASE&lt;/version&gt;
        &lt;relativePath/&gt;
    &lt;/parent&gt;
    &lt;groupId&gt;com.gf&lt;/groupId&gt;
    &lt;artifactId&gt;admin-client&lt;/artifactId&gt;
    &lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;
    &lt;properties&gt;
        &lt;java.version&gt;1.8&lt;/java.version&gt;
        &lt;spring-boot-admin.version&gt;2.1.0&lt;/spring-boot-admin.version&gt;
    &lt;/properties&gt;
    &lt;dependencies&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;de.codecentric&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-admin-starter-client&lt;/artifactId&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
            &lt;scope&gt;test&lt;/scope&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;
    &lt;dependencyManagement&gt;
        &lt;dependencies&gt;
            &lt;dependency&gt;
                &lt;groupId&gt;de.codecentric&lt;/groupId&gt;
                &lt;artifactId&gt;spring-boot-admin-dependencies&lt;/artifactId&gt;
                &lt;version&gt;${spring-boot-admin.version}&lt;/version&gt;
                &lt;type&gt;pom&lt;/type&gt;
                &lt;scope&gt;import&lt;/scope&gt;
            &lt;/dependency&gt;
        &lt;/dependencies&gt;
    &lt;/dependencyManagement&gt;
    &lt;build&gt;
        &lt;plugins&gt;
            &lt;plugin&gt;
                &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
                &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
            &lt;/plugin&gt;
        &lt;/plugins&gt;
    &lt;/build&gt;
&lt;/project&gt;</code>

application.yml

<code>spring:
  application:
    name: admin-client
  boot:
    admin:
      client:
        url: http://localhost:8769
server:
  port: 8768
management:
  endpoints:
    web:
      exposure:
        include: '*'
  endpoint:
    health:
      show-details: ALWAYS</code>

AdminClientApplication

<code>@SpringBootApplication
public class AdminClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(AdminClientApplication.class, args);
    }
}</code>

Run both projects and open

Spring Boot Admin UI
Spring Boot Admin UI

Integrating Eureka

1. Create sc-eureka-server

pom.xml

<code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;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"&gt;
    ... (same structure as previous pom, adding spring-cloud-starter-netflix-eureka-client) ...
&lt;/project&gt;</code>

application.yml

<code>spring:
  application:
    name: sc-eureka-server
server:
  port: 8761
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
    register-with-eureka: false
    fetch-registry: false
management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: ALWAYS</code>

ScEurekaServerApplication

<code>@SpringBootApplication
@EnableEurekaServer
public class ScEurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ScEurekaServerApplication.class, args);
    }
}</code>

2. Create sc-admin-server (Spring Boot Admin Server with Eureka)

pom.xml

<code>(pom similar to admin‑server but adds spring-cloud-starter-netflix-eureka-client)</code>

application.yml

<code>spring:
  application:
    name: admin-server
server:
  port: 8769
eureka:
  client:
    registryFetchIntervalSeconds: 5
    service-url:
      defaultZone: ${EUREKA_SERVICE_URL:http://localhost:8761}/eureka/
  instance:
    leaseRenewalIntervalInSeconds: 10
    health-check-url-path: /actuator/health
management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: ALWAYS</code>

ScAdminServerApplication

<code>@SpringBootApplication
@EnableAdminServer
@EnableDiscoveryClient
public class ScAdminServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ScAdminServerApplication.class, args);
    }
}</code>

3. Create sc-admin-client (Spring Boot Admin Client with Eureka)

pom.xml

<code>(pom adds spring-boot-admin-starter-client and spring-cloud-starter-netflix-eureka-client)</code>

application.yml

<code>spring:
  application:
    name: sc-admin-client
eureka:
  instance:
    leaseRenewalIntervalInSeconds: 10
    health-check-url-path: /actuator/health
  client:
    registryFetchIntervalSeconds: 5
    service-url:
      defaultZone: ${EUREKA_SERVICE_URL:http://localhost:8761}/eureka/
management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: ALWAYS
server:
  port: 8762</code>

ScAdminClientApplication

<code>@SpringBootApplication
@EnableDiscoveryClient
public class ScAdminClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(ScAdminClientApplication.class, args);
    }
}</code>

After starting the three services, visit

Admin UI with Eureka
Admin UI with Eureka

to see the auto‑registered applications.

Integrating Spring Security

Add the security starter to the admin‑server pom:

<code>&lt;dependency&gt;
    &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
    &lt;artifactId&gt;spring-boot-starter-security&lt;/artifactId&gt;
&lt;/dependency&gt;</code>

Configure username and password in

application.yml

and expose them via Eureka metadata:

<code>spring:
  security:
    user:
      name: "admin"
      password: "admin"
eureka:
  instance:
    metadata-map:
      user.name: ${spring.security.user.name}
      user.password: ${spring.security.user.password}</code>

Create a security configuration class:

<code>@Configuration
public class SecuritySecureConfig extends WebSecurityConfigurerAdapter {
    private final String adminContextPath;
    public SecuritySecureConfig(AdminServerProperties adminServerProperties) {
        this.adminContextPath = adminServerProperties.getContextPath();
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
        successHandler.setTargetUrlParameter("redirectTo");
        successHandler.setDefaultTargetUrl(adminContextPath + "/");
        http.authorizeRequests()
            .antMatchers(adminContextPath + "/assets/**").permitAll()
            .antMatchers(adminContextPath + "/login").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and()
            .logout().logoutUrl(adminContextPath + "/logout").and()
            .httpBasic();
    }
}</code>

Access

http://localhost:8769/

and you will be prompted for the credentials (admin / admin).

Notifications

1. Email Notification

Add the mail starter to the admin‑server pom:

<code>&lt;dependency&gt;
    &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
    &lt;artifactId&gt;spring-boot-starter-mail&lt;/artifactId&gt;
&lt;/dependency&gt;</code>

Configure mail properties and notification recipients in

application.yml

:

<code>spring:
  mail:
    host: smtp.163.com
    username: [email protected]
    password: xxxx
    properties:
      mail:
        smtp:
          auth: true
          starttls:
            enable: true
            required: true
  boot:
    admin:
      notify:
        mail:
          from: [email protected]
          to: [email protected]</code>

Optionally increase the monitor read timeout or disable unused health checks to avoid repeated offline notifications:

<code># Increase timeout (ms)
spring.boot.admin.monitor.read-timeout=20000
# Disable unimportant health checks
management.health.db.enabled=false
management.health.mail.enabled=false
management.health.redis.enabled=false
management.health.mongo.enabled=false</code>

2. Custom Notification

Implement a custom notifier by extending

AbstractStatusChangeNotifier

:

<code>@Component
public class CustomNotifier extends AbstractStatusChangeNotifier {
    private static final Logger LOGGER = LoggerFactory.getLogger(CustomNotifier.class);
    public CustomNotifier(InstanceRepository repository) {
        super(repository);
    }
    @Override
    protected Mono<Void> doNotify(InstanceEvent event, Instance instance) {
        return Mono.fromRunnable(() -> {
            if (event instanceof InstanceStatusChangedEvent) {
                String status = ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus();
                switch (status) {
                    case "DOWN":
                        System.out.println("Send DOWN notification");
                        break;
                    case "OFFLINE":
                        System.out.println("Send OFFLINE notification");
                        break;
                    case "UP":
                        System.out.println("Send UP notification");
                        break;
                    case "UNKNOWN":
                        System.out.println("Send UNKNOWN notification");
                        break;
                    default:
                        break;
                }
            } else {
                LOGGER.info("Instance {} ({}) {}", instance.getRegistration().getName(), event.getInstance(), event.getType());
            }
        });
    }
}</code>

Source code repository: GitHub

JavamonitoringSpring BootEurekaSpring SecuritySpring Boot Admin
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.