1. What is Spring Boot Admin?

codecentric’s Spring Boot Admin is a community project to manage and monitor your Spring Boot ® applications. The applications register with our Spring Boot Admin Client (via HTTP) or are discovered using Spring Cloud ® (e.g. Eureka, Consul). The UI is just a Vue.js application on top of the Spring Boot Actuator endpoints.

2. Getting started

2.1. Setting up Spring Boot Admin Server

First, you need to setup your server. To do this just setup a simple boot project (using start.spring.io). As Spring Boot Admin Server is capable of running as servlet or webflux application, you need to decide on this and add the according Spring Boot Starter. In this example we’re using the servlet web starter.

  1. Add Spring Boot Admin Server starter to your dependencies:

    pom.xml
    <dependency>
        <groupId>de.codecentric</groupId>
        <artifactId>spring-boot-admin-starter-server</artifactId>
        <version>2.2.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
  2. Pull in the Spring Boot Admin Server configuration via adding @EnableAdminServer to your configuration:

    @Configuration
    @EnableAutoConfiguration
    @EnableAdminServer
    public class SpringBootAdminApplication {
        public static void main(String[] args) {
            SpringApplication.run(SpringBootAdminApplication.class, args);
        }
    }
If you want to setup the Spring Boot Admin Server via war-deployment in a servlet-container, please have a look at the spring-boot-admin-sample-war.

See also the spring-boot-admin-sample-servlet project, which also adds security.

2.2. Registering Client Applications

To register your application at the SBA Server, you can either include the SBA Client or use Spring Cloud Discovery (e.g. Eureka, Consul, …​). There is also a simple option using a static configuration on the SBA Server side.

2.2.1. Spring Boot Admin Client

Each application that wants to register has to include the Spring Boot Admin Client. In order to secure the endpoints, also add the spring-boot-starter-security.

  1. Add spring-boot-admin-starter-client to your dependencies:

    pom.xml
    <dependency>
        <groupId>de.codecentric</groupId>
        <artifactId>spring-boot-admin-starter-client</artifactId>
        <version>2.2.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
  2. Enable the SBA Client by configuring the URL of the Spring Boot Admin Server:

    application.properties
    spring.boot.admin.client.url=http://localhost:8080  (1)
    management.endpoints.web.exposure.include=*  (2)
    1 The URL of the Spring Boot Admin Server to register at.
    2 As with Spring Boot 2 most of the endpoints aren’t exposed via http by default, we expose all of them. For production you should carefully choose which endpoints to expose.
  3. Make the actuator endpoints accessible:

    @Configuration
    public static class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests().anyRequest().permitAll()  (1)
                .and().csrf().disable();
        }
    }
    1 For the sake of brevity we’re disabling the security for now. Have a look at the security section on how to deal with secured endpoints.

2.2.2. Spring Cloud Discovery

If you already use Spring Cloud Discovery for your applications you don’t need the SBA Client. Just add a DiscoveryClient to Spring Boot Admin Server, the rest is done by our AutoConfiguration.

The following steps uses Eureka, but other Spring Cloud Discovery implementations are supported as well. There are examples using Consul and Zookeeper.

Also, have a look at the Spring Cloud documentation.

  1. Add spring-cloud-starter-eureka to your dependencies:

    pom.xml
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
  2. Enable discovery by adding @EnableDiscoveryClient to your configuration:

    @Configuration
    @EnableAutoConfiguration
    @EnableDiscoveryClient
    @EnableAdminServer
    public class SpringBootAdminApplication {
        public static void main(String[] args) {
            SpringApplication.run(SpringBootAdminApplication.class, args);
        }
    
        @Configuration
        public static class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter {
            @Override
            protected void configure(HttpSecurity http) throws Exception {
                http.authorizeRequests().anyRequest().permitAll()  (1)
                    .and().csrf().disable();
            }
        }
    }
    1 For the sake of brevity we’re disabling the security for now. Have a look at the security section on how to deal with secured endpoints.
  3. Tell the Eureka client where to find the service registry:

    application.yml
    eureka:   (1)
      instance:
        leaseRenewalIntervalInSeconds: 10
        health-check-url-path: /actuator/health
        metadata-map:
          startup: ${random.int}    #needed to trigger info and endpoint update after restart
      client:
        registryFetchIntervalSeconds: 5
        serviceUrl:
          defaultZone: ${EUREKA_SERVICE_URL:http://localhost:8761}/eureka/
    
    management:
      endpoints:
        web:
          exposure:
            include: "*"  (2)
      endpoint:
        health:
          show-details: ALWAYS
    1 Configuration section for the Eureka client
    2 As with Spring Boot 2 most of the endpoints aren’t exposed via http by default, we expose all of them. For production you should carefully choose which endpoints to expose.
You can include the Spring Boot Admin Server to your Eureka server. Setup everything as described above and set spring.boot.admin.context-path to something different than "/" so that the Spring Boot Admin Server UI won’t clash with Eureka’s one.

3. Client Applications

3.1. Show Version in Application List

For Spring Boot applications the easiest way to show the version, is to use the build-info goal from the spring-boot-maven-plugin, which generates the META-INF/build-info.properties. See also the Spring Boot Reference Guide.

For non-Spring Boot applications you can either add a version or build.version to the registration metadata and the version will show up in the application list.

pom.xml
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <executions>
                <execution>
                    <goals>
                        <goal>build-info</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

3.2. JMX-Bean Management

To interact with JMX-beans in the admin UI you have to include Jolokia in your application. As Jolokia is servlet based there is no support for reactive applications. In case you are using the spring-boot-admin-starter-client it will be pulled in for you, if not add Jolokia to your dependencies. With Spring Boot 2.2.0 you might want to set spring.jmx.enabled=true if you want to expose Spring beans via JMX.

pom.xml
<dependency>
    <groupId>org.jolokia</groupId>
    <artifactId>jolokia-core</artifactId>
</dependency>

3.3. Logfile Viewer

By default the logfile is not accessible via actuator endpoints and therefore not visible in Spring Boot Admin. In order to enable the logfile actuator endpoint you need to configure Spring Boot to write a logfile, either by setting logging.path or logging.file.

Spring Boot Admin will detect everything that looks like an URL and render it as hyperlink.

ANSI color-escapes are also supported. You need to set a custom file log pattern as Spring Boot’s default one doesn’t use colors.

application.properties
logging.file=/var/log/sample-boot-application.log (1)
logging.pattern.file=%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(${PID}){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wEx (2)
1 Destination the logfile is written to. Enables the logfile actuator endpoint.
2 File log pattern using ANSI colors.

3.4. Show Tags per Instance

Tags are a way to add visual markers per instanace, they will appear in the application list as well as in the instance view. By default no tags are added to instances, and it’s up to the client to specify the desired tags by adding the information to the metadata or info endpoint.

application.properties
#using the metadata
spring.boot.admin.client.instance.metadata.tags.environment=test

#using the info endpoint
info.tags.environment=test

3.5. Spring Boot Admin Client

The Spring Boot Admin Client registers the application at the admin server. This is done by periodically doing a HTTP post request to the SBA Server providing information about the application. It also adds Jolokia to your application, so that JMX-beans are accessible via HTTP.

There are plenty of properties to influence the way how the SBA Client registers your application. In case that doesn’t fit your needs, you can provide your own ApplicationFactory implementation.
Table 1. Spring Boot Admin Client configuration options
Property name Description Default value

spring.boot.admin.client.enabled

Enables the Spring Boot Admin Client.

true

spring.boot.admin.client.url

Comma separated ordered list of URLs of the Spring Boot Admin server to register at. This triggers the AutoConfiguration. Mandatory.

spring.boot.admin.client.api-path

Http-path of registration endpoint at your admin server.

"instances"

spring.boot.admin.client.username
spring.boot.admin.client.password

Username and password in case the SBA Server api is protected with HTTP Basic authentication.

spring.boot.admin.client.period

Interval for repeating the registration (in ms).

10,000

spring.boot.admin.client.connect-timeout

Connect timeout for the registration (in ms).

5,000

spring.boot.admin.client.read-timeout

Read timeout for the registration (in ms).

5,000

spring.boot.admin.client.auto-registration

If set to true the periodic task to register the application is automatically scheduled after the application is ready.

true

spring.boot.admin.client.auto-deregistration

Switch to enable auto-deregistration at Spring Boot Admin server when context is closed. If the value is unset the feature is active if a running CloudPlatform was detected.

null

spring.boot.admin.client.register-once

If set to true the client will only register against one admin server (in order defined by spring.boot.admin.instance.url); if that admin server goes down, will automatically register against the next admin server. If false, will register against all admin servers.

true

spring.boot.admin.client.instance.health-url

Health-url to register with. Can be overridden in case the reachable URL is different (e.g. Docker). Must be unique in registry.

Guessed based on management-url and endpoints.health.id.

spring.boot.admin.client.instance.management-base-url

Base url for computing the management-url to register with. The path is inferred at runtime, and appended to the base url.

Guessed based on management.port, service-url and server.servlet-path.

spring.boot.admin.client.instance.management-url

Management-url to register with. Can be overridden in case the reachable url is different (e.g. Docker).

Guessed based on management-base-url and management.context-path.

spring.boot.admin.client.instance.service-base-url

Base url for computing the service-url to register with. The path is inferred at runtime, and appended to the base url.

Guessed based on hostname, server.port.

spring.boot.admin.client.instance.service-url

Service-url to register with. Can be overridden in case the reachable url is different (e.g. Docker).

Guessed based on service-base-url and server.context-path.

spring.boot.admin.client.instance.name

Name to register with.

${spring.application.name} if set, "spring-boot-application" otherwise.

spring.boot.admin.client.instance.prefer-ip

Use the ip-address rather then the hostname in the guessed urls. If server.address / management.address is set, it get used. Otherwise the IP address returned from InetAddress.getLocalHost() gets used.

false

spring.boot.admin.client.instance.metadata.*

Metadata key-value-pairs to be associated with this instance.

spring.boot.admin.client.instance.metadata.tags.*

Tags as key-value-pairs to be associated with this instance.

Table 2. Instance metadata options
Key Value Default value

user.name
user.password

Credentials being used to access the endpoints.

4. Spring Boot Admin Server

4.1. Running Behind a Front-end Proxy Server

In case the Spring Boot Admin server is running behind a reverse proxy, it may be requried to configure the public url where the server is reachable via (spring.boot.admin.ui.public-url). In addition when the reverse proxy terminates the https connection, it may be necessary to configure server.use-forward-headers=true (also see Spring Boot Reference Guide).

4.2. Configuration Options

Property name Description Default value

spring.boot.admin.context-path

The context-path prefixes the path where the Admin Server’s statics assets and API should be served. Relative to the Dispatcher-Servlet.

spring.boot.admin.monitor.status-interval

Time interval to check the status of instances.

10,000ms

spring.boot.admin.monitor.status-lifetime

Lifetime of status. The status won’t be updated as long the last status isn’t expired.

10,000ms

spring.boot.admin.monitor.info-interval

Time interval to check the info of instances.

1m

spring.boot.admin.monitor.info-lifetime

Lifetime of info. The info won’t be updated as long the last info isn’t expired.

1m

spring.boot.admin.monitor.default-timeout

Default timeout when making requests. Individual values for specific endpoints can be overridden using spring.boot.admin.monitor.timeout.*.

10,000

spring.boot.admin.monitor.timeout.*

Key-Value-Pairs with the timeout per endpointId. Defaults to default-timeout.

spring.boot.admin.monitor.default-retries

Default number of retries for failed requests. Modifying requests (PUT, POST, PATCH, DELETE) are never retried. Individual values for specific endpoints can be overridden using spring.boot.admin.monitor.retries.*.

0

spring.boot.admin.monitor.retries.*

Key-Value-Pairs with the number of retries per endpointId. Defaults to default-retries. Modifying requests (PUT, POST, PATCH, DELETE) are never retried.

spring.boot.admin.metadata-keys-to-sanitize

Metadata values for the keys matching these regex patterns will be sanitized in all json output.

".password$", ".*secret$", ".*key$", ".$token$", ".credentials.", ".*vcap_services$"

spring.boot.admin.probed-endpoints

For Spring Boot 1.x client applications SBA probes for the specified endpoints using an OPTIONS request. If the path differs from the id you can specify this as id:path (e.g. health:ping)..

"health", "env", "metrics", "httptrace:trace", "threaddump:dump", "jolokia", "info", "logfile", "refresh", "flyway", "liquibase", "heapdump", "loggers", "auditevents"

spring.boot.admin.instance-proxy.ignored-headers

Headers not to be forwarded when making requests to clients.

`"Cookie", "Set-Cookie", "Authorization"

spring.boot.admin.ui.public-url

Base url to use to build the base href in the ui.

If running behind a reverse proxy (using path rewriting) this can be used to make correct self references. If the host/port is omitted it will be inferred from the request.

spring.boot.admin.ui.brand

Brand to be shown in the navbar.

"<img src="assets/img/icon-spring-boot-admin.svg"><span>Spring Boot Admin</span>"

spring.boot.admin.ui.title

Page-Title to be shown.

"Spring Boot Admin"

spring.boot.admin.ui.login-icon

Icon used as image on login page.

"assets/img/icon-spring-boot-admin.svg"

spring.boot.admin.ui.favicon

Icon used as default favicon and icon for desktop notifications.

"assets/img/favicon.png"

spring.boot.admin.ui.favicon-danger

Icon used as favicon when one or more service is down and for desktop notifications.

"assets/img/favicon-danger.png"

spring.boot.admin.ui.remember-me-enabled

Switch to show/hide the remember-me checkbox on the login page.

true

4.3. Spring Cloud Discovery

The Spring Boot Admin Server can use Spring Clouds DiscoveryClient to discover applications. The advantage is that the clients don’t have to include the spring-boot-admin-starter-client. You just have to add a DiscoveryClient implementation to your admin server - everything else is done by AutoConfiguration.

4.3.1. Static Configuration using SimpleDiscoveryClient

Spring Cloud provides a SimpleDiscoveryClient. It allows you to specify client applications via static configuration:

pom.xml
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter</artifactId>
</dependency>
application.yml
spring:
  cloud:
    discovery:
      client:
        simple:
          instances:
            test:
              - uri: http://instance1.intern:8080
                metadata:
                  management.context-path: /actuator
              - uri: http://instance2.intern:8080
                metadata:
                  management.context-path: /actuator

4.3.2. Other DiscoveryClients

Spring Boot Admin supports all other implementations of Spring Cloud’s DiscoveryClient (Eureka, Zookeeper, Consul, …​). You need to add it to the Spring Boot Admin Server and configure it properly. An example setup using Eureka is shown above.

4.3.3. Converting ServiceInstances

The information from the service registry are converted by the ServiceInstanceConverter. Spring Boot Admin ships with a default and Eureka converter implementation. The correct one is selected by AutoConfiguration.

You can modify how the information from the registry is used to register the application by using SBA Server configuration options and instance metadata. The values from the metadata takes precedence over the server config. If the plenty of options don’t fit your needs you can provide your own ServiceInstanceConverter.
When using Eureka, the healthCheckUrl known to Eureka is used for health-checking, which can be set on your client using eureka.instance.healthCheckUrl.
Table 3. Instance metadata options
Key Value Default value

user.name
user.password

Credentials being used to access the endpoints.

management.address

The address is substituted in the service URL and will be used for accessing the actuator endpoints.

management.port

The port is substituted in the service URL and will be used for accessing the actuator endpoints.

management.context-path

The path is appended to the service URL and will be used for accessing the actuator endpoints.

${spring.boot.admin.discovery.converter.management-context-path}

health.path

The path is appended to the service URL and will be used for the health-checking. Ignored by the EurekaServiceInstanceConverter.

${spring.boot.admin.discovery.converter.health-endpoint}

Table 4. Discovery configuration options
Property name Description Default value

spring.boot.admin.discovery.enabled

Enables the DiscoveryClient-support for the admin server.

true

spring.boot.admin.discovery.converter.management-context-path

Will be appended to the service-url of the discovered service when the management-url is converted by the DefaultServiceInstanceConverter.

/actuator

spring.boot.admin.discovery.converter.health-endpoint-path

Will be appended to the management-url of the discovered service when the health-url is converted by the DefaultServiceInstanceConverter.

"health"

spring.boot.admin.discovery.ignored-services

This services will be ignored when using discovery and not registered as application. Supports simple patterns (e.g. "foo*", "*bar", "foo*bar*").

spring.boot.admin.discovery.services

This services will be included when using discovery and registered as application. Supports simple patterns (e.g. "foo*", "*bar", "foo*bar*").

"*"

spring.boot.admin.discovery.ignored-instances-metadata

Instances of services will be ignored if they contain at least one metadata item that matches this list. (e.g. "discoverable=false")

spring.boot.admin.discovery.instances-metadata

Instances of services will be included if they contain at least one metadata item that matches this list. (e.g. "discoverable=true")

4.3.4. CloudFoundry

If you are deploying your applications to CloudFoundry then vcap.application.application_id and vcap.application.instance_index must be added to the metadata for proper registration of applications with Spring Boot Admin Server. Here is a sample configuration for Eureka:

application.yml
eureka:
  instance:
    hostname: ${vcap.application.uris[0]}
    nonSecurePort: 80
    metadata-map:
      applicationId: ${vcap.application.application_id}
      instanceId: ${vcap.application.instance_index}

4.4. Clustering

Spring Boot Admin Server supports cluster replication via Hazelcast. It is automatically enabled when a HazelcastConfig- or HazelcastInstance-Bean is present. You can also configure the Hazelcast instance to be persistent, to keep the status over restarts. Also have a look at the Spring Boot support for Hazelcast.

  1. Add Hazelcast to your dependencies:

    pom.xml
    <dependency>
        <groupId>com.hazelcast</groupId>
        <artifactId>hazelcast</artifactId>
    </dependency>
  2. Instantiate a HazelcastConfig:

    @Bean
    public Config hazelcastConfig() {
        //This map is used to store the events.
        //It should be configured to reliably hold all the data,
        //Spring Boot Admin will compact the events, if there are too many
        MapConfig eventStoreMap = new MapConfig(DEFAULT_NAME_EVENT_STORE_MAP)
            .setInMemoryFormat(InMemoryFormat.OBJECT)
            .setBackupCount(1)
            .setEvictionPolicy(EvictionPolicy.NONE)
            .setMergePolicyConfig(new MergePolicyConfig(PutIfAbsentMapMergePolicy.class.getName(), 100));
    
        //This map is used to deduplicate the notifications.
        //If data in this map gets lost it should not be a big issue as it will atmost lead to
        //the same notification to be sent by multiple instances
        MapConfig sentNotificationsMap = new MapConfig(DEFAULT_NAME_SENT_NOTIFICATIONS_MAP)
            .setInMemoryFormat(InMemoryFormat.OBJECT)
            .setBackupCount(1)
            .setEvictionPolicy(EvictionPolicy.LRU)
            .setMergePolicyConfig(new MergePolicyConfig(PutIfAbsentMapMergePolicy.class.getName(), 100));
    
        Config config = new Config();
        config.addMapConfig(eventStoreMap);
        config.addMapConfig(sentNotificationsMap);
        config.setProperty("hazelcast.jmx", "true");
    
        //WARNING: This setups a local cluster, you change it to fit your needs.
        config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false);
        TcpIpConfig tcpIpConfig = config.getNetworkConfig().getJoin().getTcpIpConfig();
        tcpIpConfig.setEnabled(true);
        tcpIpConfig.setMembers(singletonList("127.0.0.1"));
        return config;
    }
Table 5. Hazelcast configuration options
Property name Description Default value

spring.boot.admin.hazelcast.enabled

Enables the Hazelcast support

true

spring.boot.admin.hazelcast.event-store

Name of the Hazelcast-map to store the events

"spring-boot-admin-event-store"

spring.boot.admin.hazelcast.sent-notifications

Name of the Hazelcast-map used to deduplicate the notifications.

"spring-boot-admin-sent-notifications"

4.5. Notifications

4.5.1. Reminder Notifications

The RemindingNotifier sends reminders for down/offline applications, it delegates the sending of notifications to another notifier.

By default a reminder is triggered when a registered application changes to DOWN or OFFLINE. You can alter this behaviour via setReminderStatuses(). The reminder ends when either the status changes to a non-triggering status or the regarding application gets deregistered.

By default the reminders are sent every 10 minutes, to change this use setReminderPeriod(). The RemindingNotifier itself doesn’t start the background thread to send the reminders, you need to take care of this as shown in the given example below;

How to configure reminders
@Configuration
public class NotifierConfiguration {
    @Autowired
    private Notifier notifier;

    @Primary
    @Bean(initMethod = "start", destroyMethod = "stop")
    public RemindingNotifier remindingNotifier() {
        RemindingNotifier notifier = new RemindingNotifier(notifier, repository);
        notifier.setReminderPeriod(Duration.ofMinutes(10)); (1)
        notifier.setCheckReminderInverval(Duration.ofSeconds(10)); (2)
        return notifier;
    }
}
1 The reminders will be sent every 10 minutes.
2 Schedules sending of due reminders every 10 seconds.

4.5.2. Filtering Notifications

The FilteringNotifier allows you to filter certain notification based on rules you can add/remove at runtime. It delegates the sending of notifications to another notifier.

If you add a FilteringNotifier to your ApplicationContext a RESTful interface on notifications/filter gets available.

This notifier is useful if you don’t want receive notifications when deploying your applications. Before stopping the application you can add an (expiring) filter either via a POST request.

How to configure filtering
@Configuration
public class NotifierConfig {
    private final InstanceRepository repository;
    private final ObjectProvider<List<Notifier>> otherNotifiers;

    public NotifierConfig(InstanceRepository repository, ObjectProvider<List<Notifier>> otherNotifiers) {
        this.repository = repository;
        this.otherNotifiers = otherNotifiers;
    }

    @Bean
    public FilteringNotifier filteringNotifier() { (1)
        CompositeNotifier delegate = new CompositeNotifier(this.otherNotifiers.getIfAvailable(Collections::emptyList));
        return new FilteringNotifier(delegate, this.repository);
    }

    @Primary
    @Bean(initMethod = "start", destroyMethod = "stop")
    public RemindingNotifier remindingNotifier() { (2)
        RemindingNotifier notifier = new RemindingNotifier(filteringNotifier(), this.repository);
        notifier.setReminderPeriod(Duration.ofMinutes(10));
        notifier.setCheckReminderInverval(Duration.ofSeconds(10));
        return notifier;
    }
}
1 Add the FilteringNotifier bean using a delegate (e.g. MailNotifier when configured)
2 Add the RemindingNotifier as primary bean using the FilteringNotifier as delegate.
This example combines the reminding and filtering notifiers. This allows you to get notifications after the deployed application hasn’t restarted in a certain amount of time (until the filter expires).

4.5.3. Mail Notifications

Mail notifications will be delivered as HTML emails rendered using Thymeleaf templates. To enable Mail notifications, configure a JavaMailSender using spring-boot-starter-mail and set a recipient.

Sample Mail Notification
Figure 1. Sample Mail Notification
To prevent disclosure of sensitive information, the default mail template doesn’t show any metadata of the instance. If you want to you show some of the metadata you can use a custom template.
  1. Add spring-boot-starter-mail to your dependencies:

    pom.xml
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-mail</artifactId>
    </dependency>
  2. Configure a JavaMailSender

    application.properties
    spring.mail.host=smtp.example.com
    spring.boot.admin.notify.mail.to=admin@example.com
  3. Configure the mail with the options below

    Table 6. Mail notifications configuration options
    Property name Description Default value

    spring.boot.admin.notify.mail.enabled

    Enable mail notifications

    true

    spring.boot.admin.notify.mail.ignore-changes

    Comma-delimited list of status changes to be ignored. Format: "<from-status>:<to-status>". Wildcards allowed.

    "UNKNOWN:UP"

    spring.boot.admin.notify.mail.template

    Resource path to the Thymeleaf template used for rendering.

    "classpath:/META-INF/spring-boot-admin-server/mail/status-changed.html"

    spring.boot.admin.notify.mail.to

    Comma-delimited list of mail recipients

    "root@localhost"

    spring.boot.admin.notify.mail.cc

    Comma-delimited list of carbon-copy recipients

    spring.boot.admin.notify.mail.from

    Mail sender

    "Spring Boot Admin <noreply@localhost>"

    spring.boot.admin.notify.mail.additional-properties

    Additional properties which can be accessed from the template

4.5.4. PagerDuty Notifications

To enable PagerDuty notifications you just have to add a generic service to your PagerDuty-account and set spring.boot.admin.notify.pagerduty.service-key to the service-key you received.

Table 7. PagerDuty notifications configuration options
Property name Description Default value

spring.boot.admin.notify.pagerduty.enabled

Enable mail notifications

true

spring.boot.admin.notify.pagerduty.ignore-changes

Comma-delimited list of status changes to be ignored. Format: "<from-status>:<to-status>". Wildcards allowed.

"UNKNOWN:UP"

spring.boot.admin.notify.pagerduty.service-key

Service-key to use for PagerDuty

spring.boot.admin.notify.pagerduty.url

The Pagerduty-rest-api url

"https://events.pagerduty.com/generic/2010-04-15/create_event.json"

spring.boot.admin.notify.pagerduty.description

Description to use in the event. SpEL-expressions are supported

"#{instance.registration.name}/#{instance.id} is #{instance.statusInfo.status}"

spring.boot.admin.notify.pagerduty.client

Client-name to use in the event

spring.boot.admin.notify.pagerduty.client-url

Client-url to use in the event

4.5.5. OpsGenie Notifications

To enable OpsGenie notifications you just have to add a new JSON Rest API integration to your OpsGenie account and set spring.boot.admin.notify.opsgenie.api-key to the apiKey you received.

Table 8. OpsGenie notifications configuration options
Property name Description Default value

spring.boot.admin.notify.opsgenie.enabled

Enable OpsGenie notifications

true

spring.boot.admin.notify.opsgenie.ignore-changes

Comma-delimited list of status changes to be ignored. Format: "<from-status>:<to-status>". Wildcards allowed.

"UNKNOWN:UP"

spring.boot.admin.notify.opsgenie.api-key

apiKey you received when creating the integration

spring.boot.admin.notify.opsgenie.url

OpsGenie Alert API url

"https://api.opsgenie.com/v2/alerts"

spring.boot.admin.notify.opsgenie.description

Description to use in the event. SpEL-expressions are supported

"#{instance.registration.name}/#{instance.id} is #{instance.statusInfo.status}"

spring.boot.admin.notify.opsgenie.actions

Comma separated list of actions that can be executed.

spring.boot.admin.notify.opsgenie.source

Field to specify source of alert. By default, it will be assigned to IP address of incoming request.

spring.boot.admin.notify.opsgenie.tags

Comma separated list of labels attached to the alert.

spring.boot.admin.notify.opsgenie.entity

The entity the alert is related to.

spring.boot.admin.notify.opsgenie.user

Default owner of the execution. If user is not specified, the system becomes owner of the execution.

4.5.6. Hipchat Notifications

To enable Hipchat notifications you need to create an API token on your Hipchat account and set the appropriate configuration properties.

Table 9. Hipchat notifications configuration options
Property name Description Default value

spring.boot.admin.notify.hipchat.enabled

Enable Hipchat notifications

true

spring.boot.admin.notify.hipchat.ignore-changes

Comma-delimited list of status changes to be ignored. Format: "<from-status>:<to-status>". Wildcards allowed.

"UNKNOWN:UP"

spring.boot.admin.notify.hipchat.url

The HipChat REST API (V2) URL

spring.boot.admin.notify.hipchat.auth-token

The API token with access to the notification room

spring.boot.admin.notify.hipchat.room-id

The ID or url-encoded name of the room to send notifications to

spring.boot.admin.notify.hipchat.notify

Whether the message should trigger a user notification

false

spring.boot.admin.notify.hipchat.description

Description to use in the event. SpEL-expressions are supported

"<strong>#{instance.registration.name}</strong>/#{instance.id} is <strong>#{event.statusInfo.status}</strong>"

4.5.7. Slack Notifications

To enable Slack notifications you need to add a incoming Webhook under custom integrations on your Slack account and configure it appropriately.

Table 10. Slack notifications configuration options
Property name Description Default value

spring.boot.admin.notify.slack.enabled

Enable Slack notifications

true

spring.boot.admin.notify.slack.ignore-changes

Comma-delimited list of status changes to be ignored. Format: "<from-status>:<to-status>". Wildcards allowed.

"UNKNOWN:UP"

spring.boot.admin.notify.slack.webhook-url

The Slack Webhook URL to send notifications to.

spring.boot.admin.notify.slack.channel

Optional channel name (without # at the beginning). If different than channel in Slack Webhooks settings

spring.boot.admin.notify.slack.icon

Optional icon name (without surrounding colons). If different than icon in Slack Webhooks settings

spring.boot.admin.notify.slack.username

Optional username to send notification if different than in Slack Webhooks settings

Spring Boot Admin

spring.boot.admin.notify.slack.message

Message to use in the event. SpEL-expressions and Slack markups are supported

"*#{instance.registration.name}* (#{instance.id}) is *#{event.statusInfo.status}*"

4.5.8. Let’s Chat Notifications

To enable Let’s Chat notifications you need to add the host url and add the API token and username from Let’s Chat

Table 11. Let’s Chat notifications configuration options
Property name Description Default value

spring.boot.admin.notify.letschat.enabled

Enable let´s Chat notifications

true

spring.boot.admin.notify.letschat.ignore-changes

Comma-delimited list of status changes to be ignored. Format: "<from-status>:<to-status>". Wildcards allowed.

"UNKNOWN:UP"

spring.boot.admin.notify.letschat.url

The let´s Chat Host URL to send notifications

spring.boot.admin.notify.letschat.room

the room where to send the messages

spring.boot.admin.notify.letschat.token

the token to access the let´s Chat API

spring.boot.admin.notify.letschat.username

The username for which the token was created

Spring Boot Admin

spring.boot.admin.notify.letschat.message

Message to use in the event. SpEL-expressions are supported

"*#{instance.registration.name}* (#{instance.id}) is *#{event.statusInfo.status}*"

4.5.9. Microsoft Teams Notifications

To enable Microsoft Teams notifications you need to setup a connector webhook url and set the appropriate configuration property.

Table 12. Microsoft Teams notifications configuration options
Property name Description Default value

spring.boot.admin.notify.ms-teams.enabled

Enable Microsoft Teams notifications

true

spring.boot.admin.notify.ms-teams.webhook-url

The Microsoft Teams webhook url to send the notifications to.

spring.boot.admin.notify.ms-teams.*

There are several options to customize the message title and color

4.5.10. Telegram Notifications

To enable Telegram notifications you need to create and authorize a telegram bot and set the appropriate configuration properties for auth-token and chat-id.

Table 13. Telegram notifications configuration options
Property name Description Default value

spring.boot.admin.notify.telegram.enabled

Enable Telegram notifications

true

spring.boot.admin.notify.telegram.auth-token

The token identifying und authorizing your Telegram bot (e.g. 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11).

spring.boot.admin.notify.telegram.chat-id

Unique identifier for the target chat or username of the target channel

spring.boot.admin.notify.telegram.disable-notify

If true users will receive a notification with no sound.

false

spring.boot.admin.notify.telegram.parse_mode

The parsing mode for the sent message. Currently `HTML' and 'Markdown' are supported.

'HTML'

spring.boot.admin.notify.telegram.message

Text to send. SpEL-expressions are supported.

"<strong>#{instance.registration.name}</strong>/#{instance.id} is <strong>#{event.statusInfo.status}</strong>"

4.5.11. Discord Notifications

To enable Discord notifications you need to create a webhook and set the appropriate configuration property.

Table 14. Discord notifications configuration options
Property name Description Default value

spring.boot.admin.notify.discord.enabled

Enable Discord notifications

true

spring.boot.admin.notify.discord.webhook-url

The Discord webhook url to send the notifications to.

spring.boot.admin.notify.discord.username

Optional username.

Default set in Discord

spring.boot.admin.notify.discord.avatar-url

Optional URL to avatar.

Default set in Discord

spring.boot.admin.notify.discord.tts

If the message is a text to speech message.

false

spring.boot.admin.notify.discord.message

Text to send. SpEL-expressions are supported.

"*#{instance.registration.name}* (#{instance.id}) is *#{event.statusInfo.status}*"

5. Security

5.1. Securing Spring Boot Admin Server

Since there are several approaches on solving authentication and authorization in distributed web applications Spring Boot Admin doesn’t ship a default one. By default spring-boot-admin-server-ui provides a login page and a logout button.

A Spring Security configuration for your server could look like this:

@Configuration
public class SecuritySecureConfig extends WebSecurityConfigurerAdapter {
    private final AdminServerProperties adminServer;

    public SecuritySecureConfig(AdminServerProperties adminServer) {
        this.adminServer = adminServer;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
        successHandler.setTargetUrlParameter("redirectTo");
        successHandler.setDefaultTargetUrl(this.adminServer.path("/"));

        http.authorizeRequests()
            .antMatchers(this.adminServer.path("/assets/**")).permitAll() (1)
            .antMatchers(this.adminServer.path("/login")).permitAll()
            .anyRequest().authenticated() (2)
            .and()
        .formLogin().loginPage(this.adminServer.path("/login")).successHandler(successHandler).and() (3)
        .logout().logoutUrl(this.adminServer.path("/logout")).and()
        .httpBasic().and() (4)
        .csrf()
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) (5)
            .ignoringAntMatchers(
                this.adminServer.path("/instances"), (6)
                this.adminServer.path("/actuator/**") (7)
            )
        .and()
        .rememberMe().key(UUID.randomUUID().toString()).tokenValiditySeconds(1209600);
        // @formatter:on
    }

    // Required to provide UserDetailsService for "remember functionality"
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("user")
                .password("{noop}password")
                .roles("USER");
    }
}
1 Grants public access to all static assets and the login page.
2 Every other request must be authenticated.
3 Configures login and logout.
4 Enables HTTP-Basic support. This is needed for the Spring Boot Admin Client to register.
5 Enables CSRF-Protection using Cookies
6 Disables CSRF-Protection for the endpoint the Spring Boot Admin Client uses to register.
7 Disables CSRF-Protection for the actuator endpoints.

In case you use the Spring Boot Admin Client, it needs the credentials for accessing the server:

application.yml
spring.boot.admin.client:
   username: sba-client
   password: s3cret

For a complete sample look at spring-boot-admin-sample-servlet.

If you protect the /instances endpoint don’t forget to configure the username and password on your SBA-Client using spring.boot.admin.client.username and spring.boot.admin.client.password.

5.2. Securing Client Actuator Endpoints

When the actuator endpoints are secured using HTTP Basic authentication the SBA Server needs credentials to access them. You can submit the credentials in the metadata when registering the application. The BasicAuthHttpHeaderProvider then uses this metadata to add the Authorization header to access your application’s actuator endpoints. You can provide your own HttpHeadersProvider to alter the behaviour (e.g. add some decryption) or add extra headers.

Submitting the credentials using SBA Client:

application.yml
spring.boot.admin.client:
    url: http://localhost:8080
    instance:
      metadata:
        user.name: ${spring.security.user.name}
        user.password: ${spring.security.user.password}

Submitting the credentials using Eureka:

application.yml
eureka:
  instance:
    metadata-map:
      user.name: ${spring.security.user.name}
      user.password: ${spring.security.user.password}
The SBA Server masks certain metadata in the HTTP interface to prevent leaking of sensitive information.
You should configure HTTPS for your SBA Server or (service registry) when submitting credentials via the metadata.
When using Spring Cloud Discovery, you must be aware that anybody who can query your service registry can obtain the credentials.
When using this approach the SBA Server decides whether or not the user can access the registered applications. There are more complex solutions possible (using OAuth2) to let the clients decide if the user can access the endpoints. For that please have a look at the samples in joshiste/spring-boot-admin-samples.

5.2.1. CSRF on Actuator Endpoints

Some of the actuator endpoints (e.g. /loggers) support POST requests. When using Spring Security you need to ignore the actuator endpoints for CSRF-Protection as the Spring Boot Admin Server currently lacks support.

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf()
        .ignoringAntMatchers("/actuator/**");
}

5.3. Using Mutual TLS

SBA Server can also use client certificates to authenticate when accessing the actuator endpoints. If a custom configured ClientHttpConnector bean is present, Spring Boot will automatically configure a WebClient.Builder using it, which will be used by Spring Boot Admin.

@Bean
public ClientHttpConnector customHttpClient() {
    SslContextBuilder sslContext = SslContextBuilder.forClient();
    //Your sslContext customizations go here
    HttpClient httpClient = HttpClient.create().secure(
        ssl -> ssl.sslContext(sslContext)
    );
    return new ReactorClientHttpConnector(httpClient);
}

6. Customizing

6.1. Custom Notifiers

You can add your own Notifiers by adding Spring Beans which implement the Notifier interface, at best by extending AbstractEventNotifier or AbstractStatusChangeNotifier.

public class CustomNotifier  extends AbstractEventNotifier {
    private static final Logger LOGGER = LoggerFactory.getLogger(LoggingNotifier.class);

    public CustomNotifier(InstanceRepository repository) {
        super(repository);
    }

    @Override
    protected Mono<Void> doNotify(InstanceEvent event, Instance instance) {
        return Mono.fromRunnable(() -> {
            if (event instanceof InstanceStatusChangedEvent) {
                LOGGER.info("Instance {} ({}) is {}", instance.getRegistration().getName(), event.getInstance(),
                    ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus());
            } else {
                LOGGER.info("Instance {} ({}) {}", instance.getRegistration().getName(), event.getInstance(),
                    event.getType());
            }
        });
    }
}

6.2. Injecting Custom HTTP Headers

In case you need to inject custom HTTP headers into the requests made to the monitored application’s actuator endpoints you can easily add a HttpHeadersProvider:

@Bean
public HttpHeadersProvider customHttpHeadersProvider() {
    return instance -> {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("X-CUSTOM", "My Custom Value");
        return httpHeaders;
    };
}

6.3. Intercepting Requests And Responses

You can intercept and modify requests and responses made to the monitored application’s actuator endpoints by implementing the InstanceExchangeFilterFunction interface. This can be useful for auditing or adding some extra security checks.

@Bean
public InstanceExchangeFilterFunction auditLog() {
    return (instance, request, next) -> next.exchange(request).doOnSubscribe(s -> {
        if (HttpMethod.DELETE.equals(request.method()) || HttpMethod.POST.equals(request.method())) {
            log.info("{} for {} on {}", request.method(), instance.getId(), request.url());
        }
    });
}

6.4. Linking / Embedding External Pages

You can very simply add a link to external pages via configuration or even embed them (adding the iframe=true):

spring:
  boot:
    admin:
      ui:
        external-views:
          - label: "🚀"
            url: http://codecentric.de
            order: 2000

6.5. Custom Views

It is possible to add custom views to the ui. The views must be implemented as Vue.js components.

The JavaScript-Bundle and CSS-Stylesheet must be placed on the classpath at /META-INF/spring-boot-admin-server-ui/extensions/{name}/ so the server can pick them up. The spring-boot-admin-sample-custom-ui module contains a sample which has the necessary maven setup to build such a module.

The custom extension registers itself by calling SBA.use() and need to expose a install() function, which is called by the ui when setting up the routes. The install() function receives the following parameters in order to register views and/or callbacks:

If new top level routes are added to the frontend, they also must be known to the backend. Add a /META-INF/spring-boot-admin-server-ui/extensions/{name}/routes.txt with all your new toplevel routes (one route per line).

6.5.1. Adding a Top-Level View

Here is a simple top level view just listing all registered applications:

<template>
  <pre v-text="stringify(applications, null, 4)"/>
</template>

<script>
export default {
  props: {
    applications: { (1)
      type: Array,
      required: true
    }
  },
  methods: {
    stringify: JSON.stringify
  }
};
</script>
1 If you define a applications prop the component will receive all registered applications.
There are some helpful methods on the application and instances object available. Have a look at application.js and instance.js

And this is how you register the top-level view.

SBA.use({
  install({viewRegistry}) {
    viewRegistry.addView({
      name: 'custom',  (1)
      path: '/custom', (2)
      component: custom, (3)
      label: 'Custom', (4)
      order: 1000, (5)
    });
  }
});
1 Name of the view and the route to the view
2 Path where the view will be accessible
3 The imported custom component, which will be rendered on the route.
4 The label for the custom view to be shown in the top navigation bar.
5 Order for the view. Views in the top navigation bar are sorted by ascending order.

The routes.txt config with the added route:

/custom/**

6.5.2. Visualizing a Custom Endpoint

Here is a view to show a custom endpoint:

<template>
  <div class="custom">
    <p>Instance: <span v-text="instance.id" /></p>
    <p>Output: <span v-text="text" /></p>
  </div>
</template>

<script>
  export default {
    props: {
      instance: { (1)
        type: Object,
        required: true
      }
    },
    data: () => ({
      text: ''
    }),
    async created() {
      const response = await this.instance.axios.get('actuator/custom'); (2)
      this.text = response.data;
    }
  };
</script>

<style>
  .custom {
    font-size: 20px;
    width: 80%;
  }
</style>
1 If you define a instance prop the component will receive the instance the view should be rendered for.
2 Each instance has a preconfigured axios instance to access the endpoints with the correct path and headers.

Registering the instance view works like for the top-level view with some additional properties:

SBA.use({
  install({viewRegistry}) {
    viewRegistry.addView({
      name: 'instances/custom',
      parent: 'instances', (1)
      path: 'custom',
      component: customEndpoint,
      label: 'Custom',
      order: 1000,
      isEnabled: ({instance}) => instance.hasEndpoint('custom') (2)
    });
  }
});
1 The parent must be 'instances' in order to render the new custom view for a single instance.
2 If you add a isEnabled callback you can figure out dynamically if the view should be show for the particular instance.

6.6. Customizing Header Logo and Title

You can set custom information in the header (i.e. displaying staging information or company name) by using following configuration properties:

  • spring.boot.admin.ui.brand: This HTML snippet is rendered in navigation header and defaults to <img src="assets/img/icon-spring-boot-admin.svg"><span>Spring Boot Admin</span>. By default it shows the SBA logo followed by it’s name. If you want to show a custom logo you can set: spring.boot.admin.ui.brand=<img src="custom/custom-icon.png">. Either you just add the image to your jar-file in /META-INF/spring-boot-admin-server-ui/ (SBA registers a ResourceHandler for this location by default), or you must ensure yourself that the image gets served correctly (e.g. by registering your own ResourceHandler)

  • spring.boot.admin.ui.title: Use this option to customize the browsers window title.

You can set a custom image to be displayed on the login page.

  1. Put the image in a resource location which is served via http (e.g. /META-INF/spring-boot-admin-server-ui/assets/img/).

  2. Configure the icons to use using the following property:

    • spring.boot.admin.ui.login-icon: Used as icon on login page. (e.g assets/img/custom-login-icon.svg)

6.8. Customizing Favicon

It is possible to use a custom favicon, which is also used for desktop notifications. Spring Boot Admin uses a different icon when one or more application is down.

  1. Put the favicon (.png with at least 192x192 pixels) in a resource location which is served via http (e.g. /META-INF/spring-boot-admin-server-ui/assets/img/).

  2. Configure the icons to use using the following properties:

    • spring.boot.admin.ui.favicon: Used as default icon. (e.g assets/img/custom-favicon.png

    • spring.boot.admin.ui.favicon-danger: Used when one or more service is down. (e.g assets/img/custom-favicon-danger.png)

7. Monitoring Spring Boot 1.5.x

It is possible to monitor Spring Boot 1.5.x applications with Spring Boot Admin 2.x. The old Spring Boot Admin Client is able to register at a newer server. Since the API has slight changes, you need to set the following property on old clients:

  1. Reconfigure the api path for Spring Boot Admin Client 1.5.x:

    application.yml
    spring.boot.admin.api-path: instances

As some of the actuator endpoints changed with the Spring Boot 2 release not all options might be available (e.g. /metrics endpoint); for some of the endpoints we provide legacy converters.

8. Changes with 2.x

  • Added stable automatic-module-name to all jars

8.1. UI

  • Rewritten ui using vue.js

  • Integrated ui-login module into the main ui module

  • Removed ui-activity module, as it was only used rarely

  • Removed Hystrix-Dashboard integration (subject to change)

  • Added support for the session endpoint

  • Added display of the (sanitized) metadata

  • Added option to reset loglevels

  • Added wallboard view

8.2. Backend

  • Moved all classes to the spring.boot.admin.server package

  • Spring cloud related extensions moved to spring-boot-admin-server-cloud.

  • Redesigned backend using event sourcing principles

  • Added concept of applications (consisting of 1 to n instances)

  • Moved endpoint detection to the backend by querying the /actuator-index or by probing via OPTIONS request

  • Replaced Zuul with a custom proxy using the WebClient

  • Removed dependency on spring-cloud-starter

  • Added CompositeHttpHeadersProvider to support multiple HttpHeadersProviders at the same time

  • Added `InstanceExchangeFilterFunction`s which allows to intercept/modify the requests to the monitored instances

  • Added out-of-the-box support for CloudFoundry

  • Added support for Spring Boot 1.5.x actuator endpoints using LegacyEndpointConverters

  • Update OpsGenieNotifier to api v2

  • Rewritten the MailNotifier to use Thymeleaf templates

8.3. Client

  • Moved all properties to spring.boot.admin.client. and spring.boot.admin.client.instance.

  • Moved all classes to the spring.boot.admin.client package

  • Added support webflux applications

  • Added out-of-the-box support for CloudFoundry

9. FAQs

Can I include spring-boot-admin into my business application?

tl;dr You can, but you shouldn’t.
You can set spring.boot.admin.context-path to alter the path where the UI and REST-API is served, but depending on the complexity of your application you might get in trouble. On the other hand in my opinion it makes no sense for an application to monitor itself. In case your application goes down your monitoring tool also does.