How do you secure and restrict access to Actuator endpoints in production?
Quick Answer
Restrict which endpoints are exposed over HTTP at all (management.endpoints.web.exposure.include should list only what's genuinely needed, not '*'), require authentication/authorization for anything beyond a minimal health check (integrating Actuator's endpoints into the application's own Spring Security configuration, or securing them at the infrastructure/network level), and strongly consider running Actuator on a separate management port (management.server.port) that isn't exposed to the public internet at all, only reachable from an internal network/monitoring system.
Detailed Answer
Actuator's endpoints are extremely useful operationally, but several of them expose genuinely sensitive information (environment variables, full heap dumps, every registered bean and route) or dangerous capabilities (a /actuator/shutdown endpoint, if enabled, literally terminates the application) — leaving them broadly exposed and unsecured in production is a real, recurring source of security incidents.
1. Restrict exposure to only what's genuinely needed. Never set management.endpoints.web.exposure.include=* in a production configuration — enumerate specifically what monitoring actually requires:
management.endpoints.web.exposure.include=health,info,metrics,prometheus
management.endpoint.health.show-details=when-authorized
show-details=when-authorized additionally prevents even the /health endpoint from revealing granular per-indicator detail (which downstream dependency specifically failed, for instance) to unauthenticated callers, exposing only the minimal aggregated UP/DOWN status publicly.
2. Require authentication/authorization for anything beyond a minimal health check. Actuator endpoints are just ordinary Spring MVC-style endpoints from Spring Security's perspective, and can be secured the same way any other endpoint would be:
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(auth -> auth
.requestMatchers("/actuator/health", "/actuator/info").permitAll()
.requestMatchers("/actuator/**").hasRole("ACTUATOR_ADMIN") // everything else requires this role
.anyRequest().authenticated());
return http.build();
}
3. Run Actuator on a separate management port, isolated at the network level. Spring Boot supports exposing management endpoints on an entirely different port from the main application:
management.server.port=9001
Combined with network-level controls (a firewall rule, a Kubernetes NetworkPolicy, or simply not exposing that port through the load balancer/ingress at all), this means Actuator's more sensitive endpoints are only reachable from an internal network — a monitoring system or an operator on a VPN — never from the public internet at all, which is a meaningfully stronger guarantee than relying purely on application-level authentication (defense in depth: even a misconfigured security rule can't accidentally expose it publicly if the network path itself doesn't exist).
4. Explicitly disable genuinely dangerous endpoints if they're not needed — /actuator/shutdown in particular should essentially never be exposed in a production environment; if it's not deliberately, carefully secured and truly needed, it shouldn't be enabled at all.
In combination: the strongest, most common production posture is "narrow the exposed endpoint list to what's needed → put anything sensitive behind authentication → run it on a separate, network-isolated management port" — relying on just one of these three layers alone leaves a real gap the others would have covered.