Authentication
Secure your Rails Pulse dashboard with your app's existing authentication. On by default outside development and test.
Rails Pulse has no built-in user accounts. You protect the dashboard with your app’s existing authentication, using one of two hooks in the initializer.
Defaults
- Authentication is enabled by default outside development and test. Production, staging, and any custom environment name all require it.
- With nothing configured, Rails Pulse falls back to HTTP Basic against the
RAILS_PULSE_USERNAME(defaultadmin) andRAILS_PULSE_PASSWORDenvironment variables. IfRAILS_PULSE_PASSWORDis unset, every request is denied and a warning is logged. - Both hooks fail closed. If your check does not explicitly allow the request, it is rejected.
To turn authentication off in an environment where you genuinely do not want it:
config.authentication_enabled = !Rails.env.local? # the default: off only in development and test
Recommended: authorize
authorize is a predicate. It receives the controller and returns true to allow. Anything else, including false, nil, or a missing user, is a 403 Forbidden.
# config/initializers/rails_pulse.rb
RailsPulse.configure do |config|
config.authorize = ->(controller) { controller.current_user&.admin? }
end
A zero-argument proc runs in the controller’s context instead, so your app’s helpers are available directly:
RailsPulse.configure do |config|
config.authorize = proc { user_signed_in? && current_user.admin? }
end
Use this for any check that can be expressed as “is this person allowed in?”. It replaces the HTTP Basic fallback on its own.
Devise with an admin role
config.authorize = proc { user_signed_in? && current_user.admin? }
Rails 8 built-in authentication
config.authorize = proc { authenticated? && Current.user.admin? }
IP address restriction
config.authorize = ->(controller) {
allowed = ["127.0.0.1", "::1", "10.0.0.0/8"]
allowed.any? { |ip| IPAddr.new(ip).include?(controller.request.remote_ip) }
}
Redirecting to a login page: authentication_method
If an unauthenticated visitor should be sent to your login page rather than shown a 403, use authentication_method. It runs inside the controller and denies by rendering or redirecting:
# config/initializers/rails_pulse.rb
RailsPulse.configure do |config|
config.authentication_redirect_path = "/login"
config.authentication_method = proc {
unless user_signed_in? && current_user.admin?
redirect_to main_app.root_path, alert: "Access denied"
end
}
end
Rules for this hook:
- Rendering or redirecting denies the request.
- Returning
falsewithout responding is also a denial (403). - Returning
nil, which is whatunless … endreturns on success, allows the request.
Because nil allows, do not write predicate-style checks here. proc { current_user&.admin? } looks right but returns nil for a signed-out visitor and lets them in. Put predicates in authorize.
authentication_redirect_path is where users are sent when the hook raises. Never point it at /rails_pulse or you will create a redirect loop.
Using both
If both are set, authentication_method runs first, then authorize. This lets you redirect anonymous visitors to log in and then apply a stricter role check:
config.authentication_method = proc { redirect_to main_app.new_session_path unless user_signed_in? }
config.authorize = proc { current_user.admin? }
HTTP Basic with your own credentials
The built-in fallback already does this when nothing else is configured. To customise it, use constant-time comparison:
config.authentication_method = proc {
authenticate_or_request_with_http_basic("Rails Pulse") do |username, password|
ActiveSupport::SecurityUtils.secure_compare(username, ENV.fetch("RAILS_PULSE_USERNAME")) &&
ActiveSupport::SecurityUtils.secure_compare(password, ENV.fetch("RAILS_PULSE_PASSWORD"))
end
}
Security Warning: Store credentials in environment variables or Rails credentials. Never commit them to your repository.
What is not covered
- The deployments API (
POST /rails_pulse/deploymentsandPUT /rails_pulse/deployments/finish) uses its own token header and skips dashboard authentication. See Deployment Tracking. The browsable Deployments pages use the dashboard’s authentication like everything else. - The standalone dashboard (
rails_pulse_server) ignoresauthorizeandauthentication_method, because your app’s session helpers are not available in that process. It uses HTTP Basic againstRAILS_PULSE_USERNAME/RAILS_PULSE_PASSWORDunless you setconfig.standalone_authentication_method. See Standalone Dashboard.
Best Practices
- Use
authorizefor predicates andauthentication_methodonly when you need a redirect - Keep the default on for every non-local environment, including staging
- Limit access to administrators. Performance data and exception messages can reveal details about your application
- Combine checks such as a role check plus IP restriction for extra protection
- Never hardcode credentials in your initializer
Next Steps
- Learn about single vs separate database configuration
- Customize thresholds, tagging, and data retention in advanced settings